Optimizer.step not working though grads exist after requires_grad_ switch

pytorcher: <p>I have a network that trains for a bit. Then I call requires_grad_(False) to some layers then later call requires_grad_() to those layers and requires_grad_(False) to the other layers.  At this point training completely stops.  Looking at <a href="https://discuss.pytorch.org/t/gradients-exist-but-weights-not-updating/20484" class="inline-onebox">Gradients exist but weights not updating</a> I have the code:</p>
<pre><code class="lang-auto">if(epoch == test):
    before = list(cnn.parameters())
    for i in range(len(before)):
        before[i] = before[i].clone()
loss.backward()
optimizer.step()
if(epoch == test):
    after = list(cnn.parameters())
    for i in range(len(before)):
        print(torch.equal(before[i].data, after[i].data))
        if(type(after[i].grad) != type(None)):
            print(after[i].grad.data[:].max())
</code></pre>
<p>On epoch 0 before the requires grad it works.</p>
<blockquote>
<p>False<br>
tensor(7.1678e-08, device=‘cuda:0’, dtype=torch.float64)<br>
False<br>
tensor(3.6259e-06, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
True<br>
False<br>
tensor(1.1820e-05, device=‘cuda:0’, dtype=torch.float64)<br>
False<br>
tensor(2.0888e-05, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
True<br>
False<br>
tensor(8.6558e-05, device=‘cuda:0’, dtype=torch.float64)<br>
False<br>
tensor(0.0002, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
True<br>
False<br>
tensor(0.0020, device=‘cuda:0’, dtype=torch.float64)<br>
False<br>
tensor(0.0041, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
True</p>
</blockquote>
<p>But then on epoch 2 after the requires grad happens the grad is still calculated but the weights dont get updated</p>
<blockquote>
<p>True<br>
tensor(-6.2089e-07, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
tensor(1.1862e-06, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
tensor(-1.1782e-06, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
True<br>
True<br>
tensor(2.5829e-06, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
tensor(4.0316e-06, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
tensor(5.7105e-06, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
True<br>
True<br>
tensor(3.4637e-05, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
tensor(5.0992e-05, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
tensor(8.0335e-05, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
True<br>
True<br>
tensor(0.0016, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
tensor(0.0009, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
tensor(0.0019, device=‘cuda:0’, dtype=torch.float64)<br>
True<br>
True</p>
</blockquote>

albanD: <p>Are you changing the learning rate as well when you change these properties?<br>
Or anything else with the optimizers?</p>

pytorcher: <p>Nope, everything else is the same</p>

albanD: <p>Could you give a small code sample that we can run that reproduces this please?</p>

pytorcher: <p>Looks like the problem actually was the optimizers.  One other thing I was doing is reloading the model.  I think with an old verion of pytorch the optimizers would automatically point to the reloaded layers, but now it appears to have to be reinitialized.  Looks like that fixed it!</p>

Yitao_Chen: <p>Hi,</p>
<p>Do you mind sharing your solution?<br>
I run into a very similar problem as yours.<br>
Thank you!</p>

pytorcher: <p>Sorry if that explanation wasn’t clear.  I’m not home but this is the psudo code of what was happening.</p>
<pre><code class="lang-auto">model = initializeFunction()
optimizer = optimizer(model.params)

do stuff for some epochs

model = loadBestModel()
doMore stuff.
</code></pre>
<p>After loadBestModel() I needed to reinitialize the optimizer.  Basically make sure that your optimizer is actually pointing to the parameters that have gradients.</p>

Yitao_Chen: <p>Thanks for your response.<br>
What do you mean by reinitialize the optimizer?<br>
Is it just to run the line below again?<br>
optimizer = optimizer(model.params)</p>

Yitao_Chen: <p>In my case, I am trying to train one model with two different dataset.<br>
But the model failed to recognize the test data from the second dataset at all.<br>
My flow is as following:</p>
<blockquote>
<p>model = initializeFunction()</p>
<p>optimizer = optimizer(model.params)<br>
train for some epochs using the dataset1 with optimizer<br>
test with dataset1</p>
<p>optimizer_1 = optimizer(model.params)<br>
train for some epochs using the dataset1 with optimizer_1<br>
test with dataset2</p>
</blockquote>

pytorcher: <p>Yes, I do mean to just rerun optimizer=optimizer(model.params).  Make sure that if you have otimizer, and optimizer_1 its correct. and if any of these are being called in separate functions make sure that you are returning the new optmizer/model that you want to use from those functions.  I’m guessing the core of your problem is the same as mine, that when you call optimizer.step that optimizer is not actually pointing to your tensors that have the gradients.  but could be a number of ways that has happened.</p>

Yitao_Chen: <p>Thanks for your help!<br>
Following your suggestion, I found the problem.<br>
During the second training, the model weights are not changing at all.<br>
I need to explicitly add another model.train() step to fix this issue.</p>