权重衰减
在训练参数化机器学习模型时,权重衰减(weight decay)是最广泛使用的正则化的技术之一,它通常也被称为L2正则化。这项技术通过函数与零的距离来衡量函数的复杂度,因为在所有函数f中,函数 f = 0(所有 输入都得到值0)在某种意义上是最简单的。
一种简单的方法是通过线性函数
f
(
x
)
=
w
⊤
x
f(x) = w^⊤x
f(x)=w⊤x 中的权重向量的某个范数来度量其复杂性,例如
∥
w
∥
2
∥w∥^ 2
∥w∥2。要保证 权重向量比较小,最常用方法是将其范数作为惩罚项加到最小化损失的问题中。将原来的训练目标最小化训 练标签上的预测损失,调整为最小化预测损失和惩罚项之和。现在,如果我们的权重向量增长的太大,我们的学习算法可能会更集中于最小化权重范数
∥
w
∥
2
∥w∥^ 2
∥w∥2。这正是我们想要的。线性回归例子损失由下式给出
L
(
w
,
b
)
=
1
n
∑
i
=
1
n
1
2
(
w
⊤
x
(
i
)
+
b
−
y
(
i
)
)
2
L(w, b) = \frac{1} {n}\sum_{i=1}^{n}\frac{1}{2}( w^⊤x^{ (i)} + b − y^{ (i)})^ 2
L(w,b)=n1i=1∑n21(w⊤x(i)+b−y(i))2
为了惩罚权重向量的大小,我们必须以某种方式在损失函数中添加 ∥ w ∥ 2 ∥w∥^ 2 ∥w∥2,并通过正则化常数λ来描述这种的额外惩罚的损失和损失的平衡。根据估计值与观测值之间的差异来更新w,同时在试图将w的大小缩小到零。这就是为什么这种方法有时被称为权重衰减。我们仅考虑惩罚项,优化算法在训练的每一步衰减 权重。与特征选择相比,权重衰减为我们提供了一种连续的机制来调整函数的复杂度
# 偏置参数没有衰减
trainer = torch.optim.SGD([
{"params":net[0].weight,'weight_decay': wd},
{"params":net[0].bias}], lr=lr)
animator = d2l.Animator(xlabel='epochs', ylabel='loss', yscale='log',
xlim=[5, num_epochs], legend=['train', 'test'])
通过修改wd的值,来调节权重的衰减程度。
暂退法(Dropout)
以p的概率将隐藏单元置为零时,结果可以看作一个只包含原始神经元子集的网络。比如在 图4.6.1中,删除了h2和h5, 因此输出的计算不再依赖于h2或h5,并且它们各自的梯度在执行反向传播时也会消失。这样,输出层的计算 不能过度依赖于h1, . . . , h5的任何一个元素。
通常,我们在测试时不用暂退法。给定一个训练好的模型和一个新的样本,我们不会丢弃任何节点,因此不 需要标准化。然而也有一些例外:一些研究人员在测试时使用暂退法,用于估计神经网络预测的“不确定性”: 如果通过许多不同的暂退法遮盖后得到的预测结果都是一致的,那么我们可以说网络发挥更稳定。
以dropout的概率丢弃张量输入X中的元素,在训练时,Dropout层将根据指定的暂退概率随机丢弃上一层的输出(相当于下一层 的输入)。在测试时,Dropout层仅传递数据。
net = nn.Sequential(nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
# 在第一个全连接层之后添加一个dropout层
nn.Dropout(dropout1),
nn.Linear(256, 256),
nn.ReLU(),
# 在第二个全连接层之后添加一个dropout层
nn.Dropout(dropout2),
nn.Linear(256, 10))
def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std=0.01)
net.apply(init_weights);
std=0.01)
net.apply(init_weights);