https://zh.d2l.ai/chapter_linear-networks/linear-regression-concise.html
练习1的问题应该改成“如果我们用nn.MSELoss(reduction=‘sum’)替换 ,nn.MSELoss()”为了使代码的行为相同,需要怎么更改学习速率?为什么?
答:应该把学习率除以batch_size,因为默认参数是’mean’,换成’sum’需要除以批量数,一般会采用默认,因为这样学习率可以跟batch_size解耦(老师直播讲了~~
我测试了几次简洁实现和从零开始的代码,为什么基本上都是从零开始的损失更小呢?大部分从零开始的损失都是0.000050左右,而简洁实现大部分是0.000100左右
net[0].weight.grad是不是可以用来得到梯度?
Hi @dongming, 一般我们先call .backward()
再call .grad
。详见https://zh-v2.d2l.ai/chapter_preliminaries/autograd.html
我也是得到同样结果,epoch相同的情况下从零开始更优,请您有找到什么比较好的解释吗?
关于练习1,以下两种方式理论上等价,为何loss function取mean显著由于取sum的方式?
loss function reduction= ‘mean’ , lr=0.03:
epoch 1, loss 0.000361
epoch 2, loss 0.000095
epoch 3, loss 0.000095
w的估计误差: tensor([-0.0002, -0.0002])
b的估计误差: tensor([8.6784e-05])
loss function reduction = ‘sum’, lr =0.03/batch_size=0.003
epoch 1, loss 0.176310
epoch 2, loss 0.091707
epoch 3, loss 0.092358
w的估计误差: tensor([0.0007, 0.0012])
b的估计误差: tensor([0.0005])
mean意味着所有样本损失的平均值,即loss会除以样本数,sum没有除这个样本数,所以会放大1000倍(这里样本数为1000)
1.我刚才试验了几遍,由于按batch_size=10抽样本进行训练并计算损失,所以sum方式时应该用lr/10来弥补,即在optim中除10来替代loss fuction中除10,这个思路应该是没有问题的。
2.按mini batch方式训练,样本数并不为1000, 若用lr除1000得到的结果更离谱
num_epochs = 3
for epoch in range(num_epochs):
for X, y in data_iter:
l = loss(net(X) ,y)
trainer.zero_grad()
l.backward()
trainer.step()
l = loss(net(features), labels)
print(f’epoch {epoch + 1}, loss {l:f}’)
在线性回归的简洁实现中
每个epoch结尾处的计算loss并打印没有with torch.no_grad():(目的是将其移除计算图)
但是手动实现中却有,为什么它是如何保证每个epoch结束处的计算损失不会被计算入梯度
同样疑问,感觉这里是需要使用的no_grad去移除计算图再去计算的
小白表示还是有疑问,一次10个样本,理论上学习率除以10就可以了呀
net.parameter() or net[0].weight.requires_grad is set to True by default; while in sgd function, it declares: with torch.no_grad():.
loss function is executed out of the loop for gradient update backwardly. I don’t think it needs come with “torch.no_grad()”.
num_epochs = 3
for epoch in range(num_epochs):
for X, y in data_iter:
l = loss(net(X) ,y)
trainer.zero_grad()
l.backward()
trainer.step()
l = loss(net(features), labels)
print(f'epoch {epoch + 1}, loss {l:f}')
这段代码中的trainer.zero_grad()
应该要放在 l = loss(net(X) ,y)
前面吧?
为什么要放到前面,trainer.zero_grad()是清除上一轮所有结点的梯度值,和本轮的前向传播没有关系啊,我觉得没问题
请问在反向传播中
l.backward()
为什么不和上一讲一样对非标量进行累加后再反向传播?
谢谢!
我认为训练中的’l’和每个epoch结尾的’l’应该不是一个变量,(每次计算loss都是重新生成一个新的’l’?),所以应该不影响梯度计算
第3题:print(net[0].weight.grad)
可以去查看一下简洁实现版本的SGD源代码:
@torch.no_grad()
def step(self, closure=None):
"""Performs a single optimization step.
Arguments:
closure (callable, optional): A closure that reevaluates the model
and returns the loss.
"""
loss = None
if closure is not None:
with torch.enable_grad():
loss = closure()
......
有torch.no_grad()的
是不是在trainer.zero_grad()里实现的