前言
机器学习中用数据训练模型的目标: 最小化目标函数
目标函数通常可以分为两部分:
(1)损失函数(经验风险):与训练任务有关,度量模型预测值与真值之间的差异,最小化用于选择与训练数据匹配最好的模型:
回归:与残差相关的函数,包括MSE(L2损失),MAE(L1损失),Huber Loss,平滑的MSE等;
分类:与分类是否正确(或分类正确的概率)有关的的函数:0-1损失,负对数似然损失,Hinge损失等
(2)正则项(结构风险):与模型复杂度有关(选择最简单的模型)
L1正则(因约束表面为“立方体”表面,由于角更突出,角与目标函数相交的概率更大,使不显著的参数为0,变为稀疏模型),L2正则,Elastic net等。
下图为参数模型的目标函数
补充:
非线性模型:
(1)基函数:x^2、 log、 exp、样条函数、树…
(2)核化:将原问题转化为对偶问题,将对偶问题中的向量点积<xi, xj>换成核函数k(xi, xj)
(2)施加非线性变换:如(深度)神经网络中对输入的线性组合再施加非线性**函数,然后再多层叠加
分类回归树
Classification And Regression Tree (CART):用于监督学习的非参数模型,二分递归分割:将当前样本集合划分为两个子样本集合,使得生成的每个非叶子结点都有两个分支(生成的树为二叉树)
模型:树模型(非参数模型的一种)
参数:用于分裂的特征(及阈值,若为定量特征)
目标函数:
(1)损失函数:MSE(回归)/GINI指数(分类)
(2)正则项:树的节点数目、叶子结点分数平方和注:树模型很容易过拟合,所以很多策略都是在防止模型过拟合,如限制树的高度,提前终止,剪枝, Bagging…
CART算法步骤:
1.将样本递归划分进行自顶向下的递归建树,使经验损失最小
递归停止的条件:
(1)分裂带来的损失的减小太小
(2)树的深度超过了最大深度
(3)左/右分支的样本分布足够纯净
(4) 左/右分支中样本数目足够少
2.分类回归树算法容易过拟合,给定一个完全树用验证数据自底向上进行剪枝,正则:减小模型复杂度 (节点数目)
树模型的优点:
(1)容易解释
(2)不要求对特征做预处理
– 能处理离散值和连续值混合的输入
– 对特征的单调变换不敏感 (只与数据的排序有关)
– 能自动进行特征选择
– 可处理缺失数据
(3)可扩展到大数据规模
Adaptive Boost(Adaboost)
Boosting方法:将弱学习器组合成强学习器,常用的弱学习器有决策树(用于分类,每个叶子节点对应一个决策),分类回归树(用于回归,每个叶子节点对应一个预测值)
基本思想:对当前分类器不能处理的样本,下一次迭代中增加其权重,不断加入新的弱学习器,直至到达终止条件,最终模型为弱学习器的加权线性组合,权重与其正确率有关,迭代的过程使用指数损失函数(损失函数取负log似然损失,得到
logitBoost.,对回归问题,损失函数可取L2损失,得到L2boosting)
具体步骤:
Gradient Boost
基本思想:根据当前模型损失函数的负梯度信息来训练新加入的弱分类器,然后将训练好的弱分类器以累加的形式结合到现有的模型中,相对于AdaBoost仅适用指数损失函数,GBM使得我们可以使用任何可微的损失函数,从而支持的任务从两分类扩展到回归和多类分类问题。
具体步骤:在每一轮迭代中,首先计算出当前模型在所有样本上的负梯度,然后以该值为目标训练一个新的弱学习器进行拟合负梯度,并计算出该弱学习器的权重,最终实现对模型的更新。
更新时可考虑增加一个收缩因子(shrinkage),较小的收缩因子意味着更多的弱学习器(取值在0-1之间):
注意:梯度提升与梯度下降算法的联系与区别:
联系:梯度表示目标函数在某个点的位置法向量,表示函数下降最快或者上升最快的方向,两者都是在每一轮迭代中,利用损失函数相对于模型的负梯度方向的信息来对当前模型进行更新
区别:梯度下降中模型一般以参数化形式表示,确定模型后,模型训练转化为求解模型参数,模型更新等价于参数更新,而梯度提升一般直接定义在函数空间中(树模型)
XGBoost
GBM基于经验损失函数的负梯度来构造新的学习器(决策树),在决策树构建完成以后进行剪枝,XGB在决策树构建前加入了显式的正则项(限制叶子的预测值大小及叶子个数),控制模型的复杂度,有利于防止过拟合,从而提高模型的泛化能力;同时XGBoost对目标函数进行二阶泰勒展开,优化求解时,需要目标函数对预测函数f 的一阶导数和二阶导数。
理论推导如下:
损失函数的二阶近似:
XGB中的基学习器----树:
那么树的复杂度可定义为与叶子节点的数目,叶子节点的分数的L2成正比:
故得到XGB的目标函数推导如下:
假设树的结构q已知,那么目标函数为:
故结构q已知的情况下,可通过目标函数关于新树的一阶二阶梯度最小化得到新树叶子节点的分数。
贪心算法建树:相对于穷举可能的树结构q,我们在实践中会贪心地增加叶子节点的数目
注意:XGBoost并行处理,运行速度快,且内置交叉验证,允许在每一轮boosting迭代中使用交叉验证,可以方便地获得最优boosting迭代次数
Python实现XGB
数据分析的一般步骤:
XGB的简单实现:
(1)导入必要的库
import xgboost as xgb
from sklearn.metrics import accuracy_score
(2)将数据从文件中读入内存,并利用xgb.DMatrix将其格式化,改格式有着存储效率和运行速度的优化:
# 设置数据路径,数据在xgbboost安装的路径下的demo目录
# read in data,训练集和测试集
my_workpath = ‘./data/’
dtrain = xgb.DMatrix(my_workpath +'train.pkl')
dtest = xgb.DMatrix(my_workpath +'test.pkl')
注意:XGBoost 模型内部将所有的问题都建模成一个回归预测问题,输入特征只能是数值型。如果给定的数据是不同的类型,必须先将数据变成数值型(类别型特征的OneHotEncoder,文本特征的n-gram后的TFIDF等)
(3)设置训练参数:
max_depth: 树的最大深度。缺省值为6,取值范围为:[1,∞];
eta:为了防止过拟合,更新过程中用到的收缩步长。 eta通过缩减特征的权重使提升计算过程更加保守。缺省值为0.3,取值范围为:[0,1];
silent: 0表示打印出运行时信息,取1时表示以缄默方式运行,不打印运行时信息。缺省值为0;
objective: 定义学习任务及相应的学习目标,“binary:logistic” 表示二分类的逻辑回归问题,输出为概率。'multi:softmax’表示多分类,输出为预测类别,'multi:softprob’为各个分类的指数归一化预测概率,输出的是ndata * nclass的向量,可以将该向量
reshape成ndata行nclass列的矩阵。每行数据表示样本所属于每个类别的概率;
subsample:构造每棵树的所用样本比例;
# specify parameters via map
param = {'max_depth':2, 'eta':1, 'silent':0, 'objective':'binary:logistic' }
(4)模型训练
# 设置boosting迭代计算次数
num_round =300
bst = xgb.train(param, dtrain, num_round)
(5)预测(以二分类为例)
# make prediction
preds = bst.predict(dtest)
predictions = [round(value) for value in preds]
y_test = dtest.get_label()
test_accuracy = accuracy_score(y_test, predictions)
print("Test Accuracy: %.2f%%" % (test_accuracy * 100.0))
k折交叉验证:将训练数据等分成k份(k通常的取值为3、 5或10),重复k次,每次留出1份做校验,其余k-1份用于训练,次校验集上的平均性能视为模型在测试集上性能的估计。考虑到类别不平衡问题,对回归问题,采用10-fold cross-validation ; 对分类,采用stratified 10-fold cross-validation。下为Python中对模型model进行k折交叉验证的简单实现:
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score #对给定参数的单个模型评估
kfold = KFold(n_splits=10, random_state=7)
results = cross_val_score(model, X, Y, cv=kfold)
print("Accuracy: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
参数调优:根据交叉验证评估的结
果,选择最佳参数的模型输入待调节参数的范围(grid),对一组参数对应的模型进行评估,根据返回的结果得到最佳模型及其参数
from sklearn.grid_search import GridSearchCV
# 设置boosting迭代计算次数搜索范围
param_test = { 'n_estimators': range(1, 51, 1)}
clf = GridSearchCV(estimator = bst, param_grid = param_test, cv=5)
clf.fit(X_train, y_train)
clf.grid_scores_, clf.best_params_, clf.best_score_
特征重要性:从训练好的预测模型得到特征的重要性,单棵树中的特征重要性:每个特征分裂点对性能的提升量,并用每个结点的样本数加权,整个模型中的特征重要性:模型中每棵树的平均。
from matplotlib import
pyplotpyplot.bar(range(len(model_XGB.feature_importances_)),
model_XGB.feature_importances_)
XGB参数调优的一般方法
1.选择较高的学习率(learning rate),并选择对应于此学习率
的理想的树数量(XGBoost直接引用函数“cv”可以在每一次迭代中使用交叉验证,并返回理想的树数量)
2. 对于给定的学习率和树数量,进行树参数调优(max_depth,min_child_weight, gamma, subsample, colsample_bytree, colsample_bylevel)
3. xgboost的正则化参数(lambda, alpha)的调优
4. 4. 降低学习率,确定理想参数
参考文献:Chen T , Guestrin C . XGBoost: A Scalable Tree Boosting System[J]. 2016.