Initialize tensor in autograd function

cbd: <p>I want to initialize tensor “a” as shown in below code and want to access it in forward call. But it shows the " NameError: name ‘a’ is not defined "</p>
<p>import torch<br>
import torch.nn as nn<br>
from torch.autograd import Function<br>
class run(Function):</p>
<p>def <strong>init</strong>():<br>
a=torch.linspace(0,1,0.2)</p>
<p><span class="mention">@staticmethod</span><br>
def forward(cxt,input):<br>
cxt.save_for_backward(input)<br>
print(" a is ",a)<br>
return input</p>
<p><span class="mention">@staticmethod</span><br>
def backward(self,cxt, grad_output):<br>
input, = cxt.saved_tensors<br>
grad_input = grad_output.clone()<br>
grad_input[input &lt; 0] = 0<br>
return grad_input</p>
<p>fun1 = run.apply</p>
<p>if <strong>name</strong> == “<strong>main</strong>”:<br>
from torch.autograd import Variable<br>
x=torch.tensor(2.0,requires_grad=True)<br>
vc=fun1(x)</p>

albanD: <p>Hi,</p>
<p>Custom Functions are stateless. So defining the <code>__init__()</code> function does nothing. Only the forward/backward static functions are used.<br>
If you create your Tensor directly inside the <code>forward()</code> function and save it on the ctx as <code>ctx.a = a</code> if you want to have it for the backward as well.</p>

cbd: <p>I am just thinking not to create tensor every time when forward is called OR not pass by value during forward call as i don’t want it to backpropagate.</p>
<p>One more question which i don’t understand for ReLU backward function is how loss is backpropagate using chain rule of dL/(d(w))=dL/(d(relu_out))     (d(relu_out))/(d(relu_in))    (d(relu_in))/(d(w))?</p>
<p>As per my understanding 1st term on RHS is “grad_output” which is 1, 2nd term is “grade_input” which is also 1 and 3rd term is “relu_input” lets say it is (w * x) then derivatives become x only.</p>
<p>So from chain rule answer is  1 * 1 * x = x which multiply with learning rate and weight “w”  will change accordingly.</p>
<p>Now the question is if loss value is 0.2 OR it change to 0.8, how it participate to change the weight value? As in both the case passed value of grad_input and grad_output is 1.</p>
<p>Please let me correct if i misunderstood something.</p>

albanD: <blockquote>
<p>I am just thinking not to create tensor every time when forward is called OR not pass by value during forward call as i don’t want it to backpropagate.</p>
</blockquote>
<p>If you really want to do that, you can just have it as a global in your python file and re-use it.<br>
But I would advise against doing that as globals are quite dangerous in general!<br>
Recreating it in the forward shouldn’t cost you much if you don’t use the function thousands of times every time to forward through your net.</p>
<blockquote>
<p>“grad_output” which is 1</p>
</blockquote>
<p>That is not true in general, this is actually whatever the grad computed by the other layers is (lower layers).</p>
<blockquote>
<p>“grade_input” which is also 1</p>
</blockquote>
<p>Is again that depends on the other layers (the ones above you this time).</p>

cbd: <aside class="quote no-group" data-username="albanD" data-post="4" data-topic="111231">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<p>That is not true in general, this is actually whatever the grad computed by the other layers is (lower layers).</p>
</blockquote>
</aside>
<p>Let’s say input is given to convolution layer and output of convolution layer is given to ReLU activation function. From output of ReLU, loss is calculated. Assume L1 loss and lets say loss value is 0.2.</p>
<p>So for ReLU, grad_output is coming from L1 loss (lower layer as per your reply i think) and grad_input is given to convolution layer (upper layer) . As per the autograd function of ReLU, “grad_output” (dL/(d(relu_out)) is always 1 (<a href="https://github.com/DingKe/pytorch_workplace/blob/master/basic/functions.py" rel="noopener nofollow ugc">https://github.com/DingKe/pytorch_workplace/blob/master/basic/functions.py</a> ) as ReLU function is f(x) =x and L1_loss = F(x) - target. So derivative with respect to relu_out which is F(x) becomes 1. That is why i am thinking “grad_output” pass to backward function of ReLU is 1.</p>
<aside class="quote no-group quote-modified" data-username="albanD" data-post="4" data-topic="111231">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<blockquote>
<p>“grade_input” which is also 1</p>
</blockquote>
<p>Is again that depends on the other layers (the ones above you this time).</p>
</blockquote>
</aside>
<p>As per the backward function of ReLU, return value of function is “grade_input” and is always 1.</p>
<p>If output of convolution convolution layer is w*x which is input ot relu_in then (d(relu_in))/(d(w)) will be x.</p>
<p>So dL/(d(w))=dL/(d(relu_out)) (d(relu_out))/(d(relu_in)) (d(relu_in))/(d(w)) = 1 *1 *x=x.</p>
<p>New weight updation will be, w_new = w - learning_rate *  dL/(d(w))</p>
<p>So the question is, how loss has contributed to change in weight? I hope i clarified my understanding. Please let me know what i misunderstood if i am wrong.</p>

albanD: <p>Thanks for the details.<br>
So indeed for that particular net of conv + relu + l1, you get this result (i didn’t dive into the calculation but that sounds plausible).</p>
<blockquote>
<p>So the question is, how loss has contributed to change in weight?</p>
</blockquote>
<p>The actual value of the loss does not in this case. If you look at the overall function you wrote, it is actually linear at that point with slope <code>x</code>. So the only thing that will influence in which direction you should move is going to be <code>x</code>.<br>
The simplest analogy here is a 1D identity function: whatever the current point, the gradient is always 1 (the slope x in your example). So you should move to lower values. The actual value of the function is not changing anything.</p>
<p>You can try to do the same computation with a l2 loss (that is not linear) and you will see that the value of the loss will start appearing in the final result.</p>

cbd: <aside class="quote no-group" data-username="albanD" data-post="6" data-topic="111231">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<p>So the only thing that will influence in which direction you should move is going to be <code>x</code>.</p>
</blockquote>
</aside>
<p>Just going one level deeper. Lets say i want to predict y = <strong>2</strong>*x and initial weight = 1 which we want to be <strong>2</strong> as we want y_pred = w * x. Lets say every time we give the input value x=2 and learning_rate = 0.1 so the weight change at step (1) according to</p>
<aside class="quote no-group" data-username="cbd" data-post="5" data-topic="111231">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/c/13edae/48.png" class="avatar"> cbd:</div>
<blockquote>
<p>w_new = w - learning_rate * dL/(d(w))</p>
</blockquote>
</aside>
<p>is 0.8 (1- 0.1 * 2). Again same input x=2 given so in step (2), w_new = 0.6 (0.8 - 0.1<em>2). For the same input x=2, in step (3), w_new = 0.4 (0.6-0.1</em>2). Even if you change x to any positive value it is going to decrease and w_new never converge to value 2 and so the network.</p>
<p>It means we should never take ReLU output as our final output ? OR should i missed something?</p>

albanD: <aside class="quote no-group" data-username="cbd" data-post="7" data-topic="111231">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/c/13edae/48.png" class="avatar"> cbd:</div>
<blockquote>
<p>Lets say i want to predict y = <strong>2</strong>*x and initial weight = 1 which we want to be <strong>2</strong> as we want y_pred = w * x. Lets say every time we give the input value x=2 and learning_rate = 0.1</p>
</blockquote>
</aside>
<p>I’m sorry I can’t really follow this.<br>
What would be the pair <code>(x, expected_y)</code> that you want?<br>
What would be the initial weights w0?</p>
<blockquote>
<p>It means we should never take ReLU output as our final output ?</p>
</blockquote>
<p>It is not advised in general no. Mainly because it does not have any benefit (if you’re value is positive, it will just be an identity) and has the drawback of potentially getting your training stuck if the value becomes negative (as you will get 0 gradient and nothing will move anymore).</p>
<blockquote>
<p>OR should i missed something?</p>
</blockquote>
<p>Be careful here that for the l1 loss, the gradient can be 1 or -1 depending on the sign of the difference! That will make sure you don’t keep going in one direction forever.</p>

cbd: <aside class="quote no-group" data-username="albanD" data-post="8" data-topic="111231">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<p>Be careful here that for the l1 loss, the gradient can be 1 or -1 depending on the sign of the difference! That will make sure you don’t keep going in one direction forever.</p>
</blockquote>
</aside>
<p>Okay. Now its clear. Thanks a lot for continue reply.</p>