机器学习经典赛题:工业蒸汽量预测(3)
机器学习经典赛题:工业蒸汽量预测(3)
4.模型训练
4.1 回归及相关模型
4.1.1 回归的概念
回归是一种来自统计的技术,用于在目标数量连续时预测所需目标数量的值。通过房屋面积来预测房屋的价格就是一个典型的回归问题,如下图所示:
 
4.1.2 回归模型训练和预测
回归模型训练和预测的步骤:
 (1)导入需要的工具库。
 (2)对数据预处理,包括导入数据集、处理数据、特征工程等操作,具体为缺失值处理、连续型特征归一化、类别型特征转化等。
 (3)训练模型。选择合适的机器学习模型,利用训练集对模型进行训练,达到最佳拟合效果。
 (4)预测结果。将待预测的数据集输入到训练好的模型中,得到预测结果。
4.1.3 线性回归模型
假定因变量
    
     
      
       
        Y
       
      
      
       Y
      
     
    Y与自变量
    
     
      
       
        X
       
      
      
       X
      
     
    X呈线性相关,则可以采用线性模型找出自变量
    
     
      
       
        X
       
      
      
       X
      
     
    X和因变量
    
     
      
       
        Y
       
      
      
       Y
      
     
    Y的关系,以便预测新的自变量
    
     
      
       
        X
       
      
      
       X
      
     
    X的值,这就是线性回归模型。
- 一元线性回归模型
一元线性回归模型使用单一特征来预测目标变量,拟合的最佳曲线通过最小化预测值和真实值之间的误差得到。

 - 多元线性回归模型
多元线性回归模型是利用多个自变量估计因变量,从而解释和预测因变量的值。多元线性回归模型的一般形式:
y = β 0 + β 1 x 1 + β 2 x 2 + . . . + β p x p + ϵ y=\beta_0 + \beta_1x_1+\beta_2x_2+...+\beta_px_p+\epsilon y=β0+β1x1+β2x2+...+βpxp+ϵ
写成矩阵形式为 y = x β + ϵ y=x\beta+\epsilon y=xβ+ϵ,其中,

例如,商品的销售额可能与电视、收音机、报纸的广告投入都有关系,因此可以建立如下模型:
s a l e s = β 0 + β 1 ∗ T V + β 2 ∗ r a d i o + β 3 ∗ n e w s p a p e r sales=\beta_0+\beta_1 * TV +\beta_2 * radio + \beta_3 * newspaper sales=β0+β1∗TV+β2∗radio+β3∗newspaper - 线性回归调用方法
首先是在特征工程之后,需要对数据集进行切分: 
from sklearn.model_selection import train_test_split
new_test_pca_16 = new_test_pca_16.fillna(0)
train = new_train_pca_16[new_test_pca_16.columns]
target = new_train_pca_16['target']
# 切分数据,训练数据为80%,验证数据为20%
train_data, test_data, train_target, test_target = train_test_split(train, target, test_size=0.2, random_state=0)
 
然后,模型训练的基本套路如下:
 1)导入对于的模型类 from sklearn.xxx import xxx
 2)获取对于模型类的对象 xx = xxx()
 3)用数据去训练模型(训练模型参数) xx.fit(data,target)或xx.fit_transform(train_data,train_target)。后者(fit_transform)是在前者的基础上增加了数据处理(特征工程等一些方法)
 4)使用训练好的模型(对象)去对测试数据进行预测或分类 xx.predict(test_data)
 5)通过各种评价指标计算得分 score = xyz(test_target,predict)
这里使用sklearn调用线性回归模型进行预测:
from sklearn.metrics import mean_squared_error  # 评价指标
# 从sklearn库中导入线性回归模型
from sklearn.linear_model import LinearRegression
clf = LinearRegression()
clf.fit(train_data, train_target)
test_predict = clf.predict(test_data)
score = mean_squared_error(test_target, test_predict)
print("LinearRegression:  ", score)
# LinearRegression:   0.14565628375662207
 
4.1.4 K近邻回归模型
- K近邻回归模型
K近邻算法不仅可以用来分类,还可以用于回归。通过找出某个样本的K个最近邻居,将这些邻居的某个(些)属性的平均值赋给该样本,就可以得到该样本对应属性的值。 - K近邻回归调用方法
如何才能知道哪些数据样本最相近呢?设有两个点 P P P和 Q Q Q其中
P = p 1 , p 2 , p 3 , . . . , p n , Q = q 1 , q 2 , q 3 , . . . , q n P = p_1,p_2,p_3,...,p_n, Q=q_1,q_2,q_3,...,q_n P=p1,p2,p3,...,pn,Q=q1,q2,q3,...,qn
那么P与Q之间的距离表示为 d d d,则根据欧式距离公式如下所示。
d = ( p 1 − q 1 ) 2 + ( p 2 − q 2 ) 2 + . . . + ( p n − q n ) 2 d=\sqrt{(p_1-q_1)^2+(p_2-q_2)^2+...+(p_n-q_n)^2} d=(p1−q1)2+(p2−q2)2+...+(pn−qn)2
使用sklearn调用K近邻回归算法进行预测: 
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error
scores = []
for i in range(1, 10):
    knf = KNeighborsRegressor(n_neighbors=i)
    knf.fit(train_data, train_target)
    test_predict = knf.predict(test_data)
    score = mean_squared_error(test_target, test_predict)
    scores.append(score)
plt.figure(figsize=(13, 8))
plt.plot(range(1, 10), scores)
plt.title('KNeighborsRegressor K-MSE')
plt.xlabel('k')
plt.ylabel('MSE score')
 

4.1.5 决策树回归模型
- 决策树回归模型介绍
决策树回归可以理解为根据一定准则(评估方式),将一个空间划分为若干个子空间,然后利用子空间内所有点的信息表示这个子空间的值。 - 决策树回归模型举例
略 - 决策树回归调用方法
 
from sklearn.tree import DecisionTreeRegressor
DTR = DecisionTreeRegressor()
DTR.fit(train_data, train_target)
test_pred = DTR.predict(test_data)
score = mean_squared_error(test_target, test_pred)
print("DecisionTreeRegressor", score)
# DecisionTreeRegressor 0.3483485778546713
 
4.1.6 集成学习回归模型
- 随机森林回归模型
随机森林就是通过集成学习的思想将多棵树集成的一种算法,基本单元是决策树,而它的本质属于机器学习的一个分支——集成学习(Ensemble Learning)。
随机森林回归模型的主要优点:在当前所有算法中,具有极好的准确率;能够有效地运行在大数据集上;能够处理具有高维特征的输入样本,而且不需要降维;能够评估各个特征在分类问题上的重要性;在生成过程中,能够获取到内部生成误差的一种无偏估计;对于缺省值问题也能够获得很好的结果。
使用sklearn调用随机森林回归树算法进行预测: 
from sklearn.ensemble import RandomForestRegressor
clf = RandomForestRegressor(n_estimators=200)  # 200棵树模型
clf.fit(train_data, train_target)
test_predict = clf.predict(test_data)
score = mean_squared_error(test_target, clf.predict(test_data))
print('RandomForestRegressor score', score)
# RandomForestRegressor score 0.1669636684508218
 
- LightGBM回归模型
LightGBM是2017年由微软推出的可扩展机器学习系统,是微软旗下DMKT的一个开源项目,由2014年首届阿里巴巴大数据竞赛获胜者之一柯国霖老师带领开发。它是一款基于GBDT(梯度提升决策树)算法的分布式梯度提升框架,为了满足缩短模型计算时间的需求, 
LightGBM的设计思路主要集中在减小数据对内存与计算性能的使用,以及减少多机器并行计算时的通讯代价。
LightGBM可以看作是XGBoost的升级豪华版,在获得与XGBoost近似精度的同时,又提供了更快的训练速度与更少的内存消耗。
 LightGBM的主要优点:
- 简单易用。提供了主流的Python\C++\R语言接口,用户可以轻松使用LightGBM建模并获得相当不错的效果。
 - 高效可扩展。在处理大规模数据集时高效迅速、高准确度,对内存等硬件资源要求不高。
 - 鲁棒性强。相较于深度学习模型不需要精细调参便能取得近似的效果。
 - LightGBM直接支持缺失值与类别特征,无需对数据额外进行特殊处理
 
LightGBM的主要缺点:
- 相对于深度学习模型无法对时空位置建模,不能很好地捕获图像、语音、文本等高维数据。
 - 在拥有海量训练数据,并能找到合适的深度学习模型时,深度学习的精度可以遥遥领先LightGBM。
 
LightGBM核心超参数:
- task,指定任务,可选train,predict等。
 - boosting_type,提升方法,可选gbdt、rf等。
 - objective,目标(函数),如果是回归任务,可l2、l1、huber、quantile等;如果是分类任务,可选binary、multiclass等。
 - max_depth,树的最大深度,控制过拟合的有效手段。
 - num_leaves,树的最大叶子节点数。
 - feature_fraction,特征的随机采样率,指
 - bagging_fraction,样本的随机采样率
 - bagging_freq,是否启用bagging并设置迭代轮次,如启用,上述的特征与样本的的随机采样需要设置。
 - learning_rate,学习率
 - lambda_l1,L1正则化
 - lambda_l2,L2正则化
 
LightGBM优化:
- 基于Histogram的决策树算法
 - 带深度限制的Leaf_wise的叶子生长策略
 - 直方图做差加速
 - 直接支持分类特征
 - Cache命中率优化
 - 基于直方图的稀疏特征优化
 - 多线程优化
 
1. Histogram算法
 直方图算法的基本思想是先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。在遍历数据的时候,根据离散化的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。
 
 使用直方图算法有很多优点。首先,最明显就是内存消耗的降低,直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用 8 位整型存储就足够了,内存消耗可以降低为原来的1/8。
 
 然后在计算上的代价也大幅降低,预排序算法每遍历一个特征就要计算一次分裂增益,而直方图算法只需要计算k次(k可以认为是常数),时间复杂度从O(#datafeature)优化到O(K#features).
但是,Histogram算法并不是完美的。由于特征被离散化后。找到的并不是很精确的分割点,所以会对结果产生影响。但在不同的数据集上的结果表明,离散化的分割点对最终的精度影响并不是很大,甚至有时候会更好一点。
2. 带深度限制的Leaf_wise的叶子生长策略
 在 Histogram 算法之上,LightGBM 进行进一步的优化。首先它抛弃了大多数 GBDT 工具使用的按层生长 (level-wise) 的决策树生长策略,而使用了带有深度限制的按叶子生长 (leaf-wise) 算法。Level-wise 过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上 Level-wise 是一种低效的算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
 
 Leaf-wist则是一种更高效的策略,每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最深度的限制,在保证高效率的同时防止过拟合。
 
 3. 直方图加速
 LightGBM另一个优化是Histogram做差加速。一个观察到的现象:一个叶子的直方图可以由它的父节点的直方图与它兄弟的直方图做差得到。通常构造直方图,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的K个桶。利用这个方法,LightGBM可以在构造一个叶子的直方图后,可以用非常微小的代价得到它兄弟叶子的直方图,在速度上可以提升一倍。
 
 4. 直接支持类别特征
 实际上大多数机器学习工具都无法直接支持类别特征,一般需要把类别特征,转化到多维的0/1特征,降低了空间和时间的效率。而类别特征的使用是在实践中很常用的。基于这个考虑,LightGBM优化了对类别特征的支持,可以直接输入类别特征,不需要额外的0/1展开。并在决策树算法上增加了类别特征的决策规则。
5. LightGBM并行优化
 LightGBM还具有支持高效并行的优点。LightGBM原生支持并行学习,目前支持特征并行和数据并行的两种。
- 特征并行的主要思想是在不同机器在不同的特征集合上分别寻找最优的分割点,然后在机器间同步最优的分割点。

 - 数据并行则是让不同的机器先在本地构造直方图,然后进行全局合并,最后在合并的直方图上面寻找最优分割点。

 - 并行优化:基于投票的并行

 
- 其他常用模型
弹性网络(Elastic Net)回归是在参数空间中对L1和L2范数进行正则化的线性回归模型,可以理解为岭回归和Lasso回归的结合,其主要用在正则化融合的技术中。 
SVR(Support Vector Regression)是支持向量机在线性回归模型中的应用。支持向量机主要用于分类。这类模型的优势在采用核函数后,可以自动升维拟合,提高拟合效果,并且参数计算量并没有增加。
4.2 模型训练实战
4.2.1 导入相关库
from sklearn.neighbors import KNeighborsRegressor  # K近邻回归
from sklearn.linear_model import LinearRegression  # 线性回归
from sklearn.tree import DecisionTreeRegressor  # 决策树回归
from sklearn.ensemble import RandomForestRegressor  # 随机森林
from sklearn.svm import SVR  #支持向量回归
import lightgbm as lgb  # LightGBM模型
from sklearn.metrics import mean_squared_error  # 评价指标 MSE
from sklearn.model_selection import train_test_split  # 数据集切分
from sklearn.model_selection import learning_curve
from sklearn.model_selection import ShuffleSplit
 
4.2.2 切分数据
对训练集进行切分,得到80%的训练数据和20%验证数据:
# 采用PCA保留16维特征的数据
new_test_pca_16 = new_test_pca_16.fillna(0)
train = new_train_pca_16[new_test_pca_16.columns]
target = new_train_pca_16['target']
# 切分数据,训练数据为80%,验证数据为20%
train_data, test_data, train_target, test_target = train_test_split(train, target, test_size=0.2, random_state=0)
 
4.2.3 多元线性回归
clf = LinearRegression()
clf.fit(train_data, train_target)
test_predict = clf.predict(test_data)
score = mean_squared_error(test_target, test_predict)
print("LinearRegression:  ", score)
# LinearRegression:   0.14565628375662207
 
优点:模型简单,部署方便,回归权重可以用于结果分析;训练快。
 缺点:精度低,特征存在一定的共线性问题。
 使用技巧:需要进行归一化处理,建议进行一定的特征选择,尽量避免高度相关的特征同时存在。
4.2.4 K近邻回归
根据之前的k值曲线图选择最佳K值:
reg_KNN = KNeighborsRegressor(n_neighbors=6)
reg_KNN.fit(train_data, train_target)
test_pred = reg_KNN.predict(test_data)
score = mean_squared_error(test_target, reg_KNN.predict(test_data))
print("KNeighborsRegressor MSE:  ", score)
# KNeighborsRegressor MSE:   0.18288669593425605
 
优点:模型简单,易于理解,对于数据量小的情况方便修改,可视化方便
 缺点:计算量大,不适合数据量大的情况;需要调参数。
 使用技巧:特征需要归一化,重要的特征可以适当加一定比例的权重。
4.2.5 随机森林回归
clf = RandomForestRegressor(n_estimators=200)  # 200棵树模型
clf.fit(train_data, train_target)
test_predict = clf.predict(test_data)
score = mean_squared_error(test_target, clf.predict(test_data))
print('RandomForestRegressor score', score)
# RandomForestRegressor score 0.1669636684508218
 
优点:使用方便,特征无须做过多变换,精度较高;模型并行训练快。
 缺点:结果不容易解释
 使用技巧:参数调节,提高精度。
 本题结果:比较合适
4.2.6 LGB模型回归
reg_lgb = lgb.LGBMRegressor(
    learning_rate=0.01,
    max_depth=-1,
    n_estimators=5000,
    boosting_type='gbdt',
    random_state=2019,
    objective='regression',
)
#训练模型
reg_lgb.fit(train_data, train_target)
score = mean_squared_error(test_target, reg_lgb.predict(test_data))
print('LightGBM socre ', score)
#LightGBM socre  0.156274722993209
 
优点:精度高。
 缺点:训练时间长,模型复杂。
 使用技巧:有效的验证集防止过拟合;参数搜索。
 本题结果:适用。
参考资料
[1] 《阿里云天池大赛赛题解析——机器学习篇》
 [2] 机器学习(三):基于LightGBM的分类预测
 [3] 机器学习算法-lightGBM
 [4] LightGBM回归预测模型构建 - 含GBM调参方法
 [5] LightGBM+遗传算法 调参优化
 [6] 机器学习之lightGBM模型










