一篇文章详解深度学习正则化方法(L1、L2、Dropout正则化相关概念、定义、数学公式、Python代码实现)

本文主要是介绍一篇文章详解深度学习正则化方法(L1、L2、Dropout正则化相关概念、定义、数学公式、Python代码实现),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、什么是正则化?

二、正则化的作用?

三、常见的正则化方法

四、详解L1正则化 

 五、详解L2正则化

六、详解Dropout方法

总结:


博主介绍:✌专注于前后端、机器学习、人工智能应用领域开发的优质创作者、秉着互联网精神开源贡献精神,答疑解惑、坚持优质作品共享。本人是掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战,深受全网粉丝喜爱与支持✌有需要可以联系作者我哦!

🍅文末三连哦🍅

👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟

 

一、什么是正则化?

正则化是指在机器学习和统计建模中的一种技术,用于控制模型的复杂度,防止模型在训练数据上过度拟合(overfitting)。当模型过度拟合时,它会学习到训练数据中的噪声和细微变化,导致在新数据上的性能下降。

正则化通过在模型的损失函数中引入额外的惩罚项,来对模型的参数进行约束,从而降低模型的复杂度。这个额外的惩罚通常与模型参数的大小或者数量相关,旨在鼓励模型学习简单的规律,而不是过度拟合训练数据。

在深度学习中,正则化通常涉及到对网络的权重进行约束,以防止它们变得过大或过复杂。最常见的正则化技术之一是 L1 和 L2 正则化,分别通过对权重的 L1 范数和 L2 范数进行惩罚来实现。这些技术有助于降低模型的复杂度,并提高模型在未见过的数据上的泛化能力。

二、正则化的作用?

  1. 防止过拟合:正则化通过对模型的复杂度进行限制,防止模型在训练数据上过度拟合。过拟合指的是模型在训练数据上表现良好,但在未见过的数据上表现较差的情况,这可能是因为模型学习到了训练数据中的噪声或者细节,而无法泛化到新数据上。正则化有助于使模型更加简单,从而提高其在未见过的数据上的泛化能力。

  2. 提高模型的泛化能力:正则化约束了模型的复杂度,使其更容易泛化到未见过的数据上。通过控制模型的参数大小或数量,正则化可以使模型更加稳定,减少对训练数据的过度依赖,从而提高模型的泛化能力。

  3. 减少模型的复杂度:正则化技术通过对模型的参数进行惩罚,促使模型更趋向于简单的解。例如,L1 和 L2 正则化会约束模型的权重,使其趋向于稀疏或较小的值,从而减少模型的复杂度。

  4. 控制模型的学习速度:正则化技术可以对模型的学习速度进行调节,防止模型在训练过程中权重变化过大,从而导致优化过程不稳定。这有助于加速模型的收敛,并提高模型在训练数据上的表现。

  5. 提高模型的鲁棒性:正则化有助于使模型更加鲁棒,即对输入数据的微小变化不敏感。通过降低模型的复杂度,正则化可以减少模型对训练数据中噪声的敏感度,从而提高模型的鲁棒性。

三、常见的正则化方法

  1. L1 正则化:也称为 Lasso 正则化,它通过在模型的损失函数中增加权重的 L1 范数(权重向量的绝对值之和)来实现正则化。L1 正则化倾向于产生稀疏权重矩阵,即将一些权重推向零,从而实现特征选择的效果。

  2. L2 正则化:也称为 Ridge 正则化,它通过在模型的损失函数中增加权重的 L2 范数(权重向量的平方和)来实现正则化。L2 正则化会使权重值变得较小,但不会直接导致权重稀疏,因此不具有特征选择的作用,但可以有效地控制模型的复杂度。

  3. Elastic Net 正则化:Elastic Net 是 L1 和 L2 正则化的组合,它在损失函数中同时使用 L1 和 L2 范数,可以综合两者的优点。

  4. Dropout:Dropout 是一种特殊的正则化技术,通过在训练过程中随机地丢弃(将其权重置为零)网络中的部分神经元,以及它们的连接,来减少神经网络的复杂度。这样可以防止神经元之间的共适应性,从而减少过拟合。

  5. 早停(Early Stopping):早停是一种简单而有效的正则化方法,它在训练过程中监视模型在验证集上的性能,一旦验证集上的性能开始下降,就停止训练。这样可以避免模型在训练集上过拟合。

  6. 数据增强(Data Augmentation):数据增强是通过对训练数据进行变换来增加数据的多样性,从而减少过拟合的风险。例如,在图像分类任务中可以进行随机裁剪、旋转、翻转等操作来增加训练数据的数量和多样性。

  7. 批量归一化(Batch Normalization):批量归一化是一种通过对每个批次的输入进行归一化来加速训练并减少过拟合的技术。它可以使得每一层的输入分布稳定,从而更容易优化模型。

  8. 权重衰减(Weight Decay):权重衰减是一种通过在损失函数中增加权重的平方和或绝对值之和来实现正则化的技术。它等价于对权重参数进行 L2 正则化。

四、详解L1正则化 

L1 正则化,也称为 Lasso 正则化,是一种常用的正则化技术,用于控制模型的复杂度和防止过拟合。它的原理是通过在模型的损失函数中增加权重的 L1 范数(权重向量的绝对值之和)作为惩罚项,从而鼓励模型产生稀疏权重,即让一部分权重趋近于零,实现特征选择的效果。

L1 正则化的损失函数:

L_{\text{L1}} = L_{\text{data}} + \lambda \sum_{i=1}^{n} |w_i|

其中:
- L_{\text{data}}是模型的数据损失,通常是模型的预测值与真实标签之间的误差,如均方误差(MSE)或交叉熵损失(Cross-entropy loss)。
- \lambda是正则化参数,用于控制正则化项的强度。
- |w_i| 表示模型的权重的绝对值。

公式推导: 

L1 正则化是一种通过在模型的损失函数中增加权重的 L1 范数作为惩罚项来控制模型复杂度的技术。L1 范数是向量中各个元素的绝对值之和,其数学表示如下:

||\mathbf{w}||_1 = \sum_{i=1}^{n} |w_i|

其中 \mathbf{w}是模型的权重向量,n是权重向量的长度,即权重的数量。

在 L1 正则化中,惩罚项可以写为权重的 L1 范数:

\text{penalty} = \lambda ||\mathbf{w}||_1

其中 \lambda是正则化参数,用于控制正则化的强度。

现在,我们来推导一下 L1 正则化的损失函数。假设我们有一个带有 L1 正则化的线性回归模型,其损失函数可以表示为:

L(\mathbf{w}) = L_{\text{data}}(\mathbf{w}) + \lambda ||\mathbf{w}||_1

其中 L_{\text{data}}(\mathbf{w})是模型的数据损失,通常是模型的预测值与真实标签之间的误差。

我们的目标是最小化整个损失函数。为了找到最小化损失函数的权重 \mathbf{w},我们可以使用梯度下降等优化算法。在梯度下降中,我们需要计算损失函数关于权重的梯度,然后根据梯度的方向和大小来更新权重。

现在,我们来推导损失函数关于权重的梯度。为了简化推导,我们假设 L_{\text{data}}(\mathbf{w})是均方误差损失函数,即:

L_{\text{data}}(\mathbf{w}) = \frac{1}{2} ||\mathbf{y} - \mathbf{X}\mathbf{w}||_2^2

其中 \mathbf{X}是输入特征矩阵,\mathbf{y}是真实标签向量。

我们的目标是最小化总损失函数:

L(\mathbf{w}) = \frac{1}{2} ||\mathbf{y} - \mathbf{X}\mathbf{w}||_2^2 + \lambda ||\mathbf{w}||_1

现在,我们对L(\mathbf{w})求导数,得到梯度:

\nabla L(\mathbf{w}) = -\mathbf{X}^T (\mathbf{y} - \mathbf{X}\mathbf{w}) + \lambda \text{sign}(\mathbf{w})

其中 \text{sign}(\mathbf{w})是权重向量 \mathbf{w}各个元素的符号函数。这意味着每个权重的梯度由数据损失和正则化项的梯度之和组成。

最后,我们可以使用梯度下降等优化算法来最小化损失函数,并找到最优的权重 \mathbf{w}。在优化过程中,L1 正则化项会促使一些权重趋向于零,从而实现特征选择的效果,降低模型的复杂度,防止

可视化对比L1正则化效果: 

过拟合Python 代码,用于生成带有噪声的线性数据集,并分别应用没有 L1 正则化和有 L1 正则化的线性模型来拟合数据,并在同一页面可视化对比两种情况的结果:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression, Lasso# 生成带有噪声的线性数据集
np.random.seed(0)
X = np.random.rand(100, 1)  # 特征
y = 3 * X.squeeze() + np.random.normal(0, 0.3, 100)  # 标签# 不使用正则化的线性回归模型
linear_model = LinearRegression()
linear_model.fit(X, y)# 使用 L1 正则化的 Lasso 回归模型
lasso_model = Lasso(alpha=0.2)  # 正则化参数 alpha
lasso_model.fit(X, y)# 可视化结果
plt.figure(figsize=(12, 6))# 绘制原始数据和线性回归模型拟合结果
plt.subplot(1, 2, 1)
plt.scatter(X, y, color='blue', label='Data')
plt.plot(X, linear_model.predict(X), color='red', linewidth=2, label='Linear Regression')
plt.xlabel('X')
plt.ylabel('y')
plt.title('Without L1 Regularization')
plt.legend()# 绘制原始数据和 Lasso 回归模型拟合结果
plt.subplot(1, 2, 2)
plt.scatter(X, y, color='blue', label='Data')
plt.plot(X, lasso_model.predict(X), color='green', linewidth=2, label='Lasso Regression')
plt.xlabel('X')
plt.ylabel('y')
plt.title('With L1 Regularization (Lasso)')
plt.legend()plt.show()

结果展示包含两个子图的图像,左侧子图展示了没有应用 L1 正则化的线性回归模型拟合结果,右侧子图展示了应用了 L1 正则化的 Lasso 回归模型拟合结果。通过这两个子图的对比,我们可以清晰地看到 L1 正则化的作用,它使得模型的权重变得更加稀疏,从而实现了特征选择的效果。

 五、详解L2正则化

L2 正则化,也称为 Ridge 正则化。它通过向模型的损失函数添加一个权重参数的 L2 范数的惩罚项来实现。下面我们来详细解释一下 L2 正则化的原理和数学公式。

数学公式:

在 L2 正则化中,惩罚项通常被定义为权重参数的 L2 范数的平方。具体地,L2 正则化的损失函数可以表示为:

L_{\text{L2}} = L_{\text{data}} + \lambda ||\mathbf{w}||_2^2

其中:
- L_{\text{data}}是模型的数据损失,通常是模型的预测值与真实标签之间的误差。
- \lambda是正则化参数,用于控制正则化的强度。
- ||\mathbf{w}||_2^2是权重向量\mathbf{w} 的 L2 范数的平方,表示为权重向量中各个参数的平方和。

使用 L2 正则化的损失函数时,优化算法在优化过程中会同时考虑数据损失和正则化项,从而在保持对训练数据的拟合能力的同时,尽可能减小模型参数的大小,降低模型的复杂度。

可视化L2正则化效果: 

首先,我们将生成一个带有噪声的线性数据集,并分别使用没有 L2 正则化的普通线性回归模型和带有 L2 正则化的 Ridge 回归模型来拟合数据。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression, Ridge# 生成带有噪声的线性数据集
np.random.seed(0)
X = np.random.rand(100, 1)  # 特征
y = 3 * X.squeeze() + np.random.normal(0, 0.3, 100)  # 标签# 没有使用 L2 正则化的线性回归模型
linear_model = LinearRegression()
linear_model.fit(X, y)# 使用 L2 正则化的 Ridge 回归模型
ridge_model = Ridge(alpha=1.0)  # 正则化参数 alpha
ridge_model.fit(X, y)# 可视化结果
plt.figure(figsize=(10, 6))
plt.scatter(X, y, color='blue', label='Data')
plt.plot(X, linear_model.predict(X), color='red', linewidth=2, label='Linear Regression (No L2 Regularization)')
plt.plot(X, ridge_model.predict(X), color='green', linewidth=2, label='Ridge Regression (L2 Regularization)')
plt.xlabel('X')
plt.ylabel('y')
plt.title('Comparison of Linear Regression with and without L2 Regularization')
plt.legend()
plt.show()

 生成一个散点图,其中蓝色的点表示原始数据,红色的线表示没有 L2 正则化的普通线性回归模型的拟合结果,绿色的线表示带有 L2 正则化的 Ridge 回归模型的拟合结果。通过观察这张图,我们可以直观地比较两种模型的拟合效果,以及 L2 正则化对模型的影响。

六、详解Dropout方法

Dropout 是一种在神经网络中常用的正则化技术,用于减少过拟合。其原理是在网络的训练过程中,随机地将部分神经元的输出置为零(即失活),从而使得网络在每次迭代时都在不同的子网络上训练,以减少神经元之间的复杂依赖关系,从而增强模型的泛化能力。

工作原理:

  1. 随机失活神经元:在每次训练迭代时,Dropout 方法会以一定的概率(通常为 0.5)随机地将某些神经元的输出置为零,即使得这些神经元在此次迭代中不参与前向传播和反向传播。这样可以阻止网络过度依赖于某些特定的神经元,增强模型的泛化能力。

  2. 训练时与测试时的区别:在训练时,通过随机失活神经元来减少过拟合;而在测试时,所有的神经元都保持活跃,但是输出值需要按照训练时的概率进行缩放,以保持期望输出的一致性。

  3. Dropout的随机性:Dropout 是通过在每次迭代中随机选择要失活的神经元来实现的。这种随机性会导致网络在每次迭代时都训练在不同的子网络上,从而相当于训练了多个不同的模型,最终取平均或者加权平均作为最终的预测结果。

Dropout的优点:

  • 减少过拟合:通过随机失活部分神经元,阻止网络过度拟合训练数据,从而提高了模型的泛化能力。
  • 简单易用:Dropout 是一种简单而有效的正则化技术,可以直接应用于现有的神经网络模型中,而无需对网络结构进行修改。

数学公式:

在数学上,Dropout 的原理可以通过以下方式进行表述。

假设我们有一个具有L个隐藏层的神经网络,其中每个隐藏层l包含 n^{[l]}个神经元。对于每个隐藏层 l,我们定义一个二进制掩码向量\mathbf{d}^{[l]},其中d_{i}^{[l]} 表示第i个神经元是否被保留(未失活)。

在训练期间,对于每个训练示例t,Dropout 方法将随机地将掩码向量\mathbf{d}^{[l]}应用于每个隐藏层l 的输出,从而产生一个新的损失函数 L^{[l]}

L^{[l]}(\mathbf{W}^{[l]}, \mathbf{b}^{[l]}, \mathbf{d}^{[l]}) = \frac{1}{m} \sum_{t=1}^{m} L(y^{(t)}, \hat{y}^{(t)})

其中\mathbf{W}^{[l]}\mathbf{b}^{[l]} 是第l层的权重和偏置,L(y^{(t)}, \hat{y}^{(t)})是损失函数,\hat{y}^{(t)}是网络的输出,m是训练样本数量。

在测试期间,没有随机失活,因此需要通过缩放来调整每个隐藏层的输出。具体地,我们将每个神经元的输出值a^{[l]}乘以保留概率 p并除以p

\tilde{a}^{[l]} = \frac{a^{[l]}}{p}

通过这种方式,可以在测试期间保持期望输出不变,从而保持一致性。

在实践中,Dropout 的目标是将模型的期望输出与训练和测试期间的实际输出保持一致,从而减少过拟合并提高模型的泛化能力。

代码实现Dropout应用:

基于 PyTorch 框架,并使用 FashionMNIST 数据集来演示如何构建一个卷积神经网络(CNN)并应用 Dropout。在此示例中,我们将加载 FashionMNIST 数据集,创建一个包含 Dropout 层的简单 CNN 模型,并在训练过程中观察 Dropout 对模型性能的影响。

import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as plt# 定义数据转换
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,))
])# 加载 FashionMNIST 数据集
trainset = torchvision.datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)testset = torchvision.datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot')# 定义卷积神经网络模型
class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 32, 3, padding=1)self.pool = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(32, 64, 3, padding=1)self.fc1 = nn.Linear(64 * 7 * 7, 128)self.fc2 = nn.Linear(128, 10)self.dropout = nn.Dropout(0.5)  # 添加 Dropout 层def forward(self, x):x = self.pool(F.relu(self.conv1(x)))x = self.pool(F.relu(self.conv2(x)))x = x.view(-1, 64 * 7 * 7)x = F.relu(self.fc1(x))x = self.dropout(x)  # 在全连接层添加 Dropoutx = self.fc2(x)return x# 实例化模型和损失函数、优化器
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)# 训练模型
for epoch in range(5):  # 在 FashionMNIST 上训练 5 个 epochrunning_loss = 0.0for i, data in enumerate(trainloader, 0):inputs, labels = dataoptimizer.zero_grad()outputs = net(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()if i % 2000 == 1999:print('[%d, %5d] loss: %.3f' %(epoch + 1, i + 1, running_loss / 2000))running_loss = 0.0print('Finished Training')# 在测试集上评估模型
correct = 0
total = 0
with torch.no_grad():for data in testloader:images, labels = dataoutputs = net(images)_, predicted = torch.max(outputs, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

在模型中添加了一个 Dropout 层,其丢弃概率为 0.5。然后我们使用 SGD 优化器和交叉熵损失函数来训练模型。最后,我们在测试集上评估了模型的性能。

总结:

今天我们学习了正则化相关概念、常见神经网络中正则化数学公式及其作用。重点讲解正则化旨在防止模型过拟合,提高模型的泛化能力。常见的正则化方法包括L1和L2正则化,它们通过向损失函数添加正则项来限制模型参数的大小。另外,Dropout技术在训练过程中随机地关闭神经元,以减少神经网络的复杂性和过拟合风险。此外,数据增强也是一种有效的正则化方法,通过对训练数据进行微小的变换来增加数据的多样性,从而帮助模型更好地泛化到新的数据。这些正则化技术通常结合使用以提高模型的性能和鲁棒性。

今天内容分享到这里哦!

最后,创作不易!非常感谢大家的关注、点赞、评论啦!谢谢三连哦!好人好运连连,学习进步!工作顺利哦! 

这篇关于一篇文章详解深度学习正则化方法(L1、L2、Dropout正则化相关概念、定义、数学公式、Python代码实现)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/909321

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Nginx设置连接超时并进行测试的方法步骤

《Nginx设置连接超时并进行测试的方法步骤》在高并发场景下,如果客户端与服务器的连接长时间未响应,会占用大量的系统资源,影响其他正常请求的处理效率,为了解决这个问题,可以通过设置Nginx的连接... 目录设置连接超时目的操作步骤测试连接超时测试方法:总结:设置连接超时目的设置客户端与服务器之间的连接

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在