权重衰减 讨论区


#42

Gluon中指定学习率和权重衰减如何实现?

mxnet中自定义一个全连接层,分别指定weight与bias的学习率和权重衰减
_weight = mx.symbol.Variable(“fc7_weight”, shape=(args.num_classes, args.emb_size), lr_mult=args.fc7_lr_mult, wd_mult=args.fc7_wd_mult)
_bias = mx.symbol.Variable(‘fc7_bias’, lr_mult=2.0, wd_mult=0.0)
fc7 = mx.sym.FullyConnected(data=embedding, weight = _weight, bias = _bias, num_hidden=args.num_classes, name=‘fc7’)

Gluon中实现好像很麻烦,需要分别对权重和偏差构造 Trainer 实例
比如3.12.4中说的:
#对权重参数衰减。权重名称一般是以 weight 结尾。
trainer_w = gluon.Trainer(net.collect_params(’.*weight’), ‘sgd’,
{‘learning_rate’: lr, ‘wd’: wd})
不对偏差参数衰减。偏差名称一般是以 bias 结尾。
trainer_b = gluon.Trainer(net.collect_params(’.*bias’), ‘sgd’,
{‘learning_rate’: lr})

如果我有几个不同层需要不同的lr和wd_decay那训练的代码不会写得很复杂?是否会构造多个trainer呢??
Gluon中如何才能实现mx.symbol.Variable那样简洁的实现呢?


#43

我也在想这个问题


#44

同感!
在gluon的loss中没有L2惩罚项,不太理解
请大神解释下:rofl:

在gluon的实现中,loss加上了L2惩罚项后,


效果和没有时,基本一致


#45

是不是因为

他只是在后向的时候对W1添加了系数?


#46

请问 L2 正则化应该是除样本数 例子里面样本数是20 为什么代码里面却是2

def l2_penalty(w):
return (w**2).sum() / 2

按道理应该是

def l2_penalty(w):
return (w**2).sum() / 20

发了个pull request


#47

不用除以样本数,惩罚力度都交给 \lambda 调节


#49

式子没问题,你的 L2 惩罚项最终是要混合进 loss 的式子里面的,在下面的 sgd 算法中,被减去的损失函数求导的部分中,除以了 batch_size ,所以在成本函数中、 L2 惩罚项中,都不需要除以样本数


#50

我为什么觉得这里的权重衰减来减轻过拟合的程度只是一种巧合。通过增加L2范数惩罚项来让权重接近0,从而让图像看起来没那么过拟合,但是这是因为在前面生成的数据中所有的真实权重全都为0.01,在lamdb为3的情况下,要是把0.01换成0.1,图像上看起来过拟合还是很严重,当换成1的时候,这种增加L2范数惩罚项的方法几乎不起作用。


#51

我使用
trainer = gluon.Trainer(net.collect_params(), ‘adam’, {‘learning_rate’: lr, ‘wd’: 3}) # 训练器
其中 wd设置为 3,结果 测试精度变为 0.5了,请问 这是什么原因?


#52

我前几天也是为这个问题做了不少尝试。

首先我在l上自行增加了除以batch_size的操作(l = loss(net(X, w, b), y) + lambd * l2_penalty(w) / batch_size),结果表现很糟糕(为了让batch_size起到作用,我把它改成了2,因为原文中是1,除以1毫无意义),说明不应该做这个操作。

然后我继续观察l = loss(net(X, w, b), y) + lambd * l2_penalty(w)。当batch_size大于1时,l应该不是标量。按照自动求梯度那一章的说法,求梯度前会自动求和。所以它会自动将batch中每一个样本形成的式子加起来,其中w是未知数。那么这里要注意一点,lambd * l2_penalty(w)会是一个标量,所以这里的相加,会使用广播的方式。因此,最后加起来的式子中,会有batch_size个lambd * l2_penalty(w)(这点我自己通过做了简易函数做实验确认了),然后再求的梯度。那么求的梯度里应该也有batch_size * w1 * lambd。

求完梯度做随机梯度下降的时候,sgd自己会根据输入的batch_size来做除法。因此除完之后的结果式子上就完全没有batch_size了(正好和上一段的batch_size抵销了)。

因此我认为,本章节一开始写的公式是错的。
带有L2范数惩罚项的新损失函数公式中,n就不应该有;
w1和w2的迭代方式的公式中|B|也不应该有才对。


#53

weight_decay就是和L2正则化一样的效果,上面加penalty是因为没有加weight_decay,而gluon里面用了weight_decay,在求loss的时候是自动加上penalty的


#54

请问在权重衰减的从零开始实行代码中batch size是不是只能为1啊,如果大于1的话在计算总损失的时候由于广播机制会在loss的每一维都加上l2范数惩罚项,这样总的损失就相当于加上了batch size倍的l2范数惩罚项了,请问这样理解对不对呢?


#55

恩,我觉得你说得对,因为loss如果不是标量的话会有问题,loss求和得到之后再加上penalty就没问题了


#56

对啊,我也觉得加上.sum()会好一些。


#57

我查过这个问题,后来把我实验的结果写在了上面那个回复的帖子里面。你可以参照下,大概是十几天前回复的(大概在50楼)。你可以照着做下实验。我的结论是文中列出的公式错了,但code是对的。


#58

我看了你之前的回复,感觉我们说的是一个意思,感觉就是公式和程序表达不一致。但感觉就是在关于l2范数惩罚项导数上多乘了一个batch size常数的问题。


#59

嗯,不过我是觉得本来就应该乘了一个batch size,因为如果通过做实验我发现不乘的话结果明显要差很多。不知道你的实验结果和我是否一致?


#60

我没有做这方面的实验,只是验证了一下当batch size大于1时loss会不会由于广播机制每一维都加上一个l2范数惩罚项。