报错信息
在程序中我的损失函数定义如下所示:
loss = nn.CrossEntropyLoss(reduction='none')
但在执行loss.backward()
时出现了下面这条报错信息:
RuntimeError: grad can be implicitly created only for scalar outputs
原因分析
在定义损失函数loss
时,我们设置了参数reduction='none'
,这导致我们计算出的loss
是一个二维的张量,行数为batchsize
的大小。
backward
只有对标量输出时才会计算梯度,而无法对张量计算梯度。
解决办法
将张量转变成一个标量,比如我们可以对loss
求和,然后用求和得到的标量再反向传播求各个参数的梯度,这样不会对结果造成影响。
1.loss.backward
👉 loss.sum().backward
或者 loss.backward
👉 loss.backward(torch.ones_like(loss))
上面这两个方法表示对loss
求和后再进行反向传播,其中第一个方法比较好理解,第二方法中的torch.ones_like(loss)
是传入的grad_tensors
参数,表示创建了一个与loss
同样大小的全1张量,另loss
与torch.ones_like(loss)
点乘后再进行反向传播,也相当于对loss
求和后再进行反向传播。
grad_tensors
的作用其实可以简单地理解成在求梯度时的权重,因为可能不同值的梯度对结果影响程度不同,所以pytorch弄了个这种接口,而没有固定为全是1。
2.loss = nn.CrossEntropyLoss(reduction='none')
👉 loss = nn.CrossEntropyLoss()
reduction 参数有三种选择:
elementwise_mean
:为默认情况,表明对N个样本的loss进行求平均之后返回sum
:指对N个样本的loss求和none
:表示直接返回N个样本的loss