【机器学习】欠拟合、过拟合和正则化
1 欠拟合和过拟合
1.1 欠拟合
欠拟合是指模型在训练数据上表现不佳,在测试数据上同样表现不佳。这种问题通常是由于模型结构过于简单,无法捕捉数据中过于复杂的特征。欠拟合模型有如下特征:
- 训练误差较高
- 测试误差同样较高
- 模型过于简化,没能充分学习训练数据中的模式
1.2 过拟合
过拟合是指模型在训练数据上表现良好,但在新的未见过的数据上表现较差。这通常是由于模型过于复杂,过分学习了数据中噪点和细节。过拟合模型有如下特征:
- 训练误差较低
- 测试误差较高
- 模型可能过于复杂,以至于它对训练数据进行了过度拟合。
2 正则化
2.1 正则化的概念
- 正则化(Regularization) 是机器学习中对原始损失函数引入额外信息,以便防止过拟合和提高模型泛化性能的一类方法的统称。也就是目标函数变成了原始损失函数+额外项,常用的额外项一般有两种,中文称作L1正则化和L2正则化,或者L1范数和L2范数(实际是L2范数的平方)。
- L1正则化和L2正则化可以看做是损失函数的惩罚项。所谓惩罚是指对损失函数中的某些参数做一些限制。对于线性回归模型,使用L1正则化的模型叫做Lasso回归,使用L2正则化的模型叫做Ridge回归(岭回归)。
- 线性回归L1正则化损失函数:
- 线性回归L2正则化损失函数:
- 公式(1)(2)中w表示特征的系数(x的参数),可以看到正则化项是对系数做了限制。L1正则化和L2正则化的说明如下:
- L1正则化是指权值向量w中各个元素的绝对值之和,通常表示为||w||1
- L2正则化是指权值向量w中各个元素的平方和然后再求平方根(可以看到Ridge回归的L2正则化项有平方符号),通常表示为∥w||2
- 一般都会在正则化项之前添加一个系数λ。Python中用α表示,这个系数需要用户指定(也就是我们要调的超参)。
2.2 正则化的作用
-
L1正则化可以使得参数稀疏化,即得到的参数是一个稀疏矩阵,可以用于特征选择。
- 稀疏性,说白了就是模型的很多参数是0。通常机器学习中特征数量很多,例如文本处理时,如果将一个词组(term)作为一个特征,那么特征数量会达到上万个(bigram)。在预测或分类时,那么多特征显然难以选择,但是如果代入这些特征得到的模型是一个稀疏模型,很多参数是0,表示只有少数特征对这个模型有贡献,绝大部分特征是没有贡献的,即使去掉对模型也没有什么影响,此时我们就可以只关注系数是非零值的特征。这相当于对模型进行了一次特征选择,只留下一些比较重要的特征,提高模型的泛化能力,降低过拟合的可能。
-
L2正则化可以防止模型过拟合(overfitting);一定程度上,L1也可以防止过拟合。
2.3 岭回归Ridge
2.3.1 损失函数公式
岭回归是失损函数通过添加所有权重的平方和的乘积(L2)来惩罚模型的复杂度。
均方差除以2是因为方便求导, w j w_j wj指所有的权重系数, λ指惩罚型系数,又叫正则项力度
特点:
- 岭回归不会将权重压缩到零,这意味着所有特征都会保留在模型中,但它们的权重会被缩小。
- 适用于特征间存在多重共线性的情况。
- 岭回归产生的模型通常更为平滑,因为它对所有特征都有影响。
2.3.2 API
具有L2正则化的线性回归-岭回归。
sklearn.linear_model.Ridge()
1 参数:
(1)alpha, default=1.0,正则项力度
(2)fit_intercept, 是否计算偏置, default=True
(3)solver, {‘auto’, ‘svd’, ‘cholesky’, ‘lsqr’, ‘sparse_cg’, ‘sag’, ‘saga’, ‘lbfgs’}, default=’auto’
当值为auto,并且数据量、特征都比较大时,内部会随机梯度下降法。
(4)normalize:,default=True, 数据进行标准化,如果特征工程中已经做过标准化,这里就该设置为False
(5)max_iterint, default=None,梯度解算器的最大迭代次数,默认为150002 属性
coef_ 回归后的权重系数
intercept_ 偏置说明:SGDRegressor也可以做岭回归的事情,比如SGDRegressor(penalty='l2',loss="squared_loss"),但是其中梯度下降法有些不同。所以推荐使用Ridge实现岭回归
2.3.3 示例
岭回归 加载加利福尼亚住房数据集,进行回归预测
# 岭回归 加载加利福尼亚住房数据集,进行回归预测
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge
from sklearn.metrics import mean_squared_errorfrom sklearn.datasets import fetch_california_housing
# 1)加载数据
housing = fetch_california_housing(data_home="./src")
print(housing)
# 2)划分训练集与测试集
x_train, x_test, y_train, y_test = train_test_split(housing.data, housing.target, random_state=22)
# 3)标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)# 4)岭回归预估器
estimator = Ridge(alpha=0.5, max_iter=10000)
estimator.fit(x_train, y_train)# 5)得出模型
print("权重系数为:\n", estimator.coef_) #权重系数与特征数一定是同样的个数。
print("偏置为:\n", estimator.intercept_)# 6)模型评估
y_predict = estimator.predict(x_test)
print("预测的数据集:\n", y_predict)
error = mean_squared_error(y_test, y_predict)
print("均方误差为:\n", error)
2.4 拉索回归Lasso
2.4.1 损失函数公式
Lasso回归是一种线性回归模型,它通过添加所有权重的绝对值之和(L1)来惩罚模型的复杂度。
Lasso回归的目标是最小化以下损失函数:
J(w) = 1 2 n ∑ i = 1 n ( h w ( x i ) − y i ) 2 + λ ∑ j = 1 p ∣ w j ∣ \text{J(w)}= \frac{1}{2n}\sum_{i=1}^n (h_w(x_i)-y_i)^2 + \lambda \sum_{j=1}^p |w_j| J(w)=2n1∑i=1n(hw(xi)−yi)2+λ∑j=1p∣wj∣
其中:
- $n $ 是样本数量,
- $ p $ 是特征的数量,
- $ y_i $是第 $ i $ 个样本的目标值,
- $ x_i $ 是第 $ i $ 个样本的特征向量,
- w w w是模型的参数向量,
- $\lambda $ 是正则化参数,控制正则化项的强度。
特点:
- 拉索回归可以将一些权重压缩到零,从而实现特征选择。这意味着模型最终可能只包含一部分特征。
- 适用于特征数量远大于样本数量的情况,或者当特征间存在相关性时,可以从中选择最相关的特征。
- 拉索回归产生的模型可能更简单,因为它会去除一些不重要的特征。
2.4.2 API
sklearn.linear_model.Lasso()参数:1. **alpha (float, default=1.0)**:- 控制正则化强度;必须是非负浮点数。较大的 alpha 增加了正则化强度。
2. **fit_intercept (bool, default=True)**:- 是否计算此模型的截距。如果设置为 False,则不会使用截距(即数据应该已经被居中)。
3. **precompute (bool or array-like, default=False)**:- 如果为 True,则使用预计算的 Gram 矩阵来加速计算。如果为数组,则使用提供的 Gram 矩阵。
4. **copy_X (bool, default=True)**:- 如果为 True,则复制数据 X,否则可能对其进行修改。
5. **max_iter (int, default=1000)**:- 最大迭代次数。
6. **tol (float, default=1e-4)**:- 精度阈值。如果更新后的系数向量减去之前的系数向量的无穷范数除以 1 加上更新后的系数向量的无穷范数小于 tol,则认为收敛。
7. **warm_start (bool, default=False)**:- 当设置为 True 时,再次调用 fit 方法会重新使用之前调用 fit 方法的结果作为初始估计值,而不是清零它们。
8. **positive (bool, default=False)**:- 当设置为 True 时,强制系数为非负。
9. **random_state (int, RandomState instance, default=None)**:- 随机数生成器的状态。用于随机初始化坐标下降算法中的随机选择。
10. **selection ({'cyclic', 'random'}, default='cyclic')**:- 如果设置为 'random',则随机选择坐标进行更新。如果设置为 'cyclic',则按照循环顺序选择坐标。属性:1. **coef_**- 系数向量或者矩阵,代表了每个特征的权重。
2. **intercept_ **- 截距项(如果 fit_intercept=True)。
3. **n_iter_ **- 实际使用的迭代次数。
4. **n_features_in_ (int)**:- 训练样本中特征的数量。
2.4.3 示例
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import Lasso
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import numpy as np# 加载波士顿房价数据集
data = fetch_california_housing(data_home="./src")
X, y = data.data, data.target# 划分训练集和测试集
X_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 创建Lasso回归模型
lasso = Lasso(alpha=0.1) # alpha是正则化参数# 训练模型
lasso.fit(X_train, y_train)# 得出模型
print("权重系数为:\n", lasso.coef_) #权重系数与特征数一定是同样的个数。
print("偏置为:\n", lasso.intercept_)#模型评估
y_predict = lasso.predict(x_test)
print("预测的数据集:\n", y_predict)
error = mean_squared_error(y_test, y_predict)
print("均方误差为:\n", error)