机器学习笔记(十八):模型正则化

凌云时刻 · 技术

导读:上一篇我们在验证数据集概念的基础上讲了交叉验证。这一篇我们继续来讲模型正则化。

作者 | 计缘

来源 | 凌云时刻(微信号:linuxpk)

模型正则化(Regularization)

在说模型正则化之前,我们先来看一个例子:

  

import numpy as np
import matplotlib.pyplot as plt

# 构建和之前一样的样本数据
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)

# 将这些的折线图绘制出来
plt.plot(np.sort(x), y[np.argsort(x)], color='r')
plt.show()

可以看到当计算y的方程,多项式前的系数比较低(0.5和1)的时候折线图在横轴从-3到3,纵轴从-1到10的坐标系里还能全部展现,如果将这两个系数扩大10倍,会出现什么情况呢:

  

y1 = 5 * x ** 2 + 10 * x + 2 + np.random.normal(0, 1, size=100)
plt.plot(np.sort(x), y1[np.argsort(x)], color='r')
plt.axis([-3, 3, -1, 10])
plt.show()

可以看到这个折线图波动已经非常大了,在同样的坐标系中只能展现出一部分了。我们再来回顾一下前面的那张过拟合的图:

上图中,两侧的曲线图波动非常大,其实就说明了这条曲线的线性多项式方程的系数非常大,那么模型正则化做的事情就是限制这些系数的大小。

下面来看看模型正则化的基本思路,在第四篇笔记中将多元线性回归问题的时候,我们知道最终求的是下面这个函数的最优解,既让下面这个损失函数的值尽可能的小:

   

下面我们来转变一下这个损失函数:

   

我们在损失函数里加了一‍‍部分   ,此‍‍时要想让损失函数尽可能的小,就不能只考虑前面那一部分了,还要考虑后面新加的这一部分,又因为后面这部分包含多项式系数的平方,所以就整体约束了多项式系数的大小。这就是模型正则化的基本思路。

这里‍‍的   就是‍‍一个新的超参数,它的含义代表在模型正则化下,新的损失函数中每一‍‍个   都尽可能‍‍的小,这个小的程度占整个优化损失函数的多少。比如如果‍‍   ‍‍是0,那么相当于损失函数没有加入模型正则化,如‍‍果   ‍‍非常非常大,那么真正的损失函数就可以忽略了,主要考虑使模型正则化中‍‍的   ‍‍尽可能小。所以   ‍‍的作用就是让真正的损失函数尽可能小和新加入的模型正则化中的‍‍   尽‍‍可能小之间找到一个平衡,在实际的运用中,不同的数据‍‍,   的‍‍取值也不同,是需要有不断调‍‍整   这个‍‍超参数的过程。

 岭回归(Ridge Regression)

在模型正‍‍则化中,加入   的‍‍方式,称之为岭回归。下面通过不使用模型正则化和使用岭回归对比来看看:

 

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 + 3 + np.random.normal(0, 1, size=100)

plt.scatter(x, y)
plt.show()

 

# 导入Pipeline和其他需要打包进Pipeline的类
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

# 将样本数据集拆分为训练数据集和测试数据集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=666)

# 构建多项式线性回归Pipeline
def PloynomialRegression(degree):
	return Pipeline([
		("poly", PolynomialFeatures(degree=degree)),
		("std_scalar", StandardScaler()),
		("lr", LinearRegression())
	])

# 导入均方误差MSE函数
from sklearn.metrics import mean_squared_error

ploy_reg = PloynomialRegression(degree=20)
ploy_reg.fit(X_train, y_train)
y_poly_predict = ploy_reg.predict(X_test)
mean_squared_error(y_test, y_poly_predict)
# 结果
1.9558727426614517

X_ploy = np.linspace(-3, 3, 100).reshape(100, 1)
y_ploy = ploy_reg.predict(X_ploy)

plt.scatter(x, y)
plt.plot(X_ploy[:, 0], y_ploy, color='r')
plt.axis([-3, 3, 0, 6])
plt.show()

可以看到不试用模型正则化时,MSE为1.95,虽然数值不大,但是拟合曲线的波动非常大,是一个过拟合的特征。下面来看看使用模型正则化岭回归后结果会怎样:

 

# 导入Scikit Learn中岭回归的类Ridge
from sklearn.linear_model import Ridge

# 构建通过岭回归进行模型正则化的Pipeline,有两个超参数degree和alpha
def RidgeRegression(degree, alpha):
	return Pipeline([
		("poly", PolynomialFeatures(degree=degree)),
		("std_scalar", StandardScaler()),
		("rr", Ridge(alpha=alpha))
	])

ridge_reg = RidgeRegression(20, 0.0001)
ridge_reg.fit(X_train, y_train)

y_ridge_predict = ridge_reg.predict(X_test)
mean_squared_error(y_test, y_ridge_predict)
# 结果
1.0033258623784587

X_ridge = np.linspace(-3, 3, 100).reshape(100, 1)
y_ridge = ridge_reg.predict(X_ridge)

plt.scatter(x, y)
plt.plot(X_ridge[:, 0], y_ridge, color='r')
plt.axis([-3, 3, 0, 6])
plt.show()

使用岭回归后MSE降低到1,并且拟合曲线波动平缓了许多,尤其是曲线两头。这就是模型正则化的作用。


 LASSO 回归(Least Absolute Shrinkage and Selection Operator Regression)

其实岭回归和LASSO都是模型正则化的一种具体实现,区别就在于增加的模型正则公式不同。岭回归增加的‍‍是   ,‍‍而LASSO回归中增加的‍‍‍‍是   。

下面来看看相同的数据使用LASSO回归后的结果:

 

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 + 3 + np.random.normal(0, 1, size=100)

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=666)

# 导入Pipeline和其他需要打包进Pipeline的类
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import Lasso
from sklearn.metrics import mean_squared_error

def LassoRegression(degree, alpha):
	return Pipeline([
		("poly", PolynomialFeatures(degree=degree)),
		("std_scalar", StandardScaler()),
		("lasso", Lasso(alpha=alpha))
	])

lasso_reg = LassoRegression(20, 0.01)
lasso_reg.fit(X_train, y_train)

y_lasso_predict = lasso_reg.predict(X_test)
mean_squared_error(y_test, y_lasso_predict)
# 结果
0.90488682905372464

X_lasso = np.linspace(-3, 3, 100).reshape(100, 1)
y_lasso = lasso_reg.predict(X_lasso)

plt.scatter(x, y)
plt.plot(X_lasso[:, 0], y_lasso, color='r')
plt.axis([-3, 3, 0, 6])
plt.show()

可以看到相同的数据,通过LASSO处理后的模型MSE更小一些,拟合曲线也更平滑。



 岭回归和LASSO回归的数学含义上的区别

下面来解释一下岭回归和LASSO回归之间深层意义上的区别。先来看看岭回归,在前面讲过,‍‍当   ‍‍趋近无穷大时,真正的损失函数就可以忽略了,模型正则化后的损失函数就变成了求解模型正则公式的最小值,‍‍既求   的最小值,那么该公式的梯度就是对‍‍   求‍‍导可得: 

数据点按照梯度一步一步寻求最优解,如下图:

 

所以经过岭回归处理后训练出的模型,拟合线基本都是曲线。

再来看看LASSO回归,‍‍当   ‍‍趋近无穷大时,我们只考虑   ,但是   是不可导的,我们使用数学符号函数来表示其梯度:

符号函数   是很有用的一类函数,能够帮助我们实现一些直接实现有困难的情况。在数学和计算机运算中,其功能是取某个数的符号(正或负),既当   时,   ,当   时,   ,当   时,   。 

 

对于   而言,当   时,就相当于   这条直线,当   时,就相当于   这条直线。当数据点按照LASSO的梯度寻找最优解的路线是下图情况:

可以看到真正的寻址路线是橘黄色的虚线,应该中间有很多点直接打到了   轴,所以绘制出的拟合蓝色线很多时候就是一条直线,而不是曲线。那些   为0的梯度,既损失函数中的一部分   为0,这也就说明了LASSO中最后的SO(Selection Operator)选择操作符的含义,既将一些噪音比较大的特征过滤掉,选择出主要的、有用的特征。但是这是有风险的,因为很有可能LASSO将实际有用的特征给过滤掉了,所以就模型正则化的准确率来说,岭回归还是更好一些。但是在处理有巨大量特征的样本数据时,使用LASSO可以作为降低特征数量的一种方法。

LP范数

在数学定义上,范数包括向量范数和矩阵范数,向量范数表示向量空间中向量的大小,矩阵范数表征矩阵引起向量变化的大小。比如对于向量范数,向量空间中的向量都是有大小的,这个大小如何度量,就是用范数来度量的,不同的范数都可以来度量这个大小,就好比米和尺都可以来度量远近一样。对于矩阵范数,我们知道,通过运算   ,可以将向量   变化为矩阵   ,矩阵范数就是来度量这个变化大小的。

下面我们再来看一张图:

上图展示了模型正则化岭回归、LASSO回归,线性回归评测标准均方误差(MSE)、平均绝对误差(MAE),距离公式欧拉距离、曼哈顿距离之间的对比。我们可以发现一个很有意思的现象,第一行的三个公式都是平方求和的模式,第二行的三个公式都是绝对值求和的模式。其实虽然机器学习中的公式、名词很多,但是究其背后的数学原理都是有规律可循的。

我们在讲KNN时知道它除了   这个超参数外还有一个超参数   ,继而介绍了明可夫斯基距离:

   

我们对明可夫斯基距离公式再进行一下泛化,将其提炼成这种形式:

   

在数学上,我们将上面这个公式称为   范数,当   为1时,   范数就是曼哈顿距离,   为2时,   范数就是欧拉距离。那么在模型正则项中,是   范数就是岭回归,或者叫   正则项,   范数就是LASSO回归,或者叫   正则化。

这里要注意的时,如果是   范数,岭回归的模型正则化公式应该还需要开根号,但是为了计算方便,一般使用时不加这个开根号,但是加不加根号对于模型正则化的效果来说是一样的。

 弹性网(Elastic Net)

弹性网很简单,就是将   正则项和   正则项都加入模型正则化中,既结合了岭回归和LASSO回归:

   

   

公式中看到我们又引入了一个超参数   ,这个超参数表示岭回归和LASSO回归在整个模型正则化中各占的比例。

  

 

END

往期精彩文章回顾

机器学习笔记(十七):交叉验证

机器学习笔记(十六):多项式回归、拟合程度、模型泛化

机器学习笔记(十五):人脸识别

机器学习笔记(十四):主成分分析法(PCA)(2)

机器学习笔记(十三):主成分分析法(PCA)

机器学习笔记(十二):随机梯度下降

机器学习笔记(十一):优化梯度公式

机器学习笔记(十):梯度下降

机器学习笔记(九):多元线性回归

机器学习笔记(八):线性回归算法的评测标准

长按扫描二维码关注凌云时刻

每日收获前沿技术与科技洞见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值