线性回归的简洁实现 讨论区


#21

以教程里举的例子看, num_examples=1000, epoch=5,batch_size=10,所以总共是迭代了500次,更新了500次参数吗?


#22

请问loss.backward()求得的梯度的就是param.grad吗?在SGD函数的定义里也同样做了除以batch_size的处理吗?


#23
def SGD(params, lr):
    for param in params:
        #param[:] = param - lr * param.grad
        param = param - lr * param.grad

你好,请问为什么上面的式子最后求出的loss没有效果?

2222222


#24

嗯对,每个batch更新一次参数。
Gluon里定义的loss已经包含了除以batch size求mean的操作


#25

因为上面的数据类型都是ndarray, 如果不用param[:]的话所有的运算操作都会生成一个新的ndarray,而不是在本来的ndarray做in-place的更新


#26

哦哦,谢谢


#27

这个我就有点奇怪了,根据梯度下降的公式应该是需要样本梯度的平均,为什么这将这个1/n的n提出来了,我可以理解为在某些情况下不做均值也可以是吧,这样就下降的更快。


#28

我的理解是:

原文中的代价之和(nd.sum(loss))与learning_rate/batch_size这两个操作可以替代先求平均代价再sgd。

因为你说的1/n(即为1/batch_size)为一常数,在求导过程中,只要最后乘上即可。那么我们将这常数与learning_rate结合,就成了上面的形式。

所以,我觉得道理上来说,这两者完全等同。至于在实操中,速度上我个人认为也没有什么变化(或者很小)。仅仅是殊途同归的两种数学变化。


#29

这个没有除以batch_size. 如果batch_size =15,官方可以理解为这样,nd.sum(loss).bacward(),继续理解的话可以这样想:首先是函数关于参数的导数(全部用抽象的字母表述的函数),然后再看成将这15个样本点数据带入,求和。如果batch_size =15, 那就是15个样本点的 [loss梯度的] 加和。希望我已经描述清楚。


#30

怎么理解 nd.sum(loss).asscalar() 的asscalar()呢


#31

怎么理解 nd.sum(loss).asscalar() 的asscalar()呢


#32

就是把只有一个元素的tensor里的这个数拿出来


#33

这里取最小是害怕超出num_example,因为取得范围就是在 ii+batch_size 。如果取到最后,假设 num_example 不是 batch_size 的整数倍。这时候这里的 min(i+batch_size, num_example) 的作用就能体现出来了。


#34

是的是的,谢谢


#35

调用help函数写的很清楚


#36

我反复看了,linear-regression-scratch里面的确是没有除以batch_size。

  1. 我认为笔者在linear-regression-gluon里面专门让我们注意trainer.step(batch_size),并不是想说“线性回归这个模型的梯度下降会受batch_size=10带来很大的影响”。
  2. batch_size=10不是很大,但是严谨来说除以batch_size肯定是更好的,trainer.step()这个方法作为mxnet一个重要方法,当然要考虑batch_size这个参数。毕竟很有可能在很多情况下,batch_size会造成很大影响。
    总而言之
  3. linear-regression-scratch里面的确是没有除以batch_size,但在这个例子中,也许是因为batch_size不够大的原因,也有可能是线性回归不太受batch_size的影响。
  4. 为了兼顾其他情况,trainer.step()中会除以batch_size,这样是最严谨的。

#37

X = nd.random_normal(shape=(2,5))
X_prob = softmax(X)
print(X_prob)
print(X_prob.sum(axis=1))

结果为:
[[ 0.21869159 0.23117994 0.18298376 0.1587515 0.20839317]
[ 0.39214477 0.1804826 0.02733301 0.08681861 0.31322101]]
<NDArray 2x5 @cpu(0)>

[ 0.99999994 1. ]
<NDArray 2 @cpu(0)>

这个代码没理解,这个axis=1是列啊- -
那么在softmax的结果(一个2行5列的矩阵)上对列求和,就是把每一列的结果加起来,不是应该得到一个1行5列的矩阵么。。怎么会得到一个[1 1.]的结果呢?


#38

预备知识里面已经提到,当x不是一个标量而是一个向量的时候的 x.backward() 等价于 x.sum().backward(),所以loss = square_loss(output, label) loss.backward() 就是对一个batch.size里面的10个样本的损失和来对参数求导,在从0开始那一节直接用这个和来求导更新参数,在这一节使用trainer.step(10),相当于对loss除以10之后求导更新参数,所以前一节的梯度是这一节的梯度的10倍,所以在本节中lr增大10倍,从而达到相同的结果。可以通过打印前后两节的梯度观察这一结果


#39

第一个使用的是平方和,10个一组
第二次使用的是均方误差,比第一次小了10倍
故···


#40

我一开始也很好奇这个问题,
首先,注意到一点,在一个函数内部做这样的赋值操作,相当于在函数内部生成了一个新的局部变量叫 param,而所有在这个函数内部对于自己新建的这个param的操作不会影响到全局中的param的值。所以这里如果这样更新,全局中的weight是不会改变的。解决方法是,
使用nonlocal(python3)让python认识到自己在对weight做操作