第一部分:基础知识
Dropout 是一种用于防止神经网络过拟合的正则化方法。它通过在每次训练过程中随机丢弃一部分神经元,使得模型在每次迭代中使用不同的神经元组合进行计算,从而减少模型对某些神经元的依赖,增强模型的泛化能力。
第二部分:工作原理
①在训练过程中随机“删除”(也就是将权重设为0)一些神经元
②只是用在训练期间,不会用在测试期间。
这个idea的思路就是让防止神经网络对训练集过于依赖,从而提高它的泛化能力。
第三部分:工作的主要流程
①指定一个保留比例p
②每层每个神经元,以p的概率保留,以1-p的概率将权重设为0,(这样达到的效果就相当于训练了多个子网络)
③训练过程中使用的神经元进行前向和反向传播
④测试过程中将所有的权重乘以p
第四部分:dropupt与集成学习的异曲同工之妙
我们可以先将一个完整的神经网络分为many个子神经元,(每一个子神经元的本质就是一个线性模型+一个激活函数)
而集成学习的思想就是将多个算法模型的集成。
我们的dropout的随机性就可以体现“随机”抽取多个子神经元构成一个个的子神经网络
其中的由单个子神经元组成的子神经网络或者多个神经元组成的神经网络(但是这些子神经元之间没有连接)将会被剔除。
剩下的多个子神经网络再“集成”在一起。
流程如下:
然后分为多个子神经元:
然后进行组合:
上述只是我列出的一部分(可能有些不是很正确,但目的是理解这个先分开中间进行删除处理再聚合的思想)。
当我们把不满足的删除之后,再将剩下的满足的子神经网络聚集在一起就行了。
实际在神经网络中的体现就是在每一条边上都加上一个权重值(概率p)
第五部分:dropout的优缺点分析
(1)优点
可以有效地减小过拟合
简单方便
实际应用过程中有效
(2)缺点
降低训练效率(因为要多计算p)
损失函数不够明确
第六部分:案例分析
研究和展示如何通过使用 Dropout 来减少神经网络模型的过拟合问题。通过比较两个模型——一个可能会过拟合的普通模型和一个通过引入 Dropout 层来减轻过拟合的模型——来观察和分析 Dropout 对模型泛化能力的影响。
第七部分:技术使用
使用MSE计算损失函数和Adam优化器。
第八部分:dropout代码实现
(1)导包
# 导入必要的库
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
(2)定义超参数
# 定义超参数
num_samples = 20 # 样本数
hidden_size = 200 # 隐藏层大小
num_epochs = 500 # 训练轮数
(3)创建数据集并划分数据集
# 设置随机种子
torch.manual_seed(2333)
# 生活训练集
x_train = torch.unsqueeze(torch.linspace(-1, 1, num_samples), 1)
y_train = x_train + 0.3 * torch.randn(num_samples, 1)
# 测试集
x_test = torch.unsqueeze(torch.linspace(-1, 1, num_samples), 1)
y_test = x_test + 0.3 * torch.randn(num_samples, 1)
# 绘制训练集和测试集
plt.scatter(x_train, y_train, c='r', alpha=0.5, label='train')
plt.scatter(x_test, y_test, c='b', alpha=0.5, label='test')
plt.legend(loc='upper left')
plt.ylim((-2, 2))
plt.show()
(4)模型定义(过拟合模型和使用dropout的模型)
# 定义一个可能会过拟合的模型
net_overfitting = torch.nn.Sequential(
torch.nn.Linear(1, hidden_size),
torch.nn.ReLU(),
torch.nn.Linear(hidden_size, hidden_size),
torch.nn.ReLU(),
torch.nn.Linear(hidden_size, 1),
)
# 定义一个包含 Dropout 的模型
net_dropout = torch.nn.Sequential(
torch.nn.Linear(1, hidden_size),
torch.nn.Dropout(0.5), # p=0.5
torch.nn.ReLU(),
torch.nn.Linear(hidden_size, hidden_size),
torch.nn.Dropout(0.5), # p=0.5
torch.nn.ReLU(),
torch.nn.Linear(hidden_size, 1),
)
(5)模型训练
# 定义优化器
optimizer_overfitting = torch.optim.Adam(net_overfitting.parameters(), lr=0.01)
optimizer_dropout = torch.optim.Adam(net_dropout.parameters(), lr=0.01)
# 定义损失函数
criterion = nn.MSELoss()
# 执行训练循环
for i in range(num_epochs):
# overfitting模型的: 前向传播, 计算损失, 反向传播
pred_overfitting = net_overfitting(x_train)
loss_overfitting = criterion(pred_overfitting, y_train)
optimizer_overfitting.zero_grad()
loss_overfitting.backward()
optimizer_overfitting.step()
# 包含dropout的模型: 前向传播, 计算损失, 反向传播
pred_dropout = net_dropout(x_train)
loss_dropout = criterion(pred_dropout, y_train)
optimizer_dropout.zero_grad()
loss_dropout.backward()
optimizer_dropout.step()
(6)效果展示
# 在测试过程中不使用 Dropout
net_overfitting.eval()
net_dropout.eval()
# 预测
test_pred_overfitting = net_overfitting(x_test)
test_pred_dropout = net_dropout(x_test)
# 绘制训练集和测试集
plt.scatter(x_train, y_train, c='r', alpha=0.3, label='train')
plt.scatter(x_test, y_test, c='b', alpha=0.3, label='test')
plt.plot(x_test, test_pred_overfitting.data.numpy(), 'r--', lw=2, label='overfitting')
plt.plot(x_test, test_pred_dropout.data.numpy(), 'b-', lw=2, label='dropout')
plt.legend(loc='upper left')
plt.ylim((-2, 2))
plt.show()
可以看到:
红线在红点(训练集)上效果特别好,但是在蓝点上(测试集)不好,也就是过拟合现象,同时红线还有较大的来回上下浮动
相比之下,蓝线就在训练集和测试集上都非常好。
(7)pycharm完整代码实现
# 在测试过程中不使用 Dropout
net_overfitting.eval()
net_dropout.eval()
# 预测
test_pred_overfitting = net_overfitting(x_test)
test_pred_dropout = net_dropout(x_test)
# 绘制训练集和测试集
plt.scatter(x_train, y_train, c='r', alpha=0.3, label='train')
plt.scatter(x_test, y_test, c='b', alpha=0.3, label='test')
plt.plot(x_test, test_pred_overfitting.data.numpy(), 'r--', lw=2, label='overfitting')
plt.plot(x_test, test_pred_dropout.data.numpy(), 'b-', lw=2, label='dropout')
plt.legend(loc='upper left')
plt.ylim((-2, 2))
plt.show()