引言
在机器学习领域,模型过拟合是一个常见且需要解决的问题。过拟合指的是模型在训练数据上表现良好,但在未知数据上表现不佳的现象。为了解决这一问题,我们引入了正则化的概念。正则化是一种旨在减少模型泛化误差的技术,而不是仅仅关注降低训练误差。
一,正则化的潦草定义
正则化是一种在损失函数中添加额外项的方法,这些额外项被称为惩罚项。通过这种方式,我们可以控制模型的复杂度,防止过拟合。通俗来说,正则化就是在保证模型拟合训练数据的同时,不让模型过于复杂。
正则化目的是减少泛化误差,而不是减少训练误差的方法。通俗点来讲就是我们常说的防止过拟合问题。
二,机器学习中的L1和L2正则化
预防针:
本文中不会去细究一些原理性的东西,点到为止重在理解。如果想要深入的探究正则化的知识,有一些些些些知识点是必须的,例如高等数学,线性代数。在正则化中具体就涉及到拉格朗日乘子法,矩阵运算,求偏导等等。
1)L1正则化
1.1 L1正则化的定义和图形解释
L1正则化,也称为Lasso回归,通过在损失函数中添加权重的绝对值之和作为惩罚项。这种正则化方法能够导致某些特征的权重为零,从而实现特征的稀疏性。(稀疏性要从权重矩阵来看)
图形解释:在二维空间中,L1正则化的可行域是一个菱形,而损失函数的等高线是圆形。两者的交点往往出现在坐标轴上,使得某些特征权重为零。这需要涉及到高数中的拉格朗日乘数法不展开叙述。
解释了L1正则化的稀疏性后,我就不得不提L1正则化的附带作用--降维或者说特征选择,因为有的特征权重置0了,所以减少了维度,此之谓降维。
1.2 L1正则化的公式表达
加入正则化的损失函数:
回归:loss = mse + penalty
分类:loss = cross entropy + penalty
举个栗子:
线性回归中L1正则化损失函数如下:
其中 就是L1正则项,也叫惩罚项。这个公式也就是Lasso回归。其中是一个很关键的参数,构建模型时都要选择合适的。
1.3 代码演示
两种方式实现L1正则化,一种是直接调用sklearn库中的Lasso模型,另外一种是调用SGD模型,如何再选择penalty的参数为L1。
import numpy as np
from sklearn.linear_model import Lasso
from sklearn.linear_model import SGDRegressor
X = np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
lasso = Lasso(alpha=0.0001)
lasso.fit(X, y)
print(f"lasso.coef_: {lasso.coef_}")
print(f"lasso.intercept_: {lasso.intercept_}")
print(f"lasso.score(X, y): {lasso.score(X, y)}")
print(f"lasso.predict([[1.5]]): {lasso.predict([[1.5]])}")
SGD = SGDRegressor(penalty='l1', alpha=0.0001)
SGD.fit(X, y)
print(f"SGD.coef_: {SGD.coef_}")
print(f"SGD.intercept_: {SGD.intercept_}")
print(f"SGD.score(X, y): {SGD.score(X, y)}")
print(f"SGD.predict([[1.5]]): {SGD.predict([[1.5]])}")
1.4 运行结果分析
当alpha = 0.0001
当alpha = 100
从运行结果可以看出的重要性,alpha较小时,模型具有较好的准确性,但是泛化能力下降。
2)L2正则化
2.1 L2正则化的定义和图形解释
L2正则化,也称为Ridge回归,通过在损失函数中添加权重的平方和作为惩罚项。这种方法可以防止权重过大,从而减少过拟合的风险,是机器学习中主要用来防止过拟合的一种方法。
图形解释:在二维空间中,L2正则化的可行域是一个圆,而损失函数的等高线仍然是圆形。图中交点恰巧是加入L2正则项后梯度为0的点,即在原损失函数加入可行域后的最优解。
2.2 L2正则化的公式表达
加入L2正则项后的损失函数(以线性模型为例子):
如公式所示,正是我前面所提到的L2正则项,前半部分则是线性模型的损失函数,两者相加组成了线性模型新的损失函数,加上了L2正则项的线性回归也叫做Ridge回归,这也是线性回归中常使用的模型,其重要性远大于本文中另外两种正则化手段。
2.3 代码演示
利用两种方式实现L2正则化也就是Ridge回归,一种是直接调用sklearn库中的Ridge模型,另外一种是调用SGD模型,如何再选择penalty的参数为L2:
import numpy as np
from sklearn.linear_model import Ridge
from sklearn.linear_model import SGDRegressor
from sklearn.model_selection import train_test_split
from matplotlib import pyplot as plt
import warnings
warnings.filterwarnings('ignore')
np.random.seed(888)
X = np.random.rand(1000, 1)
y = 4 + 3 * X + np.random.randn(1000, 1) # 4 + 3 * 2.5 = 11.5
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
ridge = Ridge(alpha=40, solver='sag')
ridge.fit(X_train, y_train)
y_pred = ridge.predict(X_test)
# print(ridge.score(X_test, y_test))
print(f"predicted value: {ridge.predict([[2.5]])}")
print(f"ridge-intercept: {ridge.intercept_}")
print(f"ridge-coef: {ridge.coef_}")
print(f"ridge-test-score: {ridge.score(X_test, y_test)}")
print(f"ridge-train-score: {ridge.score(X_train, y_train)}")
# print(ridge.predict(X))
plt.subplot(2, 2, 1)
plt.scatter(X_train, y_train, label='training data', alpha=0.5)
plt.plot(X_train, ridge.predict(X_train), color='red', label='X predicted values')
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.title("Ridge Regression")
plt.subplot(2, 2, 2)
plt.scatter(X_test, y_test, label='test data', alpha=0.5)
plt.plot(X_test, y_pred, color='red', label='y predicted values')
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.title("Ridge Regression")
# SGD = SGDRegressor(penalty='l2', alpha=0.01, max_iter=1000)
# SGD.fit(X_train, y_train)
# y_pred = SGD.predict(X_test)
# print(f"SGD-intercept: {SGD.intercept_}")
# print(f"SGD-coef: {SGD.coef_}")
# print(f"SGD-test-score: {SGD.score(X_test, y_test)}")
# print(f"SGD-train-score: {SGD.score(X_train, y_train)}")
#
#
#
# plt.subplot(2, 2, 3)
# plt.scatter(X_train, y_train, label='training data', alpha=0.5)
# plt.plot(X_train, SGD.predict(X_train), color='red', label='X predicted values')
# plt.xlabel("x")
# plt.ylabel("y")
# plt.legend()
# plt.title("SGD Regression", alpha=0.5)
#
#
# plt.subplot(2, 2, 4)
# plt.scatter(X_test, y_test, label='test data', alpha=0.5)
# plt.plot(X_test, y_pred, color='red', label='y predicted values')
# plt.xlabel("x")
# plt.ylabel("y")
# plt.legend()
# plt.title("SGD Regression", alpha=0.5)
#
# plt.show()
"""
alph = 0.1 :ridge-test-score: 0.36724058968086404 ridge-train-score: 0.45014082728080673 predicted value:[[11.55582906]] ridge-intercept:[4.02234733] ridge-coef:[[3.01339269]]
alph = 40 :ridge-test-score: 0.32660938942643847 ridge-train-score: 0.38265947478553686 predicted value: [[9.24292991]] ridge-intercept:[4.62003072] ridge-coef: [[1.84915967]]
观察可以发现L2正则化系数alpha越大,模型的泛化能力越强,但是模型的精度越低
"""
2.4 运行结果分析
3)L1+L2正则化
3.1 L1+L2定义
L1+L2正则化就是我们常说的ElasticNet,中文名叫做弹性网络,是一个训练时同时用L1和L2范数进行正则化的线性回归模型。
ElasticNet是L1和L2正则化的结合,它通过在损失函数中同时添加L1和L2惩罚项,既能够实现特征的稀疏性,又能够保持模型的稳定性。
3.2 L1+L2正则化的公式表达
3.3 代码演示
import numpy as np
from sklearn.linear_model import ElasticNet
from sklearn.linear_model import SGDRegressor
X = np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
es = ElasticNet(alpha=100, l1_ratio=0.5, random_state=0)
es.fit(X, y)
print(f"es.coef_: {es.coef_}")
print(f"es.intercept_: {es.intercept_}")
print(f"es.score(X, y): {es.score(X, y)}")
print(f"es.predict([[1.5]]): {es.predict([[1.5]])}")
sgd = SGDRegressor(random_state=0, penalty='elasticnet')
sgd.fit(X, y)
print(f"sgd.coef_: {sgd.coef_}")
print(f"sgd.intercept_: {sgd.intercept_}")
print(f"sgd.score(X, y): {sgd.score(X, y)}")
print(f"sgd.predict([[1.5]]): {sgd.predict([[1.5]])}")
3.4 运行结果分析
alph=100
alph=0.001
从结果中可以看出当越小的时候,模型的准确率越高,但是泛化能力下降
4) 小结
alpha较小:当alpha较小时,正则化的影响较弱,模型更倾向于保留更多的特征,这可能导致模型在训练数据上表现得很好,但在未见过的新数据上可能过拟合,泛化能力较差。
alpha较大:当alpha较大时,正则化的影响较强,模型会倾向于减少特征的数量,通过稀疏化或减小系数来降低模型的复杂度。这有助于防止过拟合,提高模型在新数据上的泛化能力。但是,如果alpha过大,模型可能会变得过于简单,导致欠拟合,无法捕捉数据中的关键关系,泛化能力同样会变差。
因此,选择合适的alpha值是关键:
交叉验证:通常使用交叉验证来选择最佳的alpha值。交叉验证可以帮助我们找到在验证集上表现最好的alpha值,从而平衡模型的复杂度和泛化能力。
模型选择:在实际应用中,可能需要尝试不同的alpha值,并观察模型在验证集上的表现,以选择最佳的alpha。
三,总结
1)每种正则化的特点和使用场景
L1正则化(Lasso):适用于特征选择,能够产生稀疏模型。
L2正则化(Ridge):适用于特征数量多且相互关联的数据,可以保持模型的稳定性。
ElasticNet:结合了L1和L2正则化的特点,适用于同时需要特征选择和保持模型稳定性的场景。
2)正则化的实际应用
在实际应用中,应根据数据的特点和业务需求选择合适的正则化方法。通常,可以通过交叉验证来确定正则化参数的最佳值。
3)研究价值
未来的研究可以进一步探讨正则化方法在不同类型数据上的表现,以及如何更有效地结合多种正则化技术,以提高模型的泛化能力和解释性。此外,如何将正则化方法应用于深度学习模型,以解决过拟合问题,也是一个值得研究的方向。
标签:plt,--,正则,train,alpha,print,潦草,SGD From: https://blog.csdn.net/m0_75210954/article/details/143491220