Loss function constant, weight.grad returns None

Jason_Hu1: <p>I am trying to train a neural network where I have a custom activation function. However, the loss function remains constant through all epochs. When I printed the weight.grad for the linear layer, it returns None, which means that somewhere, a gradient is not being computed. Here is my NN class code:</p>
<pre><code class="lang-python">class OptNet(nn.Module):
    def __init__(self):
        super(OptNet,self).__init__()

        m = 2
        self.fc1 = nn.Linear(m*m, 2*m*m, bias=False)
        with torch.no_grad():
          self.fc1.weight.data = torch.tensor([[1.1,0,0,0],[0,1.3,0,0],[0,0,1.2,0],[0,0,0,1.3],[-1,0,0,0],[0,-1,0,0],[0,0,-1,0],[0,0,0,-1]])

        self.myact = MyActivationFunction(m)

    def forward(self, x):
        m = 2
        x = self.fc1(x)
        return self.myact(x)
</code></pre>
<p>And here is my activation function code (it is meant to solve a quadratic program with one of the parameters being reshaped x):</p>
<pre><code class="lang-python">class MyActivationFunction(nn.Module):

    def __init__(self, m=2):
        super(MyActivationFunction, self).__init__()
        self.m = m

    def forward(self, x):
        Q = torch.tensor([[1.3, 0.3], [0.3, 1.7]], dtype=torch.float32)
        q = torch.tensor([1,-1], dtype=torch.float32)
        A = torch.reshape(x, (4,2))
        b = torch.ones(2*self.m, dtype=torch.float32)
        e = torch.tensor([], dtype=torch.float32)
        return QPFunction(verbose=-1)(Q, q, A, b, e, e)
</code></pre>
<p>And finally, here is the code used to actually train the network. The dataMatrix and solutions tensors are the training data set, which I have used for other purposes before so I am fairly confident these are generated correctly.</p>
<pre><code class="lang-python">net = OptNet()
optimizer = optim.SGD(net.parameters(), lr=0.5)
loss_func = nn.MSELoss()  

maxepochs = 100
lossarray = numpy.zeros(maxepochs)
for epoch in range(maxepochs):
  optimizer.zero_grad()   
  predictions = torch.zeros(trainPoints,m)
  for eachpoint in range(trainPoints):
    predictions[eachpoint] = net(Variable(dataMatrix[eachpoint]))
 
  loss = Variable(loss_func(predictions, solutions), requires_grad=True)
  
  loss.backward()   
  print(net.fc1.weight.grad) #this prints None
  optimizer.step() 
  lossarray[epoch] = loss
  if epoch%5 == 1:
    print(loss) #this is always constant
</code></pre>
<p>I figure it must be something to do with the ActivationFunction which uses QPFunction from the qpth library, but this library has differentiation implemented. Any help would be greatly appreciated, thanks!</p>

KFrank: <p>Hi Jason!</p>
<p>I haven’t read your code, nor can I speak about <code>QPFunction</code>.<br>
However:</p>
<aside class="quote no-group" data-username="Jason_Hu1" data-post="1" data-topic="123890" data-full="true">
<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/jason_hu1/48/29813_2.png" class="avatar"> Jason_Hu1:</div>
<blockquote>
<pre data-code-wrap="python"><code class="lang-python">  loss = Variable(loss_func(predictions, solutions), requires_grad=True)
</code></pre>
</blockquote>
</aside>
<p>Here you create a new <code>Variable</code> that is no longer connected to<br>
the computation graph.  (Note that <code>Variable</code> is deprecated, and<br>
in current versions of pytorch is just a <code>Tensor</code>).  Creating it with<br>
<code>requires_grad = True</code> doesn’t fix this problem.</p>
<p>Consider:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; torch.__version__
'1.7.1'
&gt;&gt;&gt; loss_func = torch.nn.MSELoss()
&gt;&gt;&gt; pred = torch.randn (3, requires_grad = True)
&gt;&gt;&gt; targ = torch.randn (3)
&gt;&gt;&gt; loss1 = torch.autograd.Variable (loss_func (pred, targ), requires_grad = True)
&gt;&gt;&gt; loss1.backward()
&gt;&gt;&gt; pred.grad
&gt;&gt;&gt; loss2 = loss_func (pred, targ)
&gt;&gt;&gt; loss2.backward()
&gt;&gt;&gt; pred.grad
tensor([-0.4108,  0.5605, -0.4539])
</code></pre>
<p>Best.</p>
<p>K. Frank</p>

Jason_Hu1: <p>Worked like a charm. Thanks a lot!</p>