权重衰减(基于线性回归)

权重衰减

虽然增⼤训练数据集可能会减轻过拟合,但是获取额外的训练数据往往代价高昂。应对过拟合问题的常用方法:权重衰减。

1. 方法

权重衰减等价于 L 2 L_2 L2范数正则化(regularization)。正则化通过为模型损失函数添加惩罚项使学出的模型参数值较小,是应对过拟合的常⽤⼿段。 L 2 L_2 L2范数正则化在模型原损失函数基础上添加 L 2 L_2 L2范数惩罚项,从而得到训练所需要最小化的函数。 L 2 L_2 L2范数惩罚项指的是模型权重参数每个元素的平⽅和与⼀个正的常数的乘积。
不添加惩罚项的线性回归损失函数
l ( w 1 , w 2 , b ) = 1 n ∑ i = 1 n 1 2 ( x 1 ( i ) w 1 + x 2 ( i ) w 2 + b − y ( i ) ) 2 (1) l(w_1,w_2,b)=\frac{1}{n} \sum_{i=1}^{n} \frac{1}{2} (x_1^{(i)}w_1+x_2^{(i)}w_2+b-y^{(i)})^2 \tag 1 l(w1,w2,b)=n1i=1n21(x1(i)w1+x2(i)w2+by(i))2(1)
其中 w 1 , w 2 w_1, w_2 w1,w2是权重参数, b b b是偏差参数,样本 i i i的输⼊为 x 1 ( i ) , x 2 ( i ) x_1^{(i)},x_2^{(i)} x1(i),x2(i),标签为 y ( i ) y^{(i)} y(i),样本数为 n n n。将权重参数⽤向量 w = [ w 1 , w 2 ] w = [w_1, w_2] w=[w1,w2]表⽰。

带有范数惩罚项的新损失函数为
l ( w 1 , w 2 , b ) + λ 2 n ∣ ∣ w ∣ ∣ 2 (2) l(w_1,w_2,b)+\frac{\lambda}{2n} ||w||^2 \tag 2 l(w1,w2,b)+2nλ∣∣w2(2)
其中超参数 λ > 0 \lambda > 0 λ>0。当权重参数均为0时,惩罚项最小。当 λ \lambda λ较大时,惩罚项在损失函数中的比重较大,这通常会使学到的权重参数的元素较接近0.当 λ \lambda λ设为0时,惩罚项完全不起作用。
有了惩罚项之后,在小批量随机梯度下降中, w 1 , w 2 w_1,w_2 w1,w2的迭代方式更改为:
w 1 ← ( 1 − η λ ∣ B ∣ ) w 1 − η ∣ B ∣ ∑ i ∈ ∣ B ∣ x 1 ( i ) ( x 1 ( i ) w 1 + x 2 ( i ) w 2 + b − y ( i ) ) . w 2 ← ( 1 − η λ ∣ B ∣ ) w 2 − η ∣ B ∣ ∑ i ∈ ∣ B ∣ x 2 ( i ) ( x 1 ( i ) w 1 + x 2 ( i ) w 2 + b − y ( i ) ) . (3) w_1 \leftarrow (1-\frac{\eta \lambda}{|B|})w_1 - \frac{\eta}{|B|}\sum_{i \in |B|} x_1^{(i)} (x_1^{(i)}w_1+x_2^{(i)}w_2+b-y^{(i)}). \\ w_2 \leftarrow (1-\frac{\eta \lambda}{|B|})w_2 - \frac{\eta}{|B|}\sum_{i \in |B|} x_2^{(i)} (x_1^{(i)}w_1+x_2^{(i)}w_2+b-y^{(i)}). \tag 3 w1(1Bηλ)w1BηiBx1(i)(x1(i)w1+x2(i)w2+by(i)).w2(1Bηλ)w2BηiBx2(i)(x1(i)w1+x2(i)w2+by(i)).(3)
可⻅, L 2 L_2 L2范数正则化令权重 w 1 w_1 w1 w 2 w_2 w2先⾃乘小于1的数,再减去不含惩罚项的梯度。因此, L 2 L_2 L2范数正则化⼜叫权重衰减。权重衰减通过惩罚绝对值较⼤的模型参数为需要学习的模型增加了限制,这可能对过拟合有效。实际场景中,我们有时也在惩罚项中添加偏差元素的平⽅和。

2. 高维线性回归实验

以⾼维线性回归为例来引⼊⼀个过拟合问题,并使⽤权重衰减来应对过拟合。设数据样本特征的维度为 p p p。对于训练数据集和测试数据集中特征为 x 1 , x 2 , . . . , x p x_1, x_2, . . . , x_p x1,x2,...,xp的任⼀样本,我们使⽤如下的线性函数来⽣成该样本的标签:
y = 0.05 + ∑ i = 1 p 0.01 x i + ε (4) y=0.05+\sum_{i=1}^{p} 0.01x_i+\varepsilon \tag 4 y=0.05+i=1p0.01xi+ε(4)
其中噪声项 ε \varepsilon ε服从均值为0、标准差为0.01的正态分布。为了较容易地观察过拟合,我们考虑⾼维线性回归问题,如设维度p = 200;同时,我们特意把训练数据集的样本数设低,如20。

%matplotlib inline
from mxnet import autograd, gluon, init, nd
from mxnet.gluon import data as gdata, loss as gloss, nn
n_train, n_test, num_inputs = 20, 100, 200
true_w, true_b = nd.ones((num_inputs, 1)) * 0.01, 0.05

features = nd.random.normal(shape=(n_train + n_test, num_inputs))
labels = nd.dot(features, true_w) + true_b
labels += nd.random.normal(scale=0.01, shape=labels.shape)

train_features, test_features = features[:n_train,:], features[n_train:,:]
train_labels, test_labels = labels[:n_train], labels[n_train:]

diy实现

初始化模型参数

⾸先,定义随机初始化模型参数的函数。该函数为每个参数都附上梯度。

def init_params():
    w = nd.random.normal(scale=1, shape=(num_inputs, 1))
    b = nd.zeros(shape=(1, ))
    w.attach_grad()
    b.attach_grad()
    return [w, b]
定义L2范数惩罚项

定义 L 2 L_2 L2范数惩罚项。这⾥只惩罚模型的权重参数。

def l2_penalty(w):
    return (w**2).sum() / 2
定义训练和测试

定义如何在训练数据集和测试数据集上分别训练和测试模型。

from utils import linreg, squared_loss, sgd, semilogy
batch_size, num_epochs, lr = 1, 100, 0.003
net, loss = linreg, squared_loss
train_iter = gdata.DataLoader(gdata.ArrayDataset(train_features, train_labels), batch_size, shuffle=True)

def fit_and_plot(lambd):
    w, b = init_params()
    train_ls, test_ls = [], []
    for _ in range(num_epochs):
        for X, y in train_iter:
            with autograd.record():
            # 添加了L2范数惩罚项
                l = loss(net(X, w, b), y) + lambd * l2_penalty(w)
            l.backward()
            sgd([w, b], lr, batch_size)
        train_ls.append(loss(net(train_features, w, b), train_labels).mean().asscalar())
        test_ls.append(loss(net(test_features, w, b), test_labels).mean().asscalar())
        
    semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'loss', range(1, num_epochs + 1), test_ls, ['train', 'test'])
    print('L2 norm of w:', w.norm().asscalar())
观察过拟合

训练并测试⾼维线性回归模型。当lambd设为0时,我们没有使⽤权重衰减。结果训练误差远小于测试集上的误差。这是典型的过拟合现象。

fit_and_plot(lambd=0)


在这里插入图片描述

L2 norm of w: 13.155678
使用权重衰减

使⽤权重衰减。可以看出,训练误差虽然有所提⾼,但测试集上的误差有所下降。过拟合现象得到⼀定程度的缓解。另外,权重参数的L2范数⽐不使⽤权重衰减时的更小,此时的权重参数更接近0。

fit_and_plot(lambd=3)


在这里插入图片描述

L2 norm of w: 0.042545244

简洁实现

在构造Trainer实例时通过wd参数来指定权重衰减超参数。默认下,Gluon会对权重和偏差同时衰减。我们可以分别对权重和偏差构造Trainer实例,从而只对权重衰减。

def fit_and_plot(wd):
    net = nn.Sequential()
    net.add(nn.Dense(1))
    net.initialize(init.Normal(sigma=1))
    # 对权重参数衰减
    trainer_w = gluon.Trainer(net.collect_params('.*weight'), 'sgd', {'learning_rate': lr, 'wd': wd})
    # 不对偏差参数衰减
    trainer_b = gluon.Trainer(net.collect_params('.*bias'), 'sgd', {'learning_rate': lr})
    train_ls, test_ls = [], []
    for _ in range(num_epochs):
        for X, y in train_iter:
            with autograd.record():
                l = loss(net(X), y)
            l.backward()
            # 对两个Trainer实例分别调⽤step函数,从⽽分别更新权重和偏差
            trainer_w.step(batch_size)
            trainer_b.step(batch_size)
        train_ls.append(loss(net(train_features), train_labels).mean().asscalar())
        test_ls.append(loss(net(test_features), test_labels).mean().asscalar())
    semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'loss', range(1, num_epochs + 1), test_ls, ['train', 'test'])
    print('L2 norm of w:', net[0].weight.data().norm().asscalar())
fit_and_plot(0)


在这里插入图片描述

L2 norm of w: 13.530375
fit_and_plot(3)


在这里插入图片描述

L2 norm of w: 0.04247173
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeGLMath

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值