《Python数据科学手册》 机器学习之模型验证——基于Scikit-Learn

《Python数据科学手册》 笔记

一、超参数

      在模型拟合数据之前必须确定好的参数。

二、交叉验证

      将模型分为N组,每一轮依次用模型拟合其中的 N-1 组数据,再预测剩下一组数据,评估模型准确率。

     以五轮交叉验证为例:

用函数实现:

这是在我上一篇博客代码的基础上添加的,单独这两行代码是要报错的哦!(上一篇博客)

其中,model是实例化的一个模型(只需要初始化即可),X_iris是未手动分组的鸢尾花特征矩阵,y_iris是未手动分组的鸢尾花标签数组,cv=5表示要进行5轮交叉验证。

需要注意的是,model_selection模块在Scikit-Learn 0.18版之前是用的cross_validation。

另外有一种极端的情况,那就是每次只有一个样本做测试,其他样本全用于训练。这种交叉验证类型被称为LOO(leave-one-out)交叉验证。

用函数实现:

需要注意的是,从model_selection模块中导入的LeaveOneOut和低版本Scikit-Learn(Scikit-Learn 0.18版之前)里的cross_validation模块中导入的LeaveOneOut用法不同,前者为cv=LeaveOneOut(),而后者为cv=LeaveOneOut(len(X_iris))。

三、选择最优模型

假如模型效果不好,可以从以下几个方面进行改善:

①用更复杂/更灵活的模型

②用更简单/更确定的模型

③采集更多的训练样本

④为每个样本采集更多的特征

但是选择哪一种方案进行改善却不是件随便的事,有时候换一种复杂的模型有可能产生更差的结果,增加更多的训练样本也未必能改善性能。因此,改善模型的能力,是机器学习实践者需要努力培养的重要能力。Scikit-Learn中自带验证曲线(validation_curve)学习曲线(learning_curve),可供我们探究某一类模型得分与其复杂度和训练数据集规模的关系。接下来对模型的选择进行稍微细致的分析。

1. 偏差与方差的均衡

“最优模型”的问题可以看成是找出偏差方差平衡点的问题。

具有高偏差的模型被认为是对数据欠拟合,模型在验证集的表现与在训练及的表现类似;

具有高方差的模型被认为是对数据过拟合,模型在验证集的表现远不如在训练集的表现。

2.Scikit-Learn验证曲线

验证曲线表现的是模型得分与模型复杂度的关系

模型的训练得分和验证得分一般按照以下趋势发展:

从中可以得出:

①训练得分肯定高于验证得分

②使用复杂度较低的模型(高偏差)时,训练数据往往欠拟合(模型对训练数据和新数据都缺乏预测能力)

③使用复杂度较高的模型(高方差)时,训练数据往往过拟合(模型对训练数据预测能力强,但是对新数据预测能力差)

④当使用复杂度适中的模型时,验证曲线得分最高(偏差与方差达到均衡)

以一个带多项式预处理器的简单线性回归模型为例,可视化验证曲线,代码如下:


   
   
   
   
  1. import numpy as np
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. from sklearn.preprocessing import PolynomialFeatures
  5. from sklearn.linear_model import LinearRegression
  6. from sklearn.pipeline import make_pipeline
  7. import seaborn ;seaborn.set() #设置图形样式
  8. #定义模型
  9. def PolynomialRegression(degree=2,**kwargs):
  10. return make_pipeline(PolynomialFeatures(degree),LinearRegression(**kwargs))
  11. #产生数据
  12. def make_data(N,err=1.0,rseed=1):
  13. rng = np.random.RandomState(rseed)
  14. X = rng.rand(N, 1)** 2
  15. y = 10 - 1./(X.ravel() + 0.1)
  16. if err > 0:
  17. y += err * rng.randn(N)
  18. return X,y
  19. X,y = make_data( 40)
  20. #导入验证曲线
  21. from sklearn.model_selection import validation_curve
  22. degree = np.arange( 0, 21) #验证范围(多项式0阶到20阶)
  23. train_score,val_score = validation_curve(PolynomialRegression(),X,y, 'polynomialfeatures__degree',degree,cv= 7)
  24. #设置绘图样式
  25. plt.plot(degree,np.median(train_score, 1),color= 'blue', label= 'training score')
  26. plt.plot(degree,np.median(val_score, 1),color= 'red',label= 'validation score')
  27. plt.legend(loc= 'best')
  28. plt.ylim( 0, 1)
  29. plt.xlabel( 'degree')
  30. plt.ylabel( 'score')

需要注意的是,validation_curve在Scikit-Learn 0.18版之前是放在learning_curve模块中的,即需要将

from sklearn.model_selection import validation_curve
   
   
   
   

换为: 

from sklearn.learning_curve import validation_curve
   
   
   
   

另外,注意'polynomialfeatures__degree'中间是两个下划线 

运行结果如下:

从图中可以得出如下结论:

①训练得分总是比验证得分高

②训练得分随着模型复杂度的提升而单调递增

③验证得分增长到最高点后由于过拟合而开始骤降

③(此例中)偏差与方差均衡性最好的是三次多项式

3.Scikit-Learn学习曲线

学习曲线表现的是模型得分与训练数据集规模的关系

模型的训练得分和验证得分一般按照以下趋势发展:

从中可以得出:

①特定复杂度的模型对较小的数据集容易过拟合(训练得分高,验证得分低)

②特定复杂度的模型对较大的数据集容易欠拟合(随着数据的增大,训练得分不断降低,验证得分不断升高)

③模型的验证集得分永远不会高于训练集得分(两条曲线一直在靠近,但永远不会交叉)

④随着训练样本数量的增加,分数会收敛到定值

和可视化验证曲线相同,以一个带多项式预处理器的简单线性回归模型为例,可视化学习曲线,代码如下:


   
   
   
   
  1. from sklearn.model_selection import learning_curve
  2. fig,ax = plt.subplots( 1, 3,figsize=( 15, 5))
  3. for i,degree in enumerate([ 2, 4, 9]):
  4. N,train_lc,val_lc = learning_curve(PolynomialRegression(degree),X,y,cv= 7,train_sizes=np.linspace( 0.3, 1, 25))
  5. ax[i].plot(N,np.mean(train_lc, 1),color= 'blue',label= 'training score')
  6. ax[i].plot(N,np.mean(val_lc, 1),color= 'red',label= 'validation score')
  7. ax[i].hlines(np.mean([train_lc[ -1],val_lc[ -1]]),N[ 0],N[ -1],color= 'gray',linestyle= 'dashed')
  8. ax[i].set_ylim( 0, 1)
  9. ax[i].set_xlim(N[ 0],N[ -1])
  10. ax[i].set_xlabel( 'training size')
  11. ax[i].set_ylabel( 'score')
  12. ax[i].set_title( 'degree={0}'.format(degree),size= 14)
  13. ax[i].legend(loc= 'best')

注意,learning_curve在Scikit-Learn 0.18版之前是放在learning_curve模块中的,即需要将

from sklearn.model_selection import learning_curve
   
   
   
   

替换为

from sklearn.learning_curve import learning_curve
   
   
   
   

运行结果如下:

从图中可以得出如下结论:

(选取三个子图中的任意一图观察)当学习曲线已经收敛是(即训练曲线和验证曲线已经贴合在一起),再增加训练数据也不能再显著改善拟合效果,这时候,提高收敛的唯一办法就是换模型,通常是换更复杂的模型(图1,图2,图3的收敛值(虚线)逐渐增大)。

4.网格搜索

从以上的探索可以看出,模型得分和模型的复杂度以及训练集的大小有关,如何找到最优的模型?Scikit-Learn的grid_search模块提供了一个自动化工具解决这个问题。

例如要用网格搜索寻找最优多项式回归模型,我们可以在模型特征的三维网格中寻找最优值——包括多项式的次数的搜索范围、回归模型是否拟合斜距,以及回归模型是否需要进行标准化处理。

你可能感兴趣的:(《Python数据科学手册》,笔记)