线性回归的从零开始实现

假如y_hat.shape为[2,1]而y.shape为[1,2],那么由于广播机制,y_hat - y 的shape是[2,2],这样就导致loss的值算的不正确。

因为规则导致去执行广播而不是报错,会导致很难发现这个错误,使用reshape是非常推荐的做法。

def squared_loss(y,y_hat):
return (y - y_hat) ** 2 / 2

def squared_loss(y,y_hat):
return (y.reshape(y_hat.shape) - y_hat) ** 2 / 2
的结果大相径庭 这是为什么

找到问题所在了
def squared_loss(y,y_hat):
#这里必须要要将y reshape一下 因为他是一个向量e.g. Size[10] 而y_hat是一个矩阵 e.g.Size[10,1] 如果缺少了这个操作 pytorch的广播机制会将其结果变成Size[10,10] 一定要小心!!!
return (y.reshape(y_hat.shape) - y_hat) ** 2 / 2

这里面传的参数是 ’列表‘ 而不是 ‘普通的变量’ 传递列表的时候就相当于别的语言的数组,你在函数内对传过来的数组操做同样改变了原数组的值,一个道理。如果传过来的是int型就改变不了了 因为传递的不是引用 而是copy

我认为“reshape()把梯度grad也带上一起reshape了”是不正确的。

我做了以下实验:

"""
注意看下面的代码,原size是[2,1], 仍reshape为[2,1]
如果你的说法是正确的,即reshape会涉及到w.grad的shape,那么此时w.grad的shape也不会改变
但是训练过程中会报相同的错误
"""
w = torch.zeros((2,1), requires_grad=True).reshape(2,1)

"""
注意看下面的代码,我们在reshape操作之后再进行requires_grad属性的设置
这样,在训练过程中不会报错
我们再回看上面一段代码,reshape操作是在requires_grad设置为True之后
所以一个合理的推测是,requires_grad设置为True之后,对w变量的很多操作都会被跟踪,
并建立起计算图。所以上面一段代码中的reshape操作被跟踪,对w的梯度产生了影响,而下面的就不会
"""
w = torch.zeros((1, 2)).reshape(2,1) # w的正确的size是[2,1]
w.requires_grad_(True)

大哥,params是函数参数啊,全局环境里的params是作为参数传递到函数里的。你说的函数内能直接访问外部环境变量是闭包,这是两码事

這個是為了不要累積到梯度吧,每次更新完都要清空一次

执行d2l.set_figsize()时报错
AttributeError: module ‘d2l’ has no attribute ‘set_figsize’
这是什么原因呢?

你没有在当前代码定义这个函数,不过这个函数在d2l里定义了,所以你可以.synthetic_data调用

你好,我在gitHub仓库中找到了关于本书习题的答案,希望这对你有所帮助
仓库链接:GitHub - datawhalechina/d2l-ai-solutions-manual: 《动手学深度学习》习题解答,在线阅读地址如下: