Getting RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn even if I included 'requires_grad = True'

Song1: <p>Hi, I started studying pytorch recently and I’m stuck in a problem. The codes below trains w[0], …, w[8] which are the 2 * 2 elements of a weight matrix. The weight matrix is in the function named forward. I want to train w[1], …, w[8] to produce y from a. But after operating the codes, an error occurred. It is ‘RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn.’ I had tried to find causes but I can’t find and understand them. The original code is much more long, the code below is a simplified version. Would you help me how to fix the problem? Any help would be highly appreciated.</p>
<pre><code class="lang-auto">import torch
</code></pre>
<pre><code class="lang-auto">eta_n = torch.arange(1.0, 0, - 0.1)
#eta_n = torch.cat([torch.arange(1.0, 0.2, -0.1), torch.arange(0.2, 0, -0.01)], dim = 0)
delta_eta = eta_n[1:] - eta_n[0:-1] #Difference between the elements of eta_n. In this case, every element is -0.1.
eta_fin = eta_n[-1]
print('eta_n:', eta_n)
print('len(eta_n):', len(eta_n))
print('delta_eta:', delta_eta)
print('len(delta_eta) which is the no. of forward propagations:', len(delta_eta))
print('eta_fin:', eta_fin)
</code></pre>
<p>eta_n: tensor([1.0000, 0.9000, 0.8000, 0.7000, 0.6000, 0.5000, 0.4000, 0.3000, 0.2000, 0.1000])<br>
len(eta_n): 10<br>
delta_eta: tensor([-0.1000, -0.1000, -0.1000, -0.1000, -0.1000, -0.1000, -0.1000, -0.1000, -0.1000])<br>
len(delta_eta) which is the no. of forward propagations: 9<br>
eta_fin: tensor(0.1000)</p>
<pre><code class="lang-auto">#Activation function in hidden layers
def acti1(coordinate, layer_no):#layer_no from 0 to '(the length of eta_n) - 1'
        x = coordinate[0] 
        y = coordinate[1]

        return torch.cat([x.reshape(1, -1), (y + delta_eta[layer_no] * x ** 3).reshape(1, -1)], dim = 0)
</code></pre>
<pre><code class="lang-auto">#Activation function on the output layer
def acti2(coordinate):
    y = coordinate[1]
    F = y
    return (torch.tanh(100 * (F - 0.1)) - torch.tanh(100 * (F + 0.1)) + 2) / 2
#The result is 0 when F is between -0.5 and 0.5 and for the other F, the result is 1
#This function is steep but continuous and differentiable
</code></pre>
<pre><code class="lang-auto">def forward(coordinate, w, layer_no):#layer_no from 0 to '(the length of eta_n) - 1'
    matrix = torch.Tensor([[1, delta_eta[layer_no]], [- delta_eta[layer_no], 1 - delta_eta[layer_no] * w]])

    return acti1(matrix.mm(coordinate), layer_no)
</code></pre>
<pre><code class="lang-auto">y = torch.Tensor([0, 0, 1, 1]) #I want y_pred(later mentioned) to be this value
</code></pre>
<pre><code class="lang-auto">the_no_of_iterations = 10
learning_rate = 0.01

a = torch.Tensor([[0.5528, 0.8563, 1.0779, 0.5932], [-0.1109, -0.0569, 0.0904, 0.1435]])

torch.manual_seed(1)
w = torch.randn(9, requires_grad = True) #What I want to train to produce y from a
print('w:', w)
print('w.requires_grad:', w.requires_grad)

optimizer = torch.optim.Adam([w], lr = learning_rate)

for i in range(the_no_of_iterations):
    #Forward propagation
    for j in range(9):
        a = acti1(forward(a, w[j], j), j)
    print('a:', a)
    
    y_pred =acti2(a)
    print('y_pred:', y_pred)
    
    #Loss calculation
    loss = (y - y_pred).abs().sum()
    print('loss:', loss.item())
    print('loss.grad_fn:', loss.grad_fn)
    
    #Autograd
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    print('w.grad:', w.grad)
</code></pre>
<p>w: tensor([ 0.6614,  0.2669,  0.0617,  0.6213, -0.4519, -0.1661, -1.5228,  0.3817, -1.0276], requires_grad=True)<br>
w.requires_grad: True<br>
a: tensor([[ 0.5961,  1.1220,  1.6414,  0.3710],<br>
[ 0.0363, -0.7368, -2.2987,  0.3278]])<br>
y_pred: tensor([2.9206e-06, 1.0000e+00, 1.0000e+00, 1.0000e+00])<br>
loss: 1.0000028610229492<br>
loss.grad_fn: None</p>

ptrblck: <p>If you create a new tensor, you will detach the inputs from the computation graph.<br>
The creation of your <code>matrix</code> tensor might be the issue here.<br>
Could you try to rewrite the creation using <code>torch.cat</code> instead?</p>
<p>Let me know, if that helps or if we need to dig a bit deeper.</p>

Song1: <p>Thank you.<br>
I fixed the function named forward like below.</p>
<pre><code class="lang-auto">def forward(coordinate, w, layer_no):#layer_no from 0 to '(the length of eta_n) - 1'
    row1 = torch.Tensor([[1, delta_eta[layer_no]]])
    row2_col1 = torch.Tensor([- delta_eta[layer_no]])
    row2_col2 = w
    row2 = torch.cat([row2_col1, row2_col2], dim = 0).reshape(1, -1)
    matrix = torch.cat([row1, row2], dim = 0)

    return acti1(matrix.mm(coordinate), layer_no)
    
</code></pre>
<p>Also, I fixed</p>
<pre><code class="lang-auto">w = torch.randn(9, requires_grad = True)
</code></pre>
<p>into</p>
<pre><code class="lang-auto">w = torch.randn((9, 1) requires_grad = True)
</code></pre>
<p>in accordance with the change in function named forward. And the error was solved.</p>
<p>However, another error which is ‘RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time’ appeared. I reconstructed all codes to avoid the error what I can’t find a solution and the result is the simplified codes above. However the error appeared again. Would you help me again? I have done many googlings, but I couldn’t understand. And specifying <code>retain_graph = True</code> resulted in exponentially increasing operation time.</p>