Pytorch 4.5 权重衰减
正则化
预备知识
1.范数
距离的定义是一个宽泛的概念。只要是满足①非负②自反③三角不等式就可以称之为距离。范数是一种强化了的距离概念,它在定义上比距离多了一条数乘的运算法则。我们可以将范数当成是一种距离来理解。
(1)L-P范数
(2)据此我们很容易得到 : L-1范数
(3)L-2范数
权重衰减
在训练参数化机器学习模型时, 权重衰减(weight decay)是最广泛使用的正则化的技术之一, 它通常也被称为 \(L2\) 正则化。我们在上一篇文章中有讲到过,参数范围越大,越容易使得模型的函数更加尖锐,容易过拟合,为了使我们的函数更加平滑,具有更好的泛化性能,我们要引入一个正则化。 具体原理如下:
其中 \(L(\mathbf{w}, b)\) 是我们的损失函数 \(\frac{\lambda}{2} \|\mathbf{w}\|^2\) 是我们的正则化项,\(\lambda = 0\) 时相当于没有引入,\(\lambda > 0\) 时正则化正则化项求导 \(\lambda\mathbf{w}\) ,恰好是我们的权重张量。我们仅考虑惩罚项,优化算法在训练的每一步衰减权重。 与特征选择相比,权重衰减为我们提供了一种连续的机制来调整函数的复杂度。 较小的 \(λ\) 值对应较少约束的 \(w\) , 而较大的 \(\lambda\) 值对 \(w\) 的约束更大。
提示:我们一般不会对偏置项进行正则化,在于说,求导之后几乎都是一个常数。
简单实现下权重衰减
step1.库函数
%matplotlib inline
import torch
from torch import nn
from d2l import torch as d2l
step2.初始化参数
我们选择标签是关于输入的线性函数。 标签同时被均值为\(0\),标准差为\(0.01\)高斯噪声破坏。 为了使过拟合的效果更加明显,我们可以将问题的维数增加到 \(d=200\) , 并使用一个只包含\(20\)个样本的小训练集。
n_train, n_test, num_inputs, batch_size = 20,100,200,5
true_w, true_b = torch.ones(size=(num_inputs,1))*0.01 ,0.05
train_data = d2l.synthetic_data(true_w,true_b,n_train) # type(train_data) tuple
train_iter = d2l.load_array(train_data,batch_size) # torch.utils.data.dataloader.DataLoader
test_data = d2l.synthetic_data(true_w, true_b, n_test)
test_iter = d2l.load_array(test_data, batch_size, is_train=False) # Q1:为什么测试数据集不用随机化样本
def init_params():
w = torch.normal(0, 1, size=(num_inputs, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
return [w, b]
step3.定义正则项和训练函数
def l2_penalty(w):
return torch.sum(w.pow(2)) / 2
def train(lambd):
w, b = init_params()
net, loss = lambda X: d2l.linreg(X, w, b), d2l.squared_loss
num_epochs, lr = 100, 0.003
animator = d2l.Animator(xlabel='epochs', ylabel='loss', yscale='log',
xlim=[5, num_epochs], legend=['train', 'test'])
for epoch in range(num_epochs):
for X, y in train_iter:
# 增加了L2范数惩罚项,
# 广播机制使l2_penalty(w)成为一个长度为batch_size的向量
l = loss(net(X), y) + lambd * l2_penalty(w)
l.sum().backward()
d2l.sgd([w, b], lr, batch_size)
if (epoch + 1) % 5 == 0:
animator.add(epoch + 1, (d2l.evaluate_loss(net, train_iter, loss),
d2l.evaluate_loss(net, test_iter, loss)))
print('w的L2范数是:', torch.norm(w).item())
# 忽略正则化
train(lambd=0)
w的L2范数是: 13.449113845825195
#正则化的lambda = 1
torch(1)
w的L2范数是: 4.180489540100098
- 在本节的估计问题中使用 \(λ\) 的值进行实验。绘制训练和测试精度关于 \(λ\) 的函数。你观察到了什么?
- 使用验证集来找到最佳值 \(λ\) 。它真的是最优值吗?这有关系吗?
- 如果我们使用 \(∑_i|w_i|\) 作为我们选择的惩罚( \(L_1\) 正则化),那么更新方程会是什么样子?
- 我们知道 \(∥w∥_2=w⊤w\) 。你能找到类似的矩阵方程吗(见 2.3.10节 中的Frobenius范数)?
- 回顾训练误差和泛化误差之间的关系。除了权重衰减、增加训练数据、使用适当复杂度的模型之外,你还能想出其他什么方法来处理过拟合?
- 在贝叶斯统计中,我们使用先验和似然的乘积,通过公式 \(P(w∣x)∝P(x∣w)P(w)\) 得到后验。如何得到带正则化的 \(P(w)\) ?
posted on 2022-01-05 16:22 YangShusen' 阅读(283) 评论(0) 编辑 收藏 举报