正则化&拟合
-
- [一 正则化](#一 正则化)
-
- [1.1 概述](#1.1 概述)
- [1.2 分类](#1.2 分类)
-
- [1.2.1 L1正则化](#1.2.1 L1正则化)
- [1.2.2 L2正则化](#1.2.2 L2正则化)
- [二 拟合](#二 拟合)
-
- [2.1 概述](#2.1 概述)
- [2.2 分类](#2.2 分类)
-
-
[2.2.1 欠拟合](#2.2.1 欠拟合)
-
[2.2.2 过拟合](#2.2.2 过拟合)
-
[2.2.3 正好拟合](#2.2.3 正好拟合)
在算法中我们可以通过算法的时间复杂度和空间复杂度来评估算法的好坏。那在机器学习中如何判断一个模型的优劣呢?
此时我们就需要观察模型拟合(当然还会用到模型评估时的各种指标今天不聊),当出现了不同的拟合情况又将如何解决呢?
正则化就是一个不错的选择。有了这个基本思路跟着小编进入今天的分享,我们先从正则化说起。
-
一 正则化
1.1 概述
在机器学习中数据提供的特征有些影响模型复杂度(或者这个特征的数据点异常较多),所以算法在学习的时候尽量减少这个特征的影响(有时甚至删除某个特征的影响),这个过程就是正则化。
1.2 分类
1.2.1 L1正则化
L1正则化会使得特征的权重变为0, 一般适用于: 特征选取。
python
# 代码模拟L1正则化
# 0.导包
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression # 线性回归-正规方程模型
from sklearn.metrics import mean_squared_error # 计算均方误差
from sklearn.linear_model import Lasso # L1正则化
def dm_L1正则化():
# 1.准备数据
# 准备噪声(简单理解为随机种子),噪声相同 每次生成的随机点数相同(噪声点形成的图相同)
np.random.seed(21)
# x 表示特征 -3-3之间 随机的小数 生成100个
x = np.random.uniform(-3, 3, size=100)
# y 表示标签(目标值) 存在线性关系 y=0.5x² + x +2 + 正态分布 + 噪声
# np.random.normal(0,1,size=100) 意思是均值为0 标准差为1 生成100个
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练
# 2.创建线性回归-L1正则化 模型对象
estimator = Lasso(alpha=0.1) # alpha : 阿尔法 正则化参数 值越大正则化程度越高 权重值越小 越可能变成0
# 3.对数据集做处理
# 3.1把数据从一维数据=>2维数据
X = x.reshape(-1, 1)
# 3.2 拼接x 和 x的平方 把数据从[[1],[2],[3]] => [[1,1,1...],[2,4,8,16..],[3,9,27,81..]] 即一元线性回归=>二元线性回归
X3 = np.hstack([X, X ** 2, X ** 3, X ** 4, X ** 5, X ** 6, X ** 7, X ** 8, X ** 9, X ** 10])
# 4.模型训练
estimator.fit(X3, y) # 传入处理后的X值
# 5. 模型预测
y_predict = estimator.predict(X3)
print(f'预测结果为:{y_predict}')
# 6.模型评估
print(f'均方误差{mean_squared_error(y, y_predict)}')
# 7. 数据可视化绘制图像
plt.scatter(x, y) # 基于原始的x(特征),y(真实值)绘制散点图
# np.sort(x) 按照x值的升序排列
# np.argsort(x) 按照x值的升序排列 返回(x对应的)索引值
plt.plot(np.sort(x), y_predict[np.argsort(x)], c='r') # 基于原始的x(特征)y(预测值)绘制折线图(即 拟合回归线)
plt.show()
if __name__ == '__main__':
dm_L1正则化()
1.2.2 L2正则化
L2正则化会使得特征的权重趋向于0, 不会变为零. 解决过拟合问题的首选。
python
# 代码模拟L2正则化
# 0.导包
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression # 线性回归-正规方程模型
from sklearn.metrics import mean_squared_error # 计算均方误差
from sklearn.linear_model import Ridge # L2 正则化
def dm_L2正则化():
# 1.准备数据
# 准备噪声(简单理解为随机种子),噪声相同 每次生成的随机点数相同(噪声点形成的图相同)
np.random.seed(21)
# x 表示特征 -3-3之间 随机的小数 生成100个
x = np.random.uniform(-3, 3, size=100)
# y 表示标签(目标值) 存在线性关系 y=0.5x² + x +2 + 正态分布 + 噪声
# np.random.normal(0,1,size=100) 意思是均值为0 标准差为1 生成100个
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练
# 2.创建线性回归-L1正则化 模型对象
estimator = Ridge(alpha=0.1) # alpha : 阿尔法 正则化参数 值越大正则化程度越高 权重值越小 越去向0
# 3.对数据集做处理
# 3.1把数据从一维数据=>2维数据
X = x.reshape(-1, 1)
# 3.2 拼接x 和 x的平方 把数据从[[1],[2],[3]] => [[1,1,1...],[2,4,8,16..],[3,9,27,81..]] 即一元线性回归=>二元线性回归
X3 = np.hstack([X, X ** 2, X ** 3, X ** 4, X ** 5, X ** 6, X ** 7, X ** 8, X ** 9, X ** 10])
# 4.模型训练
estimator.fit(X3, y) # 传入处理后的X值
# 5. 模型预测
y_predict = estimator.predict(X3)
print(f'预测结果为:{y_predict}')
# 6.模型评估
print(f'均方误差{mean_squared_error(y, y_predict)}')
# 7. 数据可视化绘制图像
plt.scatter(x, y) # 基于原始的x(特征),y(真实值)绘制散点图
# np.sort(x) 按照x值的升序排列
# np.argsort(x) 按照x值的升序排列 返回(x对应的)索引值
plt.plot(np.sort(x), y_predict[np.argsort(x)], c='r') # 基于原始的x(特征)y(预测值)绘制折线图(即 拟合回归线)
plt.show()
if __name__ == '__main__':
dm_L2正则化()
二 拟合
2.1 概述
机器学习中我们常把模型对样本分布点的模拟情况称作拟合,用于判断模型的优劣。
泛化 Generalization :模型在新数据集(非训练数据)上的表现好坏的能力。
奥卡姆剃刀原则:给定两个具有相同泛化误差的模型,较简单的模型比较复杂的模型更可取。
2.2 分类
2.2.1 欠拟合
欠拟合(Underfitting):模型在训练集和测试集上的表现都很差。
原因:模型过于简单无法捕捉数据的模式。大概是机器学习算法没有充分迭代来最小化误差。
代码模拟:
python
# 0.导包
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression # 线性回归-正规方程模型
from sklearn.metrics import mean_squared_error # 计算均方误差
def dm01_欠拟合():
# 1.准备数据
# 准备噪声(简单理解为随机种子),噪声相同 每次生成的随机点数相同(噪声点形成的图相同)
np.random.seed(21)
# x 表示特征 -3-3之间 随机的小数 生成100个
x = np.random.uniform(-3,3,size=100)
# y 表示标签(目标值) 存在线性关系 y=0.5x² + x +2 + 正态分布 + 噪声
# np.random.normal(0,1,size=100) 意思是均值为0 标准差为1 生成100个
y = 0.5* x **2 + x +2 + np.random.normal(0,1,size=100)
# 模型训练
# 2.创建线性回归-正规方程 模型对象
estimator = LinearRegression(fit_intercept=True) # 计算偏置
# 3.对数据集做处理
X = x.reshape(-1,1)
# 4.模型训练
estimator.fit(X,y) # 传入处理后的X值
# 5. 模型预测
y_predict = estimator.predict(X)
print(f'预测结果为:{y_predict}')
# 6.模型评估
print(f'均方误差{mean_squared_error(y,y_predict)}')
# 7. 数据可视化绘制图像
plt.scatter(x,y) # 基于原始的x(特征),y(真实值)绘制散点图
plt.plot(x,y_predict,c='r') # 基于原始的x(特征)y(预测值)绘制折线图(即 拟合回归线)
plt.show()
if __name__ == '__main__':
dm01_欠拟合()
解决方法:
python
# 增加模型复杂度:
如果使用的是线性模型,尝试添加多项式特征或使用非线性模型。
在神经网络中增加层数或每层的节点数。
# 特征工程:
增加更多输入特征,可以包括组合现有特征创建新的特征。
使用特征选择技术,确保使用的特征是与目标变量强相关的。
# 减少正则化强度:
如果正在使用正则化来防止过拟合,可以减小正则化参数λ,使其对模型复杂度的影响减弱。
# 更多的训练迭代:
如果使用的是迭代优化算法(如梯度下降),确保允许足够多的迭代次数以达到收敛。
# 增加训练数据量:
虽然欠拟合通常是由于模型过于简单,但是增加训练数据量有时也能帮助模型更好地学习数据分布。
# 调整超参数:
对于一些模型来说,调整学习率、批大小等超参数可能会有所帮助。
# 使用集成方法:
尝试使用集成学习方法,比如随机森林或者梯度提升树等,这些方法通过组合多个弱学习器来构建更强的学习器。
# 检查数据质量:
确保数据没有异常值或错误,因为这些问题可能会影响模型的学习过程。
# 验证数据划分:
检查是否正确地分割了训练集和测试集,并且它们具有相似的数据分布。
2.2.2 过拟合
过拟合(Overfitting):模型在训练集上表现很好,但在测试集上表现较差。
原因:模型学习到了数据中的噪声而不是数据的真实趋势。
代码模拟:
python
# 0.导包
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression # 线性回归-正规方程模型
from sklearn.metrics import mean_squared_error # 计算均方误差
def dm02_过拟合():
# 1.准备数据
# 准备噪声(简单理解为随机种子),噪声相同 每次生成的随机点数相同(噪声点形成的图相同)
np.random.seed(21)
# x 表示特征 -3-3之间 随机的小数 生成100个
x = np.random.uniform(-3,3,size=100)
# y 表示标签(目标值) 存在线性关系 y=0.5x² + x +2 + 正态分布 + 噪声
# np.random.normal(0,1,size=100) 意思是均值为0 标准差为1 生成100个
y = 0.5* x **2 + x +2 + np.random.normal(0,1,size=100)
# 模型训练
# 2.创建线性回归-正规方程 模型对象
estimator = LinearRegression(fit_intercept=True) # 计算偏置
# 3.对数据集做处理
# 3.1把数据从一维数据=>2维数据
X = x.reshape(-1,1)
# 3.2 拼接x 和 x的平方 把数据从[[1],[2],[3]] => [[1,1,1...],[2,4,8,16..],[3,9,27,81..]] 即一元线性回归=>二元线性回归
X3 = np.hstack([X,X**2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10])
# 4.模型训练
estimator.fit(X3,y) # 传入处理后的X值
# 5. 模型预测
y_predict = estimator.predict(X3)
print(f'预测结果为:{y_predict}')
# 6.模型评估
print(f'均方误差{mean_squared_error(y,y_predict)}')
# 7. 数据可视化绘制图像
plt.scatter(x,y) # 基于原始的x(特征),y(真实值)绘制散点图
# np.sort(x) 按照x值的升序排列
# np.argsort(x) 按照x值的升序排列 返回(x对应的)索引值
plt.plot(np.sort(x),y_predict[np.argsort(x)],c='r') # 基于原始的x(特征)y(预测值)绘制折线图(即 拟合回归线)
plt.show()
if __name__ == '__main__':
dm02_过拟合()
解决方法:
python
# 简化模型:
减少模型的复杂度,例如减少神经网络中的层数或每层的节点数。
降低多项式回归模型的阶数。
# 使用正则化:
L1 或 L2 正则化可以帮助减少模型权重的大小,从而简化模型。(主要使用L2)
Dropout(对于神经网络)是一种在训练过程中随机丢弃部分神经元连接的方法,有助于减少过拟合。
# 增加训练数据量:
更多的训练样本可以帮助模型更好地理解数据的总体趋势,而不是仅仅记住训练集中的具体例子。
# 数据增强:
对于图像数据,可以通过旋转、缩放、翻转等方式生成额外的训练样本。
对于文本数据,可以使用同义词替换或其他技术来扩展数据集。
# 早停法(Early Stopping):
在训练过程中,当验证集上的性能开始恶化时,提前终止训练。
# 交叉验证(Cross-Validation):
使用 K 折交叉验证来评估模型的泛化能力,这可以帮助识别过拟合问题。
# 集成方法(Ensemble Methods):
使用如 Bagging 或 Boosting 的集成学习方法可以提高预测性能并减少过拟合风险。
# 特征选择:
仅选择那些真正有助于提高模型性能的特征,避免使用无关紧要或冗余的特征。
# 调整超参数:
通过网格搜索或随机搜索来调整学习率、正则化参数、批次大小等超参数,找到最优设置。
# 增加噪声:
在输入数据中加入少量的噪声可以使模型更加健壮,不易于记忆特定的输入输出关系。
2.2.3 正好拟合
正好拟合:可以理解为模型既没有发生过拟合也没有发生欠拟合的情况。
表现:在这种理想的情况下,模型在训练数据上的表现良好,并且在未见过的数据(如验证集或测试集)上也表现出较好的泛化能力。
代码模拟:
python
# 0.导包
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression # 线性回归-正规方程模型
from sklearn.metrics import mean_squared_error # 计算均方误差
def dm03_正好拟合():
# 1.准备数据
# 准备噪声(简单理解为随机种子),噪声相同 每次生成的随机点数相同(噪声点形成的图相同)
np.random.seed(21)
# x 表示特征 -3-3之间 随机的小数 生成100个
x = np.random.uniform(-3,3,size=100)
# y 表示标签(目标值) 存在线性关系 y=0.5x² + x +2 + 正态分布 + 噪声
# np.random.normal(0,1,size=100) 意思是均值为0 标准差为1 生成100个
y = 0.5* x **2 + x +2 + np.random.normal(0,1,size=100)
# 模型训练
# 2.创建线性回归-正规方程 模型对象
estimator = LinearRegression(fit_intercept=True) # 计算偏置
# 3.对数据集做处理
# 3.1把数据从一维数据=>2维数据
X = x.reshape(-1,1)
# 3.2 拼接x 和 x的平方 把数据从[[1],[2],[3]] => [[1,1],[2,4],[3,9]] 即一元线性回归=>二元线性回归
X2 = np.hstack([X,X**2])
# 4.模型训练
estimator.fit(X2,y) # 传入处理后的X值
# 5. 模型预测
y_predict = estimator.predict(X2)
print(f'预测结果为:{y_predict}')
# 6.模型评估
print(f'均方误差{mean_squared_error(y,y_predict)}')
# 7. 数据可视化绘制图像
plt.scatter(x,y) # 基于原始的x(特征),y(真实值)绘制散点图
# np.sort(x) 按照x值的升序排列
# np.argsort(x) 按照x值的升序排列 返回(x对应的)索引值
plt.plot(np.sort(x),y_predict[np.argsort(x)],c='r') # 基于原始的x(特征)y(预测值)绘制折线图(即 拟合回归线)
plt.show()
if __name__ == '__main__':
dm03_正好拟合
如何逼近:
python
# 选择合适的模型复杂度:既不太简单也不太复杂。
# 使用足够的训练数据:确保模型可以从数据中学习到通用的模式。
# 应用适当的正则化技术:防止模型变得过于复杂。
# 进行适当的特征选择:只使用对任务有贡献的特征。
# 使用交叉验证:确保模型在不同的数据子集上都有良好的表现。
# 使用合适的超参数:通过调优找到最佳的模型配置。
好了,以上就是今天和大家分享的模型优劣判别的相关原理和解决办法。传统机器学习的算法很多的,后面会分享逻辑回归,决策树,集成学习等等常用的算法。有兴趣的小伙伴可以点赞加关注哦。。。。。。我们下期见!