机器学习16_欠拟合、过拟合详解 (2021.05.31)
一. 解惑
- 什么是欠拟合、过拟合?
⇒ 用两个通俗的案例让你更好地理解什么是过拟合和欠拟合
案例1:现在有一组天鹅的特征数据,然后对模型进行训练。模型通过学习后得知:有翅膀嘴巴长的就是天鹅。之后使用该模型进行预测,该模型可能会将所有符合这两个特征的动物都预测为天鹅,比如鹦鹉、山鸡等等,这就导致了误差的产生。导致出现误差的原因就是:模型学习到的天鹅的特征太少了,导致区分标准太过于粗糙,从而导致不能准确地识别出天鹅。
案例2:有了案例1的经验以后,增加了一些用于训练的特征,然后对模型进行训练。模型这次学到的内容是:有翅膀、嘴巴长、白色、脖子长形状像2的就是天鹅。之后使用该模型进行预测,当遇到鹦鹉、山鸡等会被案例1误识别的动物时,案例2所得到的模型不会将它们识别错误,然而当识别的动物变成了黑天鹅的时候,由于黑天鹅的颜色为黑色,则导致它无法被识别,从而也产生了误差。导致出现误差的原因就是:机器学习到的特征太过于依赖或者太符合训练数据了。
⇒ 所谓的欠拟合就是案例1,过拟合就是案例2。
也就是说,欠拟合就是一个假设在训练数据上不能获得很好的拟合,而且在训练数据以外的数据上也不能很好地拟合数据,此时就认为这个假设出现了欠拟合的现象(模型过于简单)。过拟合就是一个假设在训练数据上能够获得比其他假设更好地拟合,但在训练数据以外的数据集上却不能很好的拟合数据,此时就认为这个假设出现了过拟合现象(模型过于复杂)。
二. 欠拟合、过拟合的解决办法
-
欠拟合:
原因:模型学习到的样本的特征太少
解决办法:增加样本的特征数量 (多项式回归,直线变曲线) -
过拟合:
原因:原始特征过多,存在一些嘈杂特征
解决办法:(大波浪变小波浪)
1.进行特征选择,消除关联性大的特征(比较难处理)
2.正则化值岭回归(需要掌握)
三. 欠拟合解决办法之多项式回归
- 原理介绍
为了解决欠拟合的情形,经常要提高线性的次数(高次多项式)建立模型拟合曲线,次数过高会导致过拟合,次数不够会导致欠拟合。
那么如何给样本添加高次的特征数据呢? ⇒ 使用多项式回归!
API: sklearn.preprocessing.PolynomialFeatures
参数介绍:
degree:控制多项式的度;
interaction_only:默认为False,如果指定为True,那么就不会有特征自己和自己结合的项即没有a^2 和 b^2;
include_bias:默认为Tue,如果指定为False的话,那么就不会有1这一项
(举个例子:如果有a、b两个特征,则它的2次多项式为:(1, a, b, a^2, ab, b^2) - 代码演示 – 根据蛋糕的大小预测蛋糕的价格
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures # 用于解决欠拟合的问题的多项式回归
# 自己定义训练数据
x_train = [[6], [8], [10], [14], [18]] # 大小
y_train = [[7], [9], [13], [17.5], [18]] # 价格
# 进行阶数为一阶的线性回归和预测
linear = LinearRegression()
linear.fit(x_train, y_train)
# 绘制基于出原始样本数据得出来的拟合曲线 + 散点图
xx = np.linspace(0, 25, 100)
xx = xx.reshape(-1, 1)
yy = linear.predict(xx)
plt.scatter(x_train, y_train)
plt.plot(xx, yy)
plt.show()
"""多项式回归解决出现的欠拟合问题"""
# 建立二次多项式线性回归模型进行预测
poly2 = PolynomialFeatures(degree=2) # 2次多项式特征生成器
x_train_poly2 = poly2.fit_transform(x_train)
# 建立模型预测
linear2_poly2 = LinearRegression()
linear2_poly2.fit(x_train_poly2, y_train)
# 绘制基于多项式回归后得出来的拟合曲线 + 散点图
xx_poly2 = poly2.transform(xx)
yy_poly2 = linear2_poly2.predict(xx_poly2)
plt.scatter(x_train, y_train)
plt.plot(xx, yy, label="Degree = 1")
plt.plot(xx, yy_poly2, label="Degree = 2")
plt.legend()
plt.show()
"""使用模型对未知价格的蛋糕进行价格的预测"""
x_test1 = np.array([15]).reshape(1, -1)
x_test1_poly2 = poly2.fit_transform(x_test1.reshape(1, -1))
y_test1 = linear2_poly2.predict(x_test1_poly2)
print(y_test1)
- 结果展示
- 使用未经过多项式回归的样本数据,进行训练后的拟合结果(可见有些欠拟合,蓝色线为线性回归的结果,散点为各个样本数据。)
- 使用经过了多项式回归后的样本数据,进行训练后的拟合结果(与原拟合度相比有了显著的提升, 蓝色线为基于原数据的线性回归结果,黄色线为基于多项式回归后的数据的线性回归结果,散点为各个样本数据。)
四. 过拟合解决办法之正则化处理 — Ridge岭回归
- 原理介绍
1.正则化处理
将过拟合的曲线的凹凸幅度减小就可以使得过拟合的曲线趋近于拟合曲线了。所谓的过拟合曲线的凹凸肯定是由于线性回归方程中的高次项导致的,那么正则化就可以通过不断的尝试发现高次项的特征然后将这些特征的权重w调小到0,则高次项的特征就没有了,那么凹凸幅度也就减少了,就趋近于拟合曲线了。
注:
1.正则化可以使得高次项的权重减少,趋近于0。
2.LinearRegression算法是没有办法进行正则化的, 所以该算法模型容易出现过拟合,但目前无法解决。
⇒ 因此,就需要使用带有正则化算法的模型 — Ridge岭回归,处理出现的过拟合问题。
2.Ridge岭回归:具备L2正则化的线性回归模型
API:from sklearn.linear_model import Ridge
参数介绍:
alpha:正则化的力度,越接近于0或者1,力度越大,则表示高次项的权重w越接近于0,导致拟合曲线的凹凸幅度就越小。(取值范围 0 ~ 1的小数,或者1 ~ 10的整数)
coef_:回归系数 - 代码演示 (这里为了出现过拟合的结果就对样本数据进行了5次方的多项式回归)
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures # 用于解决欠拟合的问题的多项式回归
from sklearn.linear_model import Ridge # 用于处理过拟合的正则化处理
# 自己定义训练数据
x_train = [[6], [8], [10], [14], [18]] # 大小
y_train = [[7], [9], [13], [17.5], [18]] # 价格
# 进行阶数为一阶的线性回归和预测
linear = LinearRegression()
linear.fit(x_train, y_train)
# 绘制基于出原始样本数据得出来的拟合曲线 + 散点图
xx = np.linspace(0, 25, 100)
xx = xx.reshape(-1, 1)
yy = linear.predict(xx)
plt.scatter(x_train, y_train)
plt.plot(xx, yy)
plt.show()
"""使用更高次的多项式回归产生一个过拟合的结果"""
# 建立二次多项式线性回归模型进行预测
poly5 = PolynomialFeatures(degree=5) # 5次多项式特征生成器
x_train_poly5 = poly5.fit_transform(x_train)
# 建立模型预测
linear5_poly5 = LinearRegression()
linear5_poly5.fit(x_train_poly5, y_train)
print('未经过岭回归时的各项特征的权重', linear5_poly5.coef_)
# 绘制基于多项式回归后得出来的拟合曲线 + 散点图
xx_poly5 = poly5.transform(xx)
yy_poly5 = linear5_poly5.predict(xx_poly5)
plt.scatter(x_train, y_train)
plt.plot(xx, yy, label="Degree = 1")
plt.plot(xx, yy_poly5, label="Degree = 5")
plt.legend()
plt.show()
"""使用Ridge岭回归解决出现的过拟合问题"""
# 建立二次多项式线性回归模型进行预测
poly5 = PolynomialFeatures(degree=5) # 5次多项式特征生成器
x_train_poly5 = poly5.fit_transform(x_train)
# 建立模型预测
linear5_poly5_new = Ridge(alpha=0.8)
linear5_poly5_new.fit(x_train_poly5, y_train)
print('经过岭回归后的各项特征的权重', linear5_poly5.coef_)
# 绘制基于多项式回归后得出来的拟合曲线 + 散点图
xx_poly5 = poly5.transform(xx)
yy_poly5 = linear5_poly5_new.predict(xx_poly5)
plt.scatter(x_train, y_train)
plt.plot(xx, yy, label="Degree = 1")
plt.plot(xx, yy_poly5, label="Degree = 5")
plt.legend()
plt.show()
- 结果展示
- 过拟合结果(蓝色线为未做任何处理后的线性回归的结果,黄色对样本数据由于做了过高次的多项式回归而产生的过拟合结果,散点为各个样本数据。可见黄线为了能更多地穿过散点,有些许过拟合了。)
- 对过拟合情况进行岭回归处理,可以看出已经减少了过拟合的程度(蓝色线为未做任何处理后的线性回归的结果,黄色线为对过拟合数据做了相应的岭回归后的线性回归的结果,散点为各个样本数据。可见过拟合程度有所减轻。)
五. 理解与感悟
- 样本数据的好坏直接影响着线性回归的结果。
- 学会适当地对样本数据做一些处理,可以大大提升学习得到的模型的质量。