目录
5.1 线性模型
5.1.1 Lasso回归
5.1.2 Ridge回归
5.2 树模型
5.2.1 随机森林
随机森林的优缺点
5.2.2 梯度提升树
5.2.3 XGBoost
5.2.4 LightGBM
5.2.5 CatBoost
5.2.6 模型深入对比
5.3 神经网络
5.4 实战案例
XGBoost
多层感知机
5.5 思考练习
Lasso回归,是对普通的线性回归采用L1正则化进行优化,通过乘法或限制估计值的绝对值之和,可以使某些系数为零,从而达到特征稀疏化和特征选择的效果。
当我们需要一些自动的特征、变量选择,或者处理高度相关的预测因素时,很方便。
代码实现:
from sklearn.linear_model import Ridge, Lasso
lasso_model = Lasso(alpha = 0.1, normalize = True)
只保留不相关的特征,其他为0,可能会导致信息损失
L2正则化
代码实现:
from sklearn.linear_model import Ridge, Lasso
ridge_model = Ridge(alpha = 0.05, normalize = True)
不会减少特征数量,不利于特征缩减。
两者合并:Elastic Net Regression
本节将介绍竞赛中常见的树模型,这些模型简单易用,能够带来高收益。
可将树模型分为随机森林(Random Forest, RF)和梯度提升树(GBDT), 这两者最大的差异是前者并行、后者串行。在梯度提升树部分我们将介绍如今竞赛中大火的三种树模型: XGBoost、 LightGBM 和CatBoost。能够灵活运用这三种模型是竞赛中的必备技能。接下来将详细介绍各种树模型的数学形式、优缺点、使用细节和应用场景。
机器学习面试笔试知识点-决策树、随机森林、梯度提升决策树(GBDT)、XGBoost、LightGBM、CatBoost - 知乎
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(max_ features=' auto', oob_ score=True, random state=1, n_ jobs=-1)
梯度提升树(GBDT)是基于Boosting 改进而得的,在Boosting 算法中,一系列基学习器都需要串行生成,每次学习一棵树,学习目标是上棵树的残差。和AdaBoost 一样,梯度提升树也是基于梯度下降函数。梯度提升树算法已被证明是Boosting算法集合中最成熟的算法之一,它的特点是估计方差增加,对数据中的噪声更敏感(这两个问题都可以通过使用子采样来减弱),以及由于非并行操作而导致计算成本显著,因此要比随机森林慢很多。
梯度提升树作为XGBoost、LightGBM 和CatBoost的基础,这里将对其原理进行简单介绍。我们知道梯度提升树是关于Boosting的加法模型,由K个模型组合而成,其形式如式:
一般而言,损失函数描述的是预测值与真实值之间的关系,梯度提升树是基于残差为前一个模型)来不断拟合训练集的,这里使用平方损失函数。那么对于n个样本来说,则可以写成式:
进一步,
其中代表基模型的复杂度,若基模型是树模型,则树的深度、叶子节点数等指标均可以反映树的复杂度。
对于Boosting来说,它采用的是前向优化算法,即从前往后逐渐建立基模型来逼近目标函数,具体过程如:
主要特点
代码实现:
import xgboost as xgb
params = {'eta': 0.01, ' max depth': 11, 'objective': 'reg:linear', 'eval_ metric': 'rmse' }
dtrain = xgb.DMatrix(data=X_train, label=y_train)
dtest = xgb.DMatrix(data=X_valid, label=y_valid)
watchlist = [(train.data, 'train'), (valid_data, 'valid_ data')]
model=xgb. train(params, train_data,num_boost_round=20000,evals=watchlist,early_stopping_rounds=200,verbose_eval=500)
y_pred = model. predict(xgb .DMatrix(X_test), ntree_limit=model.best_ntree_limit)
LightGBM是微软的一个团队在Github上开发的一个开源项目,高性能的LightGBM算法具有分布式和可以快速处理大量数据的特点。LightGBM虽然基于决策树和XGBoost而生,但它还遵循其他不同的策略。
XGBoost使用决策树对一个变量进行拆分,并在该变量上探索不同的切割点(按级别划分的树生长策略),而LightGBM则专注于按叶子节点进行拆分,以便获得更好的拟合(这是按叶划分的树生长策略)。这使得LightGBM能够快速获得很好的数据拟合,并生成能够替代XGBoost的解决方案。从算法上讲,XGBoost将决策树所进行的分割结构作为一个图来计算,使用广度优先搜索(BFS),而LightGBM使用的是深度优先搜索(DFS)。
主要特点
代码实现
import lightgbm as lgb
params = {'num_leaves': 54, 'objective': 'regression', 'max_depth': 18,'learning_rate': 0.01, 'boosting': 'gbdt', 'metric': 'rmse', 'lambda_11': 0.1}
model = lgb.LGBMRegressor(**params, n_estimators = 20000, nthread = 4, n_jobs = -1)
model.fit(x_train, y_train, eval_set=[(X_train, y_train), (X_valid, y_valid)], eval_metric='rmse', verbose=1000, early_stopping_rounds=200)
y_pred= model.predict(X_test, num_iteration=model.best_iteration_)
CatBoost是由俄罗斯搜索引擎Yandex在2017年7月开源的一个GBM算法,它最强大的点是能够采用将独热编码和平均编码混合的策略来处理类别特征。
CatBoost用来对类别特征进行编码的方法并不是新方法,是均值编码,该方法已经成为一种特征工程方法,被广泛应用于各种数据科学竞赛中,如Kaggle。
均值编码,也称为似然编码、影响编码或目标编码,可将标签转换为基于它们的数字,并与目标变量相关联。如果是回归问题,则基于级别典型的平均目标值转换标签;如果是分类问题,则仅给定标签的目标分类概率(目标概率取决于每个类别值)。均值编码可能看起来只是一个简单而聪明的特征工程技巧,但实际上它也有副作用,主要是过拟合,因为会把目标信息带入预测中。
主要特点
代码实现:
from catboost import CatBoostRegressor
params = {'learning_rate': 0.02, 'depth': 13,'bootstrap_type': 'Bernoulli', 'od_type': 'Iter', 'od_wait': 50, 'random_seed': 11}
model = CatBoostRegressor(iterations=20000, eval_metric='RMSE', **params)
model.fit(X_train, y_train, eval_set=(X_valid, y_valid), cat_features=[], use_best_model=True, verbose=False)
y_pred = model.predict(X_test)
每类树模型都其与众不同的地方,接下来将从决策树的生长策略、梯度偏差、类别特征处理和参数对比四个方面深入理解这些树模型,帮助参赛者更好地将它们应用到竞赛中。
更多功能
CatBoost目前还支持输入文本特征,因此不需要像以前那样先进行烦琐的操作获得标准化输入,再喂给模型。
文本特征跟类别特征的标记方式一样,只需在训练时把文本变量名的列表赋给text_features 即可。
那么CatBoost内部是怎么处理文本特征的呢?
操作其实非常常规,CatBoost内部将输入的文本特征转化为了数值特征,具体过程是分词、创建字典、将文本特征转化为多值的数值特征,接下来的处理方法可选择项就比较多了,比如完全展开成布尔型0/1特征,或者进行词频统计。
XGBoost,LightGBM 和 CatBoost是三个非常核心的树模型,本节将对它们进行分析,因为三者之间有着千丝万缕的关系,只有厘清其中的关系,才能更好地运用这三个模型。
(1)决策树生长策略
(2)梯度偏差(Gradient bias)
(3)类别特征处理
具体实现流程是首先对输入的样本集随机排序,然后针对类别特征中的某个取值,在将每个样本的该特征转换为数值型时,都基于排在该样本之前的类别标签取均值。对所有的类别特征值结果都进行如式(5-10)所示的运算,使之转化为数值结果,
(4)参数对比
如图5.3所示,从三个方面对树模型的参数进行对比,分别是用于控制过拟合、用于控制训练速度和调整类别特征的三类参数。这里只是枚举一些重要的参数,还有大量有用的参数就不一一进行介绍了。
参数作用\树模型 | XGBoost | LightGBM | CatBoost |
用于控制过拟合的参数 | 1.learning_rate/eta:减少每一步的权重(Shinkage方法)、一般在0.01和0.2之间 2.max_depth:树分裂的最大深度 3.min_child_weight:默认为1;最小叶子节点样本权重和 |
1.learning_rate:学习率 2.max_depth:默认为20;树的最大深度;另外 num_leaves=2^(max_depth),表示最大叶节点个数 3.min_data_in_leaf:默认为20,每个叶子节点对应最小数据量 |
1.learning_rate:学习率 3.没有与min_child_weight类似的参数 |
用于控制训练 速度的参数 |
1.colsample_bytree:随机列采样的比例 2.subsample:随机样本采样的比例 3.n_estimators:决策树的最大数量,越高的值有可能导致过拟合 |
1.feature_fraction:每次代随机列采样比例 2.bagging_fraction:每次迭代随机样本采样比例 3.num_iterations:默认为100,选代次数 |
1.rsm:随机子空间,每次分裂选择的特征比例 2.没有与样本采样类似的参数 3.iterations:树能够建立的最大数量 |
调整类别特征的参数 | 没有这类参数 | 1.categorical_feature:对应类别特征的位置索引 | 1.cat_features:对应类别特征的位置索引 2.one_hot_max_size:用来限制ont-hot特征向量的长度,默认为False |
略
本节仅需选择多个模型运行出结果即可,上文给出的模型并不完整,这里也将添加验证方式,让结果变得更加可靠。对于多个模型的结果可以对比着进行分析,以助模型融合部分的优化。
#接第5章实战案例代码,构造训练集和测试集
x_train = data[:ntrain][all_cols]
x_test = data[ntrain:][all_cols]
#对售价进行log处理
y_train = np.loglp(data[data.SalePrice.notnull()]['SalePrice'].values)
这里使用比较常规的五折交叉验证,
import xgboost as xgb
from sklearn.model_selection import KFold
kf = KFold(n_splits=5,shuffle=True,random_state=2020)
for i,(train_index,valid_index)in enumerate(kf.split(x_train,y_train)):
trn_x,trn_y,val_x,val_y = x_train.iloc[train_index],y_train[train_index],x_train.iloc[valid_index],y_train[valid_index]
params ={'eta':0.01,'max_depth':11,'objective':'reg:linear','eval_metric':'mae'}
dtrain = xgb.DMatrix(data=trn_x,label=trn_y)
dtest = xgb.DMatrix(data=val_x,label=val_y)
watchlist =[(dtrain,'train'),(dtest,'valid_data')]
model=xgb.train(params,dtrain,num_boost_round=20000,evals=watchlist,early_stopping_rounds=200,verbose_eval=500)
from sklearn. model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
x_train = x_train. fillna(0)
x_train = StandardScaler(). fit_transform(x_train)
trn_x, val_x, trny, val_y = train_test_split(
x_train, y_train, random_state=2020)
def create_mlp(shape):
x_input = Input((shape, ))
X = Dropout(0.2)(BatchNormalization()(
Dense(256, activation=' relu')(X_input)))
X = Dropout(0.2)(BatchNormalization()(Dense(128, activation=' relu')(X)))
X = Dropout(0.2)(BatchNormalization()(Dense(64, activation=' relu')(X)))
X = Dense(1)(X)
model = Model(inputs=X_input, outputs=X)
model. compile(optimizer=' adam', loss=' mse', metrics=[' mae'])
return model
mlp_model = create_mlp(trn_x. shape[1])
mlp_model. fit(x=trn_x, y=trn_y, validation_data=(
val_x, val_y), epochs=30, batch_size=16)
目前为止给出的模型都是比较容易实现的,这有助于快速反馈出结果。对比XGBoost(结果取对数后平均绝对误差:0.08x)和多层感知机(平均绝对误差:0.21x)的线下结果,发现后者的效果差了很多,2000多条的训练数据很难让多层感知机取得一个较好的结果。
1.在Lasso回归和Ridge回归部分,我们知道L1和L2能够减少过拟合的风险,那这个参数究竟取多大合适?
2.树模型在分裂的时候其实可以看着特征的交叉组合阶段,那么还有必要构造交叉特征喂人树模型吗?
3.本章介绍了树模型的核心参数,还有很多没有介绍到,请尝试分析参数之间的关系,以及具体参数在算法中的哪个步骤中出现,加深对参数的理解。
4.常用的激活函数还是蛮多的,在进行深度学习相关模型训练时,不同的激活函数对于结果的影响还是蛮大的,尝试整理 sigmoid,tanh,ReLU,leaky ReLU,SELU 和 GELU 等激活函数的优缺点以及适用场景,