使用sklearn库中的SVR做回归分析

sklearn中的回归有多种方法,广义线性回归集中在linear_model库下,例如普通线性回归、Lasso、岭回归等;另外还有其他非线性回归方法,例如核svm、集成方法、贝叶斯回归、K近邻回归、决策树回归等,这些不同回归算法分布在不同的库中。

本示例主要使用sklearn的多个回归算法做回归分析、用matplotlib做图形展示。数据源文件regression.txt位于“附件-chapter4”中,默认工作目录为“附件-chapter4”(如果不是,请cd切换到该目录下,否则会报“IOError: File regression.txt does not exist”)。

本示例模拟的是针对一批训练集做多个回归模型的训练和评估,从中选择效果较好的模型并对新数据集做回归预测。本示例主要使用sklearn的多个回归算法做回归分析、用matplotlib做图形展示。

完整代码如下:

  1. # 导入库
  2. import numpy as np  # numpy库
  3. from sklearn.linear_model import BayesianRidge, LinearRegression, ElasticNet  # 批量导入要实现的回归算法
  4. from sklearn.svm import SVR  # SVM中的回归算法
  5. from sklearn.ensemble.gradient_boosting import GradientBoostingRegressor  # 集成算法
  6. from sklearn.model_selection import cross_val_score  # 交叉检验
  7. from sklearn.metrics import explained_variance_score, mean_absolute_error, mean_squared_error, r2_score  # 批量导入指标算法
  8. import pandas as pd  # 导入pandas
  9. import matplotlib.pyplot as plt  # 导入图形展示库
  10. # 数据准备
  11. raw_data = np.loadtxt('regression.txt')  # 读取数据文件
  12. X = raw_data[:, :-1]  # 分割自变量
  13. y = raw_data[:, -1]  # 分割因变量
  14. # 训练回归模型
  15. n_folds = 6  # 设置交叉检验的次数
  16. model_br = BayesianRidge()  # 建立贝叶斯岭回归模型对象
  17. model_lr = LinearRegression()  # 建立普通线性回归模型对象
  18. model_etc = ElasticNet()  # 建立弹性网络回归模型对象
  19. model_svr = SVR()  # 建立支持向量机回归模型对象
  20. model_gbr = GradientBoostingRegressor()  # 建立梯度增强回归模型对象
  21. model_names = ['BayesianRidge', 'LinearRegression', 'ElasticNet', 'SVR', 'GBR']  # 不同模型的名称列表
  22. model_dic = [model_br, model_lr, model_etc, model_svr, model_gbr]  # 不同回归模型对象的集合
  23. cv_score_list = []  # 交叉检验结果列表
  24. pre_y_list = []  # 各个回归模型预测的y值列表
  25. for model in model_dic:  # 读出每个回归模型对象
  26.     scores = cross_val_score(model, X, y, cv=n_folds)  # 将每个回归模型导入交叉检验模型中做训练检验
  27.     cv_score_list.append(scores)  # 将交叉检验结果存入结果列表
  28.     pre_y_list.append(model.fit(X, y).predict(X))  # 将回归训练中得到的预测y存入列表
  29. # 模型效果指标评估
  30. n_samples, n_features = X.shape  # 总样本量,总特征数
  31. model_metrics_name = [explained_variance_score, mean_absolute_error, mean_squared_error, r2_score]  # 回归评估指标对象集
  32. model_metrics_list = []  # 回归评估指标列表
  33. for i in range(5):  # 循环每个模型索引
  34.     tmp_list = []  # 每个内循环的临时结果列表
  35.     for m in model_metrics_name:  # 循环每个指标对象
  36.         tmp_score = m(y, pre_y_list[i])  # 计算每个回归指标结果
  37.         tmp_list.append(tmp_score)  # 将结果存入每个内循环的临时结果列表
  38.     model_metrics_list.append(tmp_list)  # 将结果存入回归评估指标列表
  39. df1 = pd.DataFrame(cv_score_list, index=model_names)  # 建立交叉检验的数据框
  40. df2 = pd.DataFrame(model_metrics_list, index=model_names, columns=['ev', 'mae', 'mse', 'r2'])  # 建立回归指标的数据框
  41. print ('samples: %d \t features: %d' % (n_samples, n_features))  # 打印输出样本量和特征数量
  42. print (70 * '-')  # 打印分隔线
  43. print ('cross validation result:')  # 打印输出标题
  44. print (df1)  # 打印输出交叉检验的数据框
  45. print (70 * '-')  # 打印分隔线
  46. print ('regression metrics:')  # 打印输出标题
  47. print (df2)  # 打印输出回归指标的数据框
  48. print (70 * '-')  # 打印分隔线
  49. print ('short name \t full name')  # 打印输出缩写和全名标题
  50. print ('ev \t explained_variance')
  51. print ('mae \t mean_absolute_error')
  52. print ('mse \t mean_squared_error')
  53. print ('r2 \t r2')
  54. print (70 * '-')  # 打印分隔线
  55. # 模型效果可视化
  56. plt.figure()  # 创建画布
  57. plt.plot(np.arange(X.shape[0]), y, color='k', label='true y')  # 画出原始值的曲线
  58. color_list = ['r', 'b', 'g', 'y', 'c']  # 颜色列表
  59. linestyle_list = ['-', '.', 'o', 'v', '*']  # 样式列表
  60. for i, pre_y in enumerate(pre_y_list):  # 读出通过回归模型预测得到的索引及结果
  61.     plt.plot(np.arange(X.shape[0]), pre_y_list[i], color_list[i], label=model_names[i])  # 画出每条预测结果线
  62. plt.title('regression result comparison')  # 标题
  63. plt.legend(loc='upper right')  # 图例位置
  64. plt.ylabel('real and predicted value')  # y轴标题
  65. plt.show()  # 展示图像
  66. # 模型应用
  67. print ('regression prediction')
  68. new_point_set = [[1.05393, 0., 8.14, 0., 0.538, 5.935, 29.3, 4.4986, 4., 307., 21., 386.85, 6.58],
  69.                  [0.7842, 0., 8.14, 0., 0.538, 5.99, 81.7, 4.2579, 4., 307., 21., 386.75, 14.67],
  70.                  [0.80271, 0., 8.14, 0., 0.538, 5.456, 36.6, 3.7965, 4., 307., 21., 288.99, 11.69],
  71.                  [0.7258, 0., 8.14, 0., 0.538, 5.727, 69.5, 3.7965, 4., 307., 21., 390.95, 11.28]]  # 要预测的新数据集
  72. for i, new_point in enumerate(new_point_set):  # 循环读出每个要预测的数据点
  73.     new_pre_y = model_gbr.predict(new_point)  # 使用GBR进行预测
  74.     print ('predict for new point %d is:  %.2f' % (i + 1, new_pre_y))  # 打印输出每个数据点的预测信息

 

上述代码以空行分为6个部分。

第一部分导入库。

本示例中用到的库比较多:numpy用于文件读写和基本数据处理;sklearn.linear_model中的三个广义线性回归下的回归算法BayesianRidge、LinearRegression、ElasticNet,sklearn.svm中的svr回归算法,sklearn.ensemble.gradient_boosting中的GradientBoostingRegressor回归算法;cross_val_score用来做交叉检验;sklearn.metrics下的多个回归模型指标评估方法用来做模型评估;pandas用来做格式化的数据框,便于数据结果输出;Matplotlib用来做预测结果的展示和对比。这里导入多种回归算法,目的是检验在没有先验经验的条件下,通过多个模型的训练,从中找到最佳拟合算法做后续应用。

第二部分数据准备。

使用numpy的loadtxt方法读取数据文件,并使用索引切片功能从数据集中分割出自变量X和因变量y。自变量X拥有506个样本,13个特征变量。

第三部分训练回归模型。

本过程使用交叉检验的方法评估不同模型的训练效果。

先设置交叉检验的次数为6(6折交叉检验),后续会在交叉检验模型训练中用到;
接着分别建立贝叶斯岭回归(BayesianRidge)、普通线性回归(LinearRegression)、弹性网络回归(ElasticNet)、支持向量机回归(SVR)、梯度增强回归(GradientBoostingRegressor)模型对象,前3个算法属于广义线性回归,后两个属于支持向量机和梯度增强算法的变体;

然后分别建立不同模型的名称列表、回归模型对象的集合、交叉检验结果空列表、回归模型预测的y值空列表,分别用于后续名称读取、模型代入交叉检验算法、交叉检验结果数据存储和回归预测的结果存储。

最后通过for循环读出每个回归模型对象,对每个回归模型导入交叉检验模型cross_val_score中做训练检验并设置检验6次,并将交叉检验结果通过append方法存入结果列表,将回归训练中得到的预测y通过append方法存入列表。

相关知识点:cross_val_score

cross_val_score是sklearn.model_selection中的交叉检验工具,可以对特定算法模型进行交叉检验。常用参数:

  1. sklearn.model_selection.cross_val_score(estimator, X, y=None, groups=None, scoring=None, cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch='2*n_jobs')

estimator:要应用交叉检验的模型对象,该模型在交叉检验中会通过使用fit方法来训练模型

  • X, y:交叉检验的数据集X和目标y,其中X至少是2维数据
  • cv:要进行交叉检验的模式。如果cv值为空,那么默认使用3折交叉检验;如果cv值是整数,那么使用按照指定的数量做交叉检验。这两种情况下都会调用model_selection.StratifiedKFold方法实现。如果cv值是用来交叉检验的生成器对象或可迭代的测试和训练集,那么将使用sklearn.model_selection.KFold方法。
  • cross_val_score交叉检验后返回的得分默认调用算法模型的score方法做得分估计,因此不同的算法模型其得分计算方法可能有差异,具体取决于模型本身score方法(scorer(estimator, X, y))的计算逻辑。当然,也可以通过设置scoring参数字符串来手动指定得分计算方法,例如cross_val_score(estimator, X, y, scoring='r2', cv=6)。

第四部分模型效果指标评估。

先通过自变量数据集的shape获得总样本量和总特征数;

接着创建一个列表用于存储接下来用到的回归模型评估指标对象,explained_variance_score,mean_absolute_error,mean_squared_error, r2_score,这些对象在第一步导入库时已经导入,因此无需做其他处理便可直接使用;创建用于存储不同回归评估指标的列表。

  • explained_variance_score:解释回归模型的方差得分,其值取值范围是[0,1],越接近于1说明自变量越能解释因变量的方差变化,值越小则说明效果越差。
  • mean_absolute_error:平均绝对误差(Mean Absolute Error,MAE),用于评估预测结果和真实数据集的接近程度的程度,其其值越小说明拟合效果越好。
  • mean_squared_error:均方差(Mean squared error,MSE),该指标计算的是拟合数据和原始数据对应样本点的误差的平方和的均值,其值越小说明拟合效果越好。
  • r2_score:判定系数,其含义是也是解释回归模型的方差得分,其值取值范围是[0,1],越接近于1说明自变量越能解释因变量的方差变化,值越小则说明效果越差。

然后通过两层for循环来分别对每个模型和每种回归模型评估方法进行计算。需要注意的是里面有一个用于存储每个内循环的临时结果列表,需要在内循环结束之后,每次将其结果存储到外部循环中的回归评估指标列表。

下面是通过pandas的Dataframe方法分别建立交叉检验和回归指标数据框,然后打印输出样本量和特征数量、交叉检验和回归指标数据框,并通过打印横线来做逻辑输出切分;

为了更好的理解指标的含义,打印输出缩写和全名标题对照表。在打印过程中使用的方法跟聚类中的类似,但是对于格式化的输出,这里使用了pandas的数据框,这样如果数据量比较多的情况下,更容易控制。输出结果如下:

 

  1. samples: 506     features: 13
  2. --------------------------------------------------------------------------
  3. cross validation result:
  4.                          0         1         2         3         4         5
  5. BayesianRidge     0.662422  0.677079  0.549702  0.776896 -0.139738 -0.024448
  6. LinearRegression  0.642240  0.611521  0.514471  0.785033 -0.143673 -0.015390
  7. ElasticNet        0.582476  0.603773  0.365912  0.625645  0.437122  0.200454
  8. SVR              -0.000799 -0.004447 -1.224386 -0.663773 -0.122252 -1.374062
  9. GBR               0.747920  0.809555  0.767936  0.862972  0.375267  0.559758
  10. --------------------------------------------------------------------------
  11. regression metrics:
  12.                         ev       mae        mse        r2
  13. BayesianRidge     0.731143  3.319204  22.696772  0.731143
  14. LinearRegression  0.740608  3.272945  21.897779  0.740608
  15. ElasticNet        0.686094  3.592915  26.499828  0.686094
  16. SVR               0.173548  5.447960  71.637552  0.151410
  17. GBR               0.975126  1.151773   2.099835  0.975126
  18. --------------------------------------------------------------------------
  19. short name   full name
  20. ev   explained_variance
  21. mae      mean_absolute_error
  22. mse      mean_squared_error
  23. r2   r2

 

通过结果可以看出,增强梯度(GBR)回归是所有模型中拟合效果最好的,表现在能解释97%的方差变化,并且各个误差项的值都是最低的。另外,还有一个重要因素是,梯度增强算法在测试的6次中,其结果相对稳定性较高,这也说明了该算法在应对不同数据集的稳定效果。指标中r2跟ev的值是相同的,原因是r2作为判定系数,本身就是解释方差的比例,含义相同。

第五部分模型效果可视化。

该部分使用Matplotlib将原始数据y和其他5个回归模型预测到的y值通过趋势图进行对比。

先通过figure方法创建画布,然后画出原始数据y的分布,其中画图所需的x值域,使用自变量集X的形状得到一个自增数字列表。

接着画出其他5个回归预测结果展示所需要的颜色列表、样式列表,并通过for集合plot方法循环画出每个预测结果趋势线。

最后设置图形标题、图例位置(右上角)、y轴标题并展示图像

注意 不要忘记设置图像位置,否则即使在plot方法中设置了label值(图例标签值),也会由于缺少图例位置而无法显示图例。

1

从图中看出,梯度增强算法(青色)的拟合程度跟原始数据(黑色)最接近,这也印证了在上面指标中输出的结果。

第六部分模型应用。

基于新给出的包含多个数据点的数据集,我们要预测未来值,直接使用for循环读出每个数据,然后使用最优回归模型梯度增强的predict方法做预测,得到如下结果:

  1. predict for new point 1 is:  21.49
  2. predict for new point 2 is:  16.84
  3. predict for new point 3 is:  19.50
  4. predict for new point 4 is:  19.16

上述过程中,主要需要考虑的关键点是:如何在样本维度较多的情况下,选择最佳的回归模型,这里我们使用了多个模型,并结合交叉检验的方法找到最优的回归方法。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>