pytorch中的一些技巧-统计参数数量,划分数据集,初始化,正则化

统计参数总数量

1
num_params = sum(param.numel() for param in model.parameters())

划分训练集和验证集

1
2
3
train_size = int(0.8 * len(full_dataset))
test_size = len(full_dataset) - train_size
train_dataset, test_dataset = torch.utils.data.random_split(full_dataset, [train_size, test_size])

参数初始化

Xavier 初始化

Xavier初始化的基本思想是保持输入和输出的方差一致,这样就避免了所有输出值都趋向于0。这是通用的方法,适用于任何激活函数。

1
2
3
for m in model.modules():
if isinstance(m, (nn.Conv2d, nn.Linear)):
nn.init.xavier_uniform(m.weight)

He 初始化

He 初始化的思想是:在ReLU网络中,假定每一层有一半的神经元被激活,另一半为0。推荐在ReLU网络中使用。

1
2
3
for m in model.modules():
if isinstance(m, (nn.Conv2d, nn.Linear)):
nn.init.kaiming_normal(m.weight, mode=\\'fan_in\\')

正则化

一般正则化,只是对模型的权重W参数进行惩罚,而偏置b是不进行惩罚的,如果对权值w偏置b同时进行惩罚,将会导致严重的欠拟合。

L2 正则化

torch.optim 的优化器固定实现L2正则化,也只实现了L2正则化,若想实现L1正则化,见下。而torch.optim 的优化器weight_decay参数指定的权值衰减是对网络中的所有参数,包括 权值w偏置b 同时进行惩罚,需要特意设置一下,只对 权值w进行惩罚。

1
2
3
4
5
6
7
8
9
10
11
12
weight_p, bias_p = [],[]
for name, p in model.named_parameters():
if 'bias' in name:
bias_p += [p]
else:
weight_p += [p]
# 这里的model中每个参数的名字都是系统自动命名的,只要是权值都是带有weight,偏置都带有bias

optim.SGD([
{'params': weight_p, 'weight_decay':1e-5},
{'params': bias_p, 'weight_decay':0}
], lr=1e-2, momentum=0.9)

另一种实现:

1
2
3
4
5
6
7
8
reg = 1e-6
l2_loss = Variable(torch.FloatTensor(1), requires_grad=True)
for name, param in model.named_parameters():
if 'bias' not in name:
l2_loss = l2_loss + 0.5 * reg * torch.sum(torch.pow(param, 2)))

classify_loss = criteon(outputs, labels)
loss = classify_loss + l2_loss

L1 正则化

1
2
3
4
5
6
7
8
reg = 1e-6
l1_loss = Variable(torch.FloatTensor(1), requires_grad=True)
for name, param in model.named_parameters():
if 'bias' not in name:
l1_loss = l1_loss + reg * torch.sum(torch.abs(param)))

classify_loss = criteon(outputs, labels)
loss = classify_loss + l1_loss