之前我们讨论了许多关于优化的算法,随着模型的优化算法在不断的改进使得模型的学习能力越来越强,那么如果模型的学习能力过强,就会导致模型的过拟合问题,因此今天我们来介绍一下机器学习中防止模型过拟合的方法—岭回归。
通常在我们设计一个机器学习模型时,我们会确定好输入与输出,定义一个成本函数来衡量模型的效果,训练一个模型的核心思想是将成本函数降到最低,而为了降低成本函数,通常我们会增加数据特征数量,随着特征数量的增加,模型的效果会有所提高,成本函数在逐渐下降,但同时特征数量的增加也会增加特征空间维度,模型变得复杂化,根据偏差-方差理论,模型就会产生过拟合的问题,即模型在当前数据集上表现良好,要是换个新的数据集模型效果就会大幅降低。
从上图可以看出,过度拟合模型在训练数据集上表现良好,其成本函数为零。但是,当我们使用上图中的测试数据集测试此模型时,模型效果十分的差。模型的预测值和目标值相差很大。
那么岭回归是如何解决过拟合的问题呢?
答:岭回归用于控制模型系数的大小来防止过度拟合。岭回归通过在成本函数中加入模型参数的正则项以平衡数据的拟合和系数的大小。即岭回归成本= RSS(W)+λ* || W ||²=(Y - WH)*(Y - WH)+ WW,在矩阵表示法中写为:岭回归成本=(Y - HW)ᵗ(Y - HW)+WᵗW。
在求解岭回归的成本函数时,通常使用梯度下降的思想,将上式方程求微分得:
Δ[RSS(W) + λ||W||]²
= Δ{(Y - HW)ᵗ(Y - HW)} + λ Δ{WᵗW}
= -2Hᵗ(Y - HW)+2λW
令上式等于0得到:
W = (HᵗH + λI)-¹HᵗY
λ值是一个调整的参数,在确定λ值时,我们将数据分为三部分,即训练集、验证集和测试集。
训练集:此数据集将用于获取每个λ值的W系数值。
验证集:将不同的w ^ λ值在验证集上进行评估。选择代价函数最小的那个。
测试集:再次通过测试数据集评估W系数。
下面提供一个使用梯度下降进行岭回归求解的例子。例子来源文末博客。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error
data = np.array([[ -2.95507616, 10.94533252],
[ -0.44226119, 2.96705822],
[ -2.13294087, 6.57336839],
[ 1.84990823, 5.44244467],
[ 0.35139795, 2.83533936],
[ -1.77443098, 5.6800407 ],
[ -1.8657203 , 6.34470814],
[ 1.61526823, 4.77833358],
[ -2.38043687, 8.51887713],
[ -1.40513866, 4.18262786]])
m = data.shape[0] # 样本大小
X = data[:, 0].reshape(-1, 1) # 将array转换成矩阵
y = data[:, 1].reshape(-1, 1)
# 代价函数
def L_theta(theta, X_x0, y, lamb):
"""
lamb: lambda, the parameter of regularization
theta: (n+1)·1 matrix, contains the parameter of x0=1
X_x0: m·(n+1) matrix, plus x0
"""
h = np.dot(X_x0, theta) # np.dot 表示矩阵乘法
theta_without_t0 = theta[1:]
L_theta = 0.5 * mean_squared_error(h, y) + 0.5 * lamb * np.sum(np.square(theta_without_t0))
return L_theta
# 梯度下降
def GD(lamb, X_x0, theta, y, alpha):
"""
lamb: lambda, the parameter of regularization
alpha: learning rate
X_x0: m·(n+1), plus x0
theta: (n+1)·1 matrix, contains the parameter of x0=1
"""
for i in range(T):
h = np.dot(X_x0, theta)
theta_with_t0_0 = np.r_[np.zeros([1, 1]), theta[1:]] # set theta[0] = 0
theta -= (alpha * 1/m * np.dot(X_x0.T, h - y) + lamb*(theta_with_t0_0)) # add the gradient of regularization term
if i%50000==0:
print(L_theta(theta, X_x0, y, lamb))
return theta
T = 1200000 # 迭代次数
degree = 11
theta = np.ones((degree + 1, 1)) # 参数的初始化,degree = 11,一个12个参数
alpha = 0.0000000006 # 学习率
# alpha = 0.003 # 学习率
lamb = 0.0001
# lamb = 0
poly_features_d = PolynomialFeatures(degree=degree, include_bias=False)
X_poly_d = poly_features_d.fit_transform(X)
X_x0 = np.c_[np.ones((m, 1)), X_poly_d] # ADD X0 = 1 to each instance
theta = GD(lamb=lamb, X_x0=X_x0, theta=theta, y=y, alpha=alpha)
参考
https://towardsdatascience.com/machine-learning-ridge-regression-in-detail-76787a2f8e2d
博客(该博客提供多种岭回归求解方法)
https://www.cnblogs.com/Belter/p/8536939.html