- Python计算机视觉与深度学习实战
- 郭卡 戴亮编著
- 1209字
- 2025-02-24 11:09:48
1.7 模型验证
在训练完模型之后,需要对模型进行评价,决定是否采用训练后的模型。本书前面的例子都是直接在训练数据上验证模型,这种方法存在一个很严重的问题:模型有可能过拟合。
什么情况下会出现过拟合呢?过拟合常常出现在以下3种情况下:
- 数据有噪声;
- 数据集过小;
- 模型太复杂。
在解决过拟合问题之前,需要有一个判断过拟合的依据,就是使用训练集之外的数据进行验证。
在sklearn中,有两种常用的验证方法:留出验证法和交叉验证法。
留出验证法的操作方式是在训练之前,从总数据集中按一定规则(或随机)抽取一部分数据作为验证数据集,然后在模型训练完成之后,在验证集上对模型的预测效果进行验证。
如果模型在训练集上的效果非常好,但是在验证集上的效果很差,就说明模型出现了过拟合现象。
sklearn中的留出验证法可以通过sklearn.model_selection.train_test_split
函数实现。下面是一个模型过拟合的例子(此例使用Jupyter Notebook编写):
In:
import numpy as np
from sklearn.model_selection import train_test_split
# 导入线性模型和多项式特征构造模块
from sklearn import linear_model
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import r2_score
import matplotlib.pyplot as plt
%matplotlib inline
接下来需要生成20个样本点,并加入一些随机扰动,生成数据的代码如下:
In:
# 样本数量
n_samples = 20
x = np.array([i+2 for i in range(n_samples)]) * 4
# 在log函数曲线上加入随机噪声
y = 3 * np.log(x) + np.random.randint(0,3,n_samples)
plt.scatter(x,y)
生成的样本如图1-16所示。

图 1-16 生成数据
然后对数据集进行划分,留出一部分验证集,其中test_size
是验证集在总数据集中的占比:
In:
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size = 0.3)
下面使用二项式拟合的方式来拟合这个模型。在sklearn中,二项式拟合的实现方法是先将训练特征转换为二项式特征,然后再使用线性回归模型进行拟合,相关代码如下:
In:
def poly_fit(degree):
poly_reg =PolynomialFeatures(degree=degree)
# 转换成二次特征
x_ploy_train = poly_reg.fit_transform(x_train.reshape(-1,1))
# 对x_test进行同样的转换
x_ploy_test = poly_reg.transform(x_test.reshape(-1,1))
clf = linear_model.LinearRegression()
clf.fit(x_ploy_train,y_train.reshape(-1,1))
# 创建子图,绘制训练集上的预测结果
plt.subplot(121)
y_train_pred = clf.predict(x_ploy_train)
sorted_indices = np.argsort(x_train)
plt.plot(x_train[sorted_indices],y_train_pred[sorted_indices])
plt.scatter(x_train,y_train)
# 创建子图,绘制验证集上的预测结果
plt.subplot(122)
y_test_pred = clf.predict(x_ploy_test)
# 同时对x_test和y_test_pred进行排序
sorted_indices = np.argsort(x_test)
plt.plot(x_test[sorted_indices],y_test_pred[sorted_indices])
plt.scatter(x_test,y_test)
# 计算r2_score
print("Train R2 score",r2_score(y_train_pred,y_train))
print("Test R2 score",r2_score(y_test_pred,y_test))
然后逐步提高多项式的次数,观察模型效果与多项式次数之间的关系。二次多项式拟合代码如下,结果如图1-17所示:
In:
poly_fit(2)
Out:
Train R2 score 0.8102748526150807
Test R2 score 0.7661602866338544

图 1-17 二次多项式拟合结果
五次多项式拟合代码如下,结果如图1-18所示:
In:
poly_fit(5)
Out:
Train R2 score 0.9087433750748772
Test R2 score 0.8326903541105737

图 1-18 五次多项式拟合结果
十次多项式拟合代码如下,结果如图1-19所示:
In:
poly_fit(10)
Out:
Train R2 score 0.9176237285551411
Test R2 score -0.13339572778788056

图 1-19 十次多项式拟合结果
上述案例使用train_test_split
将数据集划分为两个部分,训练集和验证集。然后在训练集上进行模型训练,训练完成后,分别计算训练集和验证集上的模型指标。
结果发现,随着模型复杂度的提升(多项式特征次数越来越高),模型在训练集上的表现(R2 Score
)越来越好,在验证集上的效果却是先变好再变坏。这就是模型过拟合的表现。
交叉验证法可以理解为留出验证法的升级版,以sklearn中的KFold检验为例,其算法步骤如下。
(1) 将数据集划分为n个互斥子集。
(2) 以其中一个子集作为验证集,其他子集作为训练集,训练模型。
(3) 选择另一个子集作为验证集,其他子集作为训练集,再训练模型。
(4) 如此进行n次训练和测试,得到n个结果。
在发现模型过拟合后,可以尝试通过如下几个方法解决过拟合的问题:
- 重新清洗数据;
- 增加数据量;
- 采用正则化方法;
- 选择合适的模型。