模型选择- Validation Curve
我们业务中遇到的适用机器学习的场景,大部分都是监督学习,监督学习的算法非常多,每个模型需要调的超参也各不相同。当我们试用不同的模型,试图找到最优模型的过程,其实就是找出偏差和方差平衡点的过程。
模型的偏差与方差
我们用上述两幅图来说明下模型的方差和偏差的概念。上述两幅图是基于同一个数据集的两个回归模型的结果,左图表示的是高偏差,也就是欠拟合(underfitting).右图描述的是高方差,即过拟合(overfitting).
- 高偏差(underfitting):
高偏差的模型,一般training score 和 validation score结果都较差,模型过于简单,并不能很好的利用数据集的信息来预测因变量。一般处理这种情况,就往两个方向努力:- 增加模型复杂度
- 增加特征,利用训练集的数据,加工出更多的高阶特征
- 增加模型结构的复杂度,例如在随机森林中,可以增加数的数量
- 降低模型的正则惩罚力度。例如在逻辑回归中, λ \lambda λ的取值可以相对降低一些。
- 增加模型复杂度
- 高方差(overfitting):
高方差的模型,一般模型在训练集上表现都很好,但是在测试集上,一般都比较差。training score 和 validation score之间存在较大gap。遇到这种情况时,相应的也是往两个方向努力:- 增加更多的数据量。但是如果训练集本身数据量就已经够多了,比如customer churn的预测,相应的records一般都是数十万量级,增加数据量,可能对模型效果提升作用也不大。
- 降低模型的复杂度。
由上述可知,可以利用调节模型的结构复杂度来调节模型的方差和偏差,我们之前非线性模型中讲过polynomialRegression,这里我们以多项式回归为例,介绍下如何用validation curve来决定degree。
Validation Curve
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
import numpy as np
import pandas as pd
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import validation_curve
pipeline = make_pipeline(PolynomialFeatures(),LinearRegression())
from sklearn.datasets import load_boston
data = load_boston()
df = pd.DataFrame(data=data.data,columns = data.feature_names)
df.describe()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 | 506.000000 |
mean | 3.613524 | 11.363636 | 11.136779 | 0.069170 | 0.554695 | 6.284634 | 68.574901 | 3.795043 | 9.549407 | 408.237154 | 18.455534 | 356.674032 | 12.653063 |
std | 8.601545 | 23.322453 | 6.860353 | 0.253994 | 0.115878 | 0.702617 | 28.148861 | 2.105710 | 8.707259 | 168.537116 | 2.164946 | 91.294864 | 7.141062 |
min | 0.006320 | 0.000000 | 0.460000 | 0.000000 | 0.385000 | 3.561000 | 2.900000 | 1.129600 | 1.000000 | 187.000000 | 12.600000 | 0.320000 | 1.730000 |
25% | 0.082045 | 0.000000 | 5.190000 | 0.000000 | 0.449000 | 5.885500 | 45.025000 | 2.100175 | 4.000000 | 279.000000 | 17.400000 | 375.377500 | 6.950000 |
50% | 0.256510 | 0.000000 | 9.690000 | 0.000000 | 0.538000 | 6.208500 | 77.500000 | 3.207450 | 5.000000 | 330.000000 | 19.050000 | 391.440000 | 11.360000 |
75% | 3.677083 | 12.500000 | 18.100000 | 0.000000 | 0.624000 | 6.623500 | 94.075000 | 5.188425 | 24.000000 | 666.000000 | 20.200000 | 396.225000 | 16.955000 |
max | 88.976200 | 100.000000 | 27.740000 | 1.000000 | 0.871000 | 8.780000 | 100.000000 | 12.126500 | 24.000000 | 711.000000 | 22.000000 | 396.900000 | 37.970000 |
degree = np.arange(0,21)
X = df.iloc[:,3:6]
y = data.target
train_score,val_score = validation_curve(estimator = pipeline,X=X,y=y,param_name = 'polynomialfeatures__degree',param_range = degree,cv=7)
plt.figure(figsize=(16,8))
plt.plot(degree,np.median(train_score,1),color='blue',label='training_score')
plt.plot(degree,np.median(val_score,1),color='red',label='validation score')
plt.legend(loc='best')
plt.ylim(0,1)
plt.xlabel('degree')
plt.ylabel('score')
模型没有加数据预处理,不过依然可以看出,偏差与方差平衡最好的是三次多项。加上数据预处理和特征加工后,可以利用本文介绍的方法来最终进行模型结构的确定