Gradient Exist but Weights not updated

username: RealNewNoob
cooked: <p>I am trying to cluster some images using the code from<br>
<aside class="onebox whitelistedgeneric">
  <header class="source">
      <img src="https://github.githubassets.com/favicon.ico" class="site-icon" width="32" height="32">
      <a href="https://github.com/michaal94/torch_DCEC" target="_blank" rel="nofollow noopener">GitHub</a>
  </header>
  <article class="onebox-body">
    <img src="https://avatars0.githubusercontent.com/u/25354680?s=400&amp;v=4" class="thumbnail onebox-avatar" width="420" height="420">

<h3><a href="https://github.com/michaal94/torch_DCEC" target="_blank" rel="nofollow noopener">michaal94/torch_DCEC</a></h3>

<p>Pytorch Deep Clustering with Convolutional Autoencoders implementation - michaal94/torch_DCEC</p>


  </article>
  <div class="onebox-metadata">
    
    
  </div>
  <div style="clear: both"></div>
</aside>
<br>
in which the clustering layer weights is defined as follows:</p>
<pre><code class="lang-auto">class ClusterlingLayer(nn.Module):
    def __init__(self, in_features=10, out_features=10, alpha=1.0):
        super(ClusterlingLayer, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.alpha = alpha
        self.weight = nn.Parameter(torch.Tensor(self.out_features, self.in_features), requires_grad = True)
        self.weight = nn.init.xavier_uniform_(self.weight)

    def forward(self, x):
        x = x.unsqueeze(1)
        x = x - self.weight
        x = torch.mul(x, x)
        x = torch.sum(x, dim=2)
        x = 1.0 + (x / self.alpha)
        x = 1.0 / x
        x = x ** ((self.alpha +1.0) / 2.0)
        x = torch.t(x) / torch.sum(x, dim=1)
        x = torch.t(x)
        return x

    def extra_repr(self):
        return 'in_features={}, out_features={}, alpha={}'.format(
            self.in_features, self.out_features, self.alpha
        )

    def set_weight(self, tensor):
        self.weight = nn.Parameter(tensor, requires_grad = True)
    
    def return_weight(self):
        return self.weight
</code></pre>
<p>And I added the following code in the training process to check the data and gradient of the clustering weights.</p>
<pre><code class="lang-auto">for name, param in model.named_parameters():
    if 'clustering' in name:
        print('clustering weight data and grad:')
        print(param.data)
        print(param.grad)
</code></pre>
<p>On my custom dataset, the data and grad are as follows:<br>
epoch 343<br>
clustering weight data and grad:<br>
tensor([[ 38.1564,  50.6772,  15.0029,  27.4586],<br>
[ -1.5073,  44.5947, -11.2756, -53.1255],<br>
[  4.1370,  42.0674, -44.5653, -15.3601],<br>
[ -6.0383,  48.9728, -25.7221,  30.2076]], device=‘cuda:0’)<br>
tensor([[-0.0278, -0.0074, -0.0885,  0.1166],<br>
[-0.0663, -0.0325, -0.1827, -0.0491],<br>
[ 0.0852,  0.0231,  0.1948, -0.1382],<br>
[ 0.0097,  0.0350,  0.0888,  0.0871]], device=‘cuda:0’)</p>
<p>epoch 344<br>
clustering weight data and grad:<br>
tensor([[ 38.1564,  50.6772,  15.0029,  27.4586],<br>
[ -1.5073,  44.5947, -11.2756, -53.1255],<br>
[  4.1370,  42.0674, -44.5653, -15.3601],<br>
[ -6.0383,  48.9728, -25.7221,  30.2076]], device=‘cuda:0’)<br>
tensor([[-0.0279, -0.0073, -0.0888,  0.1171],<br>
[-0.0667, -0.0326, -0.1836, -0.0493],<br>
[ 0.0854,  0.0234,  0.1954, -0.1385],<br>
[ 0.0097,  0.0351,  0.0894,  0.0875]], device=‘cuda:0’)</p>
<p>The weights of the clustering layer are not updated at all in the training process, but the grad exists and not small.<br>
Meanwhile, I also checked the weights of other layers, they all get updated normally in each training.<br>
Does anyone have any ideas about what is going on?</p>

username: albanD
cooked: <p>Hi,</p>
<p>Given how you set the weights, what most likely happens is that you set the weights after passing them to the optimizer?<br>
In that case, the weights that the optimizer get are not in the model anymore and so that won’t work.</p>
<p>If you just want to change the values of the weight, you can implement it as:</p>
<pre><code class="lang-python">    def set_weight(self, tensor):
        with torch.no_grad():
            self.weight.copy_(tensor)
</code></pre>
<p>This way, the parameter given to the optimizer won’t change.</p>

username: RealNewNoob
cooked: <p>I tried your method and it works! Thank you and I really appreciate it.</p>

username: RealNewNoob
cooked: <p>Sorry for the interruption, I recently retry running the code and notice the clustering weights are no trained, and the gradients are zero. My original aim is to used set_weight to initialize the parameters of the clustering layer, and then train it with gradient.<br>
Not sure it worked previously, or maybe I was just too careless.</p>

username: RealNewNoob
cooked: <p>I figured out why, thank you.</p>

username: JiriJurik
cooked: <p>Hi <a class="mention" href="/u/realnewnoob">@RealNewNoob</a> ,</p>
<p>I am currently facing the same issue. Can you please tell me how have you solved it?</p>
<p>Regards,<br>
Jiří</p>

username: RealNewNoob
cooked: <p>I just took the advice by albanD.</p>