防止过拟合的几种方法

权重衰减

权重衰减可以在损失函数中加入假如L2惩罚项\(\frac{\lambda}{2}||w||^2\),然后正常使用优化器进行梯度下降。但这种方式会使得计算量变大。

另一种方式是损失函数不计算L2惩罚项,直接在梯度下降时加入惩罚项的梯度,在pytorch的优化器中,有weight_decay这个参数设置L2惩罚项的\(\lambda\)参数值,如果非零,则进行权重衰减的梯度下降,比如:

1
loss_function = optim.SGD(model.parameters(), lr=0.01, weight_decay=1e-6)

Dropout

1
torch.nn.Dropout(p=0.5, inplace=False)
  • p: 这个参数控制着dropout的比例。例如,如果p设置为0.2,则在训练过程中,每个神经元有20%的概率被关闭(即其输出被置为0)。这个参数可以根据具体任务和过拟合的程度进行调整。
  • inplace: 这个参数是一个优化选项。如果设置为True,Dropout操作将会直接在输入张量上进行,而不是创建一个新的张量来存储结果。这可以节省内存,但会改变输入张量的值,可能会影响到后续的操作。

在神经网络模块的训练模式时,pytorch会自动应用dropout;在评估模式时,pytorch则不会应用dropout

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import torch
import torch.nn as nn
import torch.optim as optim

# 定义一个简单的神经网络,包含Dropout层
class SimpleNet(nn.Module):
def __init__(self):
super(SimpleNet, self).__init__()
self.fc1 = nn.Linear(784, 500) # 假设输入特征为784
self.dropout = nn.Dropout(0.5) # Dropout概率为0.5
self.fc2 = nn.Linear(500, 10) # 假设输出类别为10

def forward(self, x):
x = torch.relu(self.fc1(x))
x = self.dropout(x) # 应用Dropout
x = self.fc2(x)
return x

# 实例化网络
model = SimpleNet()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练模式
model.train()
for data, target in train_loader:
optimizer.zero_grad() # 清除旧的梯度
output = model(data) # 前向传播,应用Dropout
loss = criterion(output, target) # 计算损失
loss.backward() # 反向传播计算梯度
optimizer.step() # 更新模型参数

# 评估模式
model.eval()
with torch.no_grad(): # 不计算梯度
for data, target in test_loader:
output = model(data) # 前向传播,不应用Dropout
# 进行评估,如计算准确率等

防止过拟合的几种方法
https://blog.shinebook.net/2025/02/25/人工智能/pytorch/防止过拟合的几种方法/
作者
X
发布于
2025年2月25日
许可协议