Computing gradient of a value w.r.t a vector 0.4.0 vs 1.7

Ilya_Kotlov: <p>Hi.<br>
I try to adapt code which was written on pytorch 0.4.0 to a later version of torch 1.7.1,<br>
And in the old code I had:</p>
<pre><code>        grad_target = (output_cl * label).sum()
        grad_target.backward(gradient=label * output_cl, retain_graph=True)
</code></pre>
<p>But in my new pytorch version it complains about the fact that grad_target has dimension (<span class="chcklst-box fa fa-square-o fa-fw"></span>) and label*output_cl is a vector.</p>
<p>Here is the full traceback:</p>
<blockquote>
<p>Traceback (most recent call last):<br>
File “C:\Program Files\JetBrains\PyCharm 2021.1\plugins\python\helpers\pydev\pydevd.py”, line 1483, in _exec<br>
pydev_imports.execfile(file, globals, locals)  # execute the script<br>
File “C:\Program Files\JetBrains\PyCharm 2021.1\plugins\python\helpers\pydev_pydev_imps_pydev_execfile.py”, line 18, in execfile<br>
exec(compile(contents+“\n”, file, ‘exec’), glob, loc)<br>
File “C:/Users/Student1/PycharmProjects/new/main_wrapper.py”, line 42, in <br>
args.func(args)<br>
File “C:\Users\Student1\PycharmProjects\new\main.py”, line 99, in train_handler<br>
num_heatmaps=args.heatmaps_per_test)<br>
File “C:\Users\Student1\PycharmProjects\new\gain.py”, line 369, in train<br>
am_mask=sample[‘label/masks’])<br>
File “C:\Users\Student1\PycharmProjects\new\gain.py”, line 317, in forward<br>
return self._forward(data, label, extra_super, am_mask)<br>
File “C:\Users\Student1\PycharmProjects\new\gain.py”, line 531, in <em>forward<br>
output_cl, loss_cl, gcams = self.<em>attention_map_forward(data, labels)<br>
File “C:\Users\Student1\PycharmProjects\new\gain.py”, line 489, in <em>attention_map_forward<br>
grad_target.backward(gradient=label * output_cl, retain_graph=True)<br>
File “C:\Users\Student1\anaconda3\envs\new\lib\site-packages\torch\tensor.py”, line 221, in backward<br>
torch.autograd.backward(self, gradient, retain_graph, create_graph)<br>
File "C:\Users\Student1\anaconda3\envs\new\lib\site-packages\torch\autograd_<em>init</em></em>.py", line 126, in backward<br>
grad_tensors</em> = <em>make_grads(tensors, grad_tensors</em>)<br>
File "C:\Users\Student1\anaconda3\envs\new\lib\site-packages\torch\autograd_<em>init</em></em>.py", line 37, in _make_grads<br>
+ str(out.shape) + “.”)<br>
RuntimeError: Mismatch in shape: grad_output[0] has a shape of torch.Size([1, 20]) and output[0] has a shape of torch.Size(<span class="chcklst-box fa fa-square-o fa-fw"></span>).</p>
</blockquote>
<p>How can I change it preserving the original logic?</p>
<p>I wonder if I should just remove the gradient argument.</p>
<p>Thank you.</p>

albanD: <p>The problem is that <code>grad_target</code> contains a single scalar value (that’s what the size [] means).<br>
But label * output_cl is a whole vector. The gradient should be the same size as the Tensor, so a single scalar value here.</p>

Ilya_Kotlov: <p>Yes, I’ve already understood it from other similar issues. It worked in this way with pytorch==0.4.0, I guess the meaning of this was “derive results w.r.t each element in the vector”, so to remove it will do the work, don’t you think <a class="mention" href="/u/alband">@albanD</a> ?</p>
<p>At least after trying it, I see it gives me same results as in the old version, which I did manage to run on google Collab.</p>

albanD: <p>Yes, you should be able to remove that gradient argument.</p>

Ilya_Kotlov: <p><a class="mention" href="/u/alband">@albanD</a>, just final clarification, it will also be equivalent to write:</p>
<pre><code class="lang-auto">        grad_target = (output_cl * label)
        grad_target.backward(gradient=label * output_cl, retain_graph=True)
</code></pre>
<p>Because doing backward on the sum of <code>output_cl * label</code> with respect to itself as much as I understand is equivalent to doing backward on each multiplication element-wise, i.e minimizing each multiplication element-wise, which is minimal i.f.f the sum minimal, am I wrong?<br>
Is it equivalent ? If it doesn’t, so what is the meaning of this derivation comparing to the first one ?<br>
Appreciate your answering <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"><br>
Thanks.</p>

albanD: <p>That will be equivalent to the sum if you do <code>grad_target.backward(gradient=torch.ones_like(grad_target)</code></p>

Ilya_Kotlov: <p><a class="mention" href="/u/alband">@albanD</a>, now that O think about it, what does the ones vector mean?<br>
Because suppose the true labels are [0 0 1 0 0 1].<br>
and by multiplying output_cl * label I will get [0 0.5 0 0.5 0.5 0.5].</p>
<p>So the logic of derivation according to the multiclass labels and optimization problem should be:<br>
[0 0.5 0 0.5 0.5 0.5].backward(gradient=[0 0 1 0 0 1]) isn’t it ?<br>
because I want 1’s only in the true labels position (suppose in is one hot encoding), and not [1 1 1 1 1 1].</p>

albanD: <p>Hi,</p>
<p>The gradient argument here is not the gradient of the op you just did. But the gradient flowing back from the later functions.<br>
If you want to see it differently, it computes <code>gradient^T J</code> where J is the jacobian of your function that contains the derivatives.</p>

Ilya_Kotlov: <p>I see. So in the first time we backward, in the gradient argument it is naturally desired USUALLY one/s.</p>
<p><a class="mention" href="/u/alband">@albanD</a>, so correct if I wrong the gradient argument is useful, suppose in any situation when I calculated the gradient somehow manually for example, and now I want to continue with the gradient calculation, it is kind a manual hook to do back propagation, but usually the desired behavior is putting value/vector/matrix of ones ?</p>
<p>Any other scenarios of necessity of this argument and it’s use will be great to look at and understand it better, thank you.</p>

albanD: <p>Hi,</p>
<p>In 99.9% of the cases, the output loss is scalar and so what you want here is a single 1 (which is the default value) as this will compute the full gradient of your function.<br>
If there is more than one output, then there is no natural value to set so it has to be provided by the user.</p>
<p>Then the value you set depends what you want to do, there is no “usual” value in this case.<br>
I said a vector full of 1s because that corresponds to the sum() you were asking about. But that’s it.</p>
<p>There are very little cases where this arg is actually needed.<br>
The main one I know of is for backpropagation through time were you want to stage the backwardprop of each step independently so that you can run just the right number.<br>
In that case, you will need to manually chain the backward calls and you can use this argument for that.</p>

Ilya_Kotlov: <p>Excellent, thank you very much!</p>