学习目标
🍀 掌握过拟合、欠拟合的概念
🍀 掌握过拟合、欠拟合产生的原因
🍀 知道什么是正则化,以及正则化的分类
🍔欠拟合与过拟合
1.1 欠拟合与过拟合定义
🐻 过拟合:一个假设 在训练数据上能够获得比其他假设更好的拟合, 但是在测试数据集上却不能很好地拟合数据 (体现在准确率下降),此时认为这个假设出现了过拟合的现象。(模型过于复杂)
🐻 欠拟合:一个假设 在训练数据上不能获得更好的拟合,并且在测试数据集上也不能很好地拟合数据 ,此时认为这个假设出现了欠拟合的现象。(模型过于简单)
过拟合和欠拟合的区别:
欠拟合在训练集和测试集上的误差都较大
过拟合在训练集上误差较小,而测试集上误差较大
1.2 通过代码认识过拟合和欠拟合
🐼 绘制数据
import numpy as np import matplotlib.pyplot as plt np.random.seed(666) x = np.random.uniform(-3,3,size = 100) X = x.reshape(-1,1) y = 0.5* x**2 + x+2 +np.random.normal(0,1,size = 100) from sklearn.linear_model import LinearRegression estimator = LinearRegression() estimator.fit(X,y) y_predict = estimator.predict(X) plt.scatter(x,y) plt.plot(x,y_predict,color = 'r') plt.show()
#计算均方误差
from sklearn.metrics import mean_squared_error mean_squared_error(y,y_predict) #3.0750025765636577
🐼 添加二次项,绘制图像
X2 = np.hstack([X,X**2])
estimator2 = LinearRegression()
estimator2.fit(X2,y)
y_predict2 = estimator2.predict(X2)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict2[np.argsort(x)],color = 'r')
plt.show()
#计算均方误差和准确率
from sklearn.metrics import mean_squared_error
mean_squared_error(y,y_predict2)
#1.0987392142417858
🐼 再次加入高次项,绘制图像,观察均方误差结果
X5 = np.hstack([X2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10])
estimator3 = LinearRegression()
estimator3.fit(X5,y)
y_predict5 = estimator3.predict(X5)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict5[np.argsort(x)],color = 'r')
plt.show()
error = mean_squared_error(y, y_predict5)
error
#1.0508466763764157
通过上述观察发现,随着加入的高次项越来越多,拟合程度越来越高,均方误差也随着加入越来越小。说明已经不再欠拟合了。
那么问题来了:
🤖 如何判断出现过拟合呢?
将数据集进行划分:对比X、X2、X5的测试集的均方误差
X的测试集均方误差
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state = 5)
estimator = LinearRegression()
estimator.fit(X_train,y_train)
y_predict = estimator.predict(X_test)
mean_squared_error(y_test,y_predict)
#3.153139806483088
X2的测试集均方误差
X_train,X_test,y_train,y_test = train_test_split(X2,y,random_state = 5)
estimator = LinearRegression()
estimator.fit(X_train,y_train)
y_predict = estimator.predict(X_test)
mean_squared_error(y_test,y_predict)
#1.111873885731967
X5的测试集的均方误差
X_train,X_test,y_train,y_test = train_test_split(X5,y,random_state = 5)
estimator = LinearRegression()
estimator.fit(X_train,y_train)
y_predict = estimator.predict(X_test)
mean_squared_error(y_test,y_predict)
#1.4145580542309835
1.3 原因以及解决办法
欠拟合产生原因: 学习到数据的特征过少
💘 解决办法:
(1)添加其他特征项,有时出现欠拟合是因为特征项不够导致的,可以添加其他特征项来解决
(2)添加多项式特征,模型过于简单时的常用套路,例如将线性模型通过添加二次项或三次项使模型泛化能力更强
过拟合产生原因: 原始特征过多,存在一些嘈杂特征, 模型过于复杂是因为模型尝试去兼顾所有测试样本
💘 解决办法:
(1)重新清洗数据,导致过拟合的一个原因有可能是数据不纯,如果出现了过拟合就需要重新清洗数据。
(2)增大数据的训练量,还有一个原因就是我们用于训练的数据量太小导致的,训练数据占总数据的比例过小。
(3)正则化
(4)减少特征维度
🍔正则化
2.1 什么是正则化
在解决回归过拟合中,我们选择正则化。但是对于其他机器学习算法如分类算法来说也会出现这样的问题,除了一些算法本身作用之外(决策树、神经网络),我们更多的也是去自己做特征选择,包括之前说的删除、合并一些特征
🥪 如何解决?
在学习的时候,数据提供的特征有些影响模型复杂度或者这个特征的数据点异常较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除某个特征的影响),这就是正则化
注:调整时候,算法并不知道某个特征影响,而是去调整参数得出优化的结果
2.2 正则化类别
🐻 L1正则化
- 假设𝐿(𝑊)是未加正则项的损失,𝜆是一个超参,控制正则化项的大小。
- 则最终的损失函数:𝐿=𝐿(𝑊)+ \lambda*\sum_{i=1}^{n}\lvert w_i\rvert
作用:用来进行特征选择,主要原因在于L1正则化会使得较多的参数为0,从而产生稀疏解,可以将0对应的特征遗弃,进而用来选择特征。一定程度上L1正则也可以防止模型过拟合。
LASSO回归: from sklearn.linear_model import Lasso
🐻 L2正则化
- 假设𝐿(𝑊)是未加正则项的损失,𝜆是一个超参,控制正则化项的大小。
- 则最终的损失函数:𝐿=𝐿(𝑊)+ \lambda*\sum{i=1}^{n}w{i}^{2}
作用:主要用来防止模型过拟合,可以减小特征的权重
优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
Ridge回归: from sklearn.linear_model import Ridge
🐻 L2正则为什么可以减小特征权重
- 对于之前梯度下降讲到的损失函数来说,在代价函数后面加上一个正则化项
- 对其求偏导后得到
- 然后得到梯度下降的表达式如下
🐻 L1正则为什么可以产生稀疏解(可以特征选择)
稀疏性:向量中很多维度值为0
- 对其中的一个参数 w_i 计算梯度,其他参数同理,α是学习率,sign(wi)是符号函数。
L1的梯度:
🍼 𝐿=𝐿(𝑊)+ \lambda*\sum_{i=1}^{n}\lvert w_i\rvert
🍼 \frac{\partial L}{\partial w{i}} = \frac{\partial L(W)}{\partial w{i}}+\lambda sign(w_{i})
🍼 w_i = w_i - \alpha \frac{\partial L(W)}{\partial w_{i}} - \alpha 2\lambda w_i
正则化案例💯:
X10 = np.hstack([X2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10])
estimator3 = LinearRegression()
estimator3.fit(X10,y)
y_predict3 = estimator3.predict(X10)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict3[np.argsort(x)],color = 'r')
plt.show()
estimator3.coef_
array([ 1.32292089e+00, 2.03952017e+00, -2.88731664e-01, -1.24760429e+00,
8.06147066e-02, 3.72878513e-01, -7.75395040e-03, -4.64121137e-02,
1.84873446e-04, 2.03845917e-03])
from sklearn.linear_model import Lasso # L1正则 from sklearn.linear_model import Ridge # 岭回归 L2正则 from numpy import np X10 = np.hstack([X2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10]) estimator_l1 = Lasso(alpha=0.005,normalize=True) # 调整alpha 正则化强度 查看正则化效果 estimator_l1.fit(X10,y) y_predict_l1 = estimator_l1.predict(X10) plt.scatter(x,y) plt.plot(np.sort(x),y_predict_l1[np.argsort(x)],color = 'r') plt.show() estimator_l1.coef_ # Lasso 回归 L1正则 会将高次方项系数变为0 array([ 0.97284077, 0.4850203 , 0. , 0. , -0. , 0. , -0. , 0. , -0. , 0. ]) X10 = np.hstack([X2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10]) estimator_l2 = Ridge(alpha=0.005,normalize=True) # 调整alpha 正则化强度 查看正则化效果 estimator_l2.fit(X10,y) y_predict_l2 = estimator_l2.predict(X10) plt.scatter(x,y) plt.plot(np.sort(x),y_predict_l2[np.argsort(x)],color = 'r') plt.show() estimator_l2.coef_ # l2 正则不会将系数变为0 但是对高次方项系数影响较大 array([ 9.91283840e-01, 5.24820573e-01, 1.57614237e-02, 2.34128982e-03, 7.26947948e-04, -2.99893698e-04, -8.28333499e-05, -4.51949529e-05, -4.21312015e-05, -8.22992826e-07])
🍔小结
🍬 欠拟合
- 在训练集上表现不好,在测试集上表现不好
- 解决方法,继续学习:添加其他特征项,添加多项式特征
🍬 过拟合
- 在训练集上表现好,在测试集上表现不好
- 解决方法:重新清洗数据集、增大数据的训练量、正则化、 减少特征维度
🍬 正则化
- 在损失函数中加入正则项,通过减小回归系数
- L1正则化:可以将某些特征的回归系数变为0
- L1正则化API:Lasso回归
# 代码演示 from sklearn.linear_model import Lasso
- L2正则化:每次梯度下降迭代都减小特征前面的系数
- L2正则化API:岭回归
# 代码演示 from sklearn.linear_model import Ridge