前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【动手学深度学习笔记】之通过权重衰减法解决过拟合问题

【动手学深度学习笔记】之通过权重衰减法解决过拟合问题

作者头像
树枝990
发布2020-08-19 22:33:43
1.3K0
发布2020-08-19 22:33:43
举报
文章被收录于专栏:拇指笔记拇指笔记

点击【拇指笔记】,关注我的公众号。

1.通过权重衰减解决过拟合问题

1.1 权重衰减

为了减轻上一篇文章提到的过拟合现象,往往需要增大训练集,但增大训练集的代价往往是高昂的。

因此这里介绍一种常用的缓解过拟合问题的方法:权重衰减。

1.2 实现方法

权重衰减通过惩罚绝对值较大的模型参数为需要学习的模型增加了限制。权重衰减等价于范数正则化。正则化通过为模型损失函数添加惩罚项使学习得到的模型参数值较小。

范数正则化在模型原损失函数基础上添加范数惩罚项,范数惩罚项指的是模型权重参数()每个元素的平方和与一个正的常数的乘积。

以如下这个损失函数为例

对应的迭代方程为

它的带有范数惩罚项的新损失函数为

其中为超参数()。当较大时,惩罚项比重较大,这会使学到的权重参数较接近0。当为0时,惩罚项完全不起作用。

当优化算法为小批量随机梯度下降(SGD)时,的迭代方程b变为

由此可见,因为添加了范数正则化,迭代方程中的权重参数自乘了一个小于1的数()。因此范数正则化又叫做权重衰减。实际场景中,有时也需要在惩罚项中添加偏差元素的平方和。

1.3 引入过拟合问题

以高维线性回归为例,引入过拟合问题。

以下面这个维度为的线性函数为例,生成人工数据集。

噪声项服从均值为0,标准差为0.01的正态分布。假设,训练集样本数为20。

1.3.1 生成人工数据集

代码语言:javascript
复制
根据模型,随机生成特征值,计算得到标签。
n_train,n_test,num_inputs = 20,100,200
true_w,true_b = torch.ones(num_inputs,1)*0.01,0.05
#设置为与输入数据同形,方便计算
features = torch.randn((n_train+n_test,num_inputs))
#随机生成训练集和测试集中的特征值
labels = torch.matmul(features,true_w)+true_b
labels += torch.tensor(np.random.normal(0,0.01,size = labels.size()),dtype = torch.float)
#生成训练集和测试集中的标签
train_features = features[:n_train,:]
test_features = features[n_train:,:]
train_labels = labels[:n_train,:]
test_labels = labels[n_train:,:]
#分割测试集和训练集

1.3.2 定义和初始化模型

先将权重参数和偏差参数初始化,

代码语言:javascript
复制
def init():
	w = torch.randn((num_inputs,1),requires_grad = True)
    b = torch.zeros(1,requires_grad = True)
    return [w,b]

代码语言:javascript
复制
def linear(x,w,b):    return torch.mm(x,w)+b

1.3.3 定义损失函数和优化函数

使用之前在线性回归中介绍的平方误差函数和小批量随机梯度下降算法。

代码语言:javascript
复制
#平方误差损失函数
def square_loss(y_hat,y):
    return (y_hat-y.view(y_hat.size()))**2/2

#小批量随机梯度下降
def sgd(params,lr,batch_size):
    for param in params:
        param.data -= lr*param.grad/batch_size

1.3.4 定义范数惩罚项

这里只惩罚权重参数。

代码语言:javascript
复制
def l2(w):    return (w**2).sum()/2

1.3.5 训练模型

代码语言:javascript
复制
batch_size,num_epochs,lr = 1,100,0.003
net,loss = linear,square_loss

dataset = torch.utils.data.TensorDataset(train_features,train_labels)
train_iter = torch.utils.data.DataLoader(dataset,batch_size,shuffle = True)

def train(lambda1):
#通过设置lambda=0,可以实现过拟合效果。设置lambda=3,实现权重衰减,减轻过拟合。
    w,b = init()
    train_ls,test_ls = [],[]
    for epoch in range(num_epochs+1):
        for x,y in train_iter:
            l = loss(net(x,w,b),y) +lambda1*l2(w)
            l = l.sum()
            
            if w.grad is not None:
                #如果权重参数的梯度信息不是None,代表已经开始计算,需要进行梯度清零
                w.grad.data.zero_()
                b.grad.data.zero_()
            l.backward()
            sgd([w,b],lr,batch_size)
        train_ls.append(loss(net(train_features,w,b),train_labels).mean().item())
        test_ls.append(loss(net(test_features,w,b),test_labels).mean().item())
        print('权重参数的L2范数',w.norm().item())

1.3.6 过拟合效果

代码语言:javascript
复制
#令lambda=0,L2范数为0。即不开启权重衰减
train(0)

过拟合情况下,对数化的训练误差和泛化误差随学习周期的变化如图

可以看出,出现了严重的过拟合。

1.3.7 使用权重衰减矫正过拟合

代码语言:javascript
复制

#令lambda=3,开启权重衰减
train(3)

使用权重衰减后,对数化的训练误差和泛化误差随学习周期的变化如图

代码语言:javascript
复制
不难看出,使用权重衰减法后, 过拟合现象得到一定程度的缓解。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 拇指笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.通过权重衰减解决过拟合问题
    • 1.1 权重衰减
      • 1.2 实现方法
        • 1.3 引入过拟合问题
          • 1.3.1 生成人工数据集
          • 1.3.2 定义和初始化模型
          • 1.3.3 定义损失函数和优化函数
          • 1.3.4 定义范数惩罚项
          • 1.3.5 训练模型
          • 1.3.6 过拟合效果
          • 1.3.7 使用权重衰减矫正过拟合
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档