1.5.模型选择

模型选择

训练误差和泛化误差

  • 训练误差:模型在训练数据上的误差
  • 泛化误差:模型在新数据上的误差

验证数据集和测试数据集

  • 验证测试集合:用来评估模型好坏的数据集

    不要和训练数据集搞混了,先训练后,用来验证一下超参数是否合适

  • 测试数据集:只用一次的数据集

K-折交叉验证

​ 大多数情况下没有足够多的数据来使用,可使用K-则交叉验证

  1. 将训练数据分割成K块

    1. 循环K次,当循环第i次时,使用第i块作为验证数据集,其余的作为训练数据集
    2. 报告K个验证集误差的平均

    常用:K=5或K=10

过拟合和欠拟合

模型容量\数据简单复杂
正常欠拟合
过拟合正常

模型容量

​ 模型容量指拟合各种函数的能力,低容量的模型难以拟合训练数据,高容量的模型可以记住所有的训练数据。

模型容量的影响

在这里插入图片描述

估计模型容量

难以在不同的种类算法之间比较:树模型和神经网络

给定一个模型种类,将有两个主要因素:

  • 参数的个数
  • 参数值的选择范围

在这里插入图片描述

VC维

​ 给定一个分类模型,VC等于一个最大的数据集的大小,不管如何给定标号(label),都存在一个模型来对它进行完美分类。

线性分类器的VC维

​ 对于2维输入的感知机,VC维=3,能够分类任何3个点,但不能分类4个(异或问题)

​ 支持N维输入的感知机的VC维是N+1

​ 一些多层感知机的VC维是 O ( N l o g 2 N ) O(Nlog_2N) O(Nlog2N)

数据复杂度

​ 样本个数,每个样本的元素个数,时间、空间结构,多样性

权重衰退(weight decay)

​ 比较常见的处理过拟合的办法

控制模型的容量:

  1. 使用小模型,减少参数的个数
  2. 控制参数值的选择范围

权重衰退就是用过限制参数值的选择范围来控制模型容量

使用均方范数作为硬性限制

m i n   l ( w , b )    s u b j e c t   t o   ∣ ∣ w ∣ ∣ 2 ≤ θ min\ l(w,b)\ \ subject\ to\ ||w||^2\le\theta min l(w,b)  subject to ∣∣w2θ

  • 通常不限制偏移b(限不限制都差不多)
  • 小的 θ \theta θ意味着更强的正则项

使用均方范数作为柔性限制

​ 对于每个 θ \theta θ,都可以找到 λ \lambda λ使得之前的目标韩式等价于
m i n   l ( w , b ) + λ 2 ∣ ∣ w ∣ ∣ 2 min\ l(w,b)+\frac{\lambda}{2}||w||^2 min l(w,b)+2λ∣∣w2
​ 超参数 λ \lambda λ控制了正则项的重要程度

  • λ = 0 \lambda =0 λ=0:无作用
  • λ → ∞ , w ∗ → 0 \lambda\rightarrow \infty,w^*\rightarrow 0 λ,w0

图示影响

在这里插入图片描述

​ 将 λ 2 ∣ ∣ w ∣ ∣ 2 \frac \lambda 2 ||w||^2 2λ∣∣w2项叫做罚,假设只有两个参数,是二维的,等高线上的每一点值都是一样的。可以看出 w ^ ∗ \hat w ^* w^离原点很远,沿梯度下降后,再加上罚,可以到达 w ∗ w^* w,可以认为是平衡点。远离 w ∗ w^* w的值,梯度下降(远离)的强度没有罚的项大,则会逐渐拉回到 w ∗ w^* w,达到平衡。

在这里插入图片描述

​ 可以再加上这个二次函数理解,离原点较远时,梯度下降很快,罚的值也很大,可以快速的回到原点,当接近原点时,梯度下降变慢了,罚的值也会相应变小,减缓下降速度,避免过拟合。

参数更新法则

​ 计算梯度
∂ ∂ w ( l ( w , b ) + λ 2 ∣ ∣ w ∣ ∣ 2 = ∂ l ( w , b ) ∂ w + λ w \frac{\partial}{\partial w}(l(w,b)+\frac{\lambda}{2}||w||^2=\frac{\partial l(w,b)}{\partial w}+\lambda w w(l(w,b)+2λ∣∣w2=wl(w,b)+λw
​ 时间t更新参数( η \eta η是学习率):
w t + 1 = ( 1 − η λ ) w t − η ∂ l ( w t , b t ) ∂ w t w_{t+1}=(1-\eta \lambda)w_t -\eta \frac{\partial l(w_t,b_t)}{\partial w_t} wt+1=(1ηλ)wtηwtl(wt,bt)
​ 注意到多了 η λ \eta\lambda ηλ这一项,通常 η λ < 1 \eta \lambda <1 ηλ<1,在深度学习中通常叫做权重衰退。

权重衰退通过L2正则项使得模型参数不会过大,从而控制模型复杂度。正则项权重是控制模型复杂度的超参数。

import torch
from torch import nn
from d2l import torch as d2l

# 生成一个人工数据集
# y = 0.05 + \sum 0.01x_i + 噪音  噪音满足N(0,0.0001)

n_train, n_test, num_inputs, batch_size = 20, 100, 200, 5  # 训练数据小,就容易过拟合
true_w, true_b = torch.ones((num_inputs, 1)) * 0.01, 0.05  # 每一项的权重都是0.01,偏置为0.05
train_data = d2l.synthetic_data(true_w, true_b, n_train)
train_iter = d2l.load_array(train_data, batch_size)
test_data = d2l.synthetic_data(true_w, true_b, n_test)
test_iter = d2l.load_array(test_data, batch_size, is_train=False)


# 初始化模型参数
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]


# 定义L2范数惩罚
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  # lambda临时函数
    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())
    d2l.plt.show()


# train(lambd=0) #过拟合
train(lambd=6)  # 还行的拟合

'''简洁写法'''


def train_concise(wd):
    net = nn.Sequential(nn.Linear(num_inputs, 1))
    for param in net.parameters():
        param.data.normal_()  # 参数正态分布处理
    loss = nn.MSELoss(reduction='none')
    num_epochs, lr = 100, 0.003
    # 偏置参数没有衰减
    trainer = torch.optim.SGD([
        {"params": net[0].weight, 'weight_decay': wd},  #传入w和lambda,直接在算法中使用权重衰退
        {"params": net[0].bias}], lr=lr)
    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:
            trainer.zero_grad()
            l = loss(net(X), y)
            l.mean().backward()
            trainer.step()
        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范数:', net[0].weight.norm().item())

在这里插入图片描述

没有正则化,由于数据很少,直接过拟合了

在这里插入图片描述

λ \lambda λ取6时候的值,有比较好的效果

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值