Question about how to make the partial tensor trainable?

username: Antonio_Lopez
cooked: <p>Hi,</p>
<p>I recently encountered a problem. I have a learnable matrix</p>
<pre><code class="lang-auto">self.learnable_A = nn.Parameter(torch.empty(n, n))
</code></pre>
<p>and an unlearnable matrix (just a tensor):</p>
<pre><code class="lang-auto">self.unlearnable_B = torch.randn(m, m)
</code></pre>
<p>where m &gt;&gt; n holds. Moreover, we also have an index vector v (list, with the size n)</p>
<pre><code class="lang-auto">v = [2, 5, 11, 1, ..., 19]
</code></pre>
<p>where each element v_i in the list v satisfies 0&lt;=v_i&lt;=m.</p>
<p><strong>Target</strong>: We want to insert the self.learnable_A into the self.unlearnable_B according to the v (cols=v and row=v), and keeps the element from the self.learnable_A trainable (.requires_grad=True) while the element from the self.learnable_B untrainable (.requires_grad=False).</p>
<p>I have tried many ways to do this but can’t. Is this possible?</p>

username: KFrank
cooked: <p>Hi Antonio!</p>
<aside class="quote no-group" data-username="Antonio_Lopez" data-post="1" data-topic="209925" 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/antonio_lopez/48/72768_2.png" class="avatar"> Antonio_Lopez:</div>
<blockquote>
<p>We want to insert the self.learnable_A into the self.unlearnable_B according to the v (cols=v and row=v)</p>
</blockquote>
</aside>
<p>You may use pytorch tensor indexing to write <code>A</code> into the<br>
desired locations of <code>B</code>.  (I don’t understand specifically what<br>
you mean by “cols=v and row=v”.)</p>
<aside class="quote no-group">
<blockquote>
<p>and keeps the element from the self.learnable_A trainable</p>
</blockquote>
</aside>
<p>After you write <code>A</code> into <code>B</code> the “non-leaf” tensor <code>B</code> will carry<br>
<code>requires_grad = True</code> and depend on the trainable leaf<br>
tensor <code>A</code>.  So you will be able to backpropagate through <code>B</code><br>
to <code>A</code> and train <code>A</code> using those backpropagated gradients.</p>
<aside class="quote no-group">
<blockquote>
<p>while the element from the self.learnable_B untrainable (.requires_grad=False).</p>
</blockquote>
</aside>
<p>Even though <code>B</code> carries <code>requires_grad = True</code> (after being<br>
written into), it is not a leaf tensor, so it isn’t “trainable.”</p>
<p>(Note that things like <code>requires_grad</code> and being a leaf tensor<br>
apply to entire tensors as a whole and not to individual<br>
elements of tensors.  But the non-leaf tensor <code>B</code> is computed<br>
from the leaf tensor <code>A</code> and all of <code>A</code> is “trainable” and carries<br>
<code>requires_grad = True</code>, which is what you want.)</p>
<p>Consider:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; print (torch.__version__)
2.4.1
&gt;&gt;&gt;
&gt;&gt;&gt; n = 5
&gt;&gt;&gt; m = 11
&gt;&gt;&gt;
&gt;&gt;&gt; A = (torch.arange (n * n).float() + 1).reshape (n, n)
&gt;&gt;&gt; A.requires_grad = True
&gt;&gt;&gt; A
tensor([[ 1.,  2.,  3.,  4.,  5.],
        [ 6.,  7.,  8.,  9., 10.],
        [11., 12., 13., 14., 15.],
        [16., 17., 18., 19., 20.],
        [21., 22., 23., 24., 25.]], requires_grad=True)
&gt;&gt;&gt;
&gt;&gt;&gt; B = torch.zeros (m, m)
&gt;&gt;&gt; B
tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
&gt;&gt;&gt;
&gt;&gt;&gt; v = torch.tensor ([1, 3, 5, 7, 9])
&gt;&gt;&gt; ind = v.repeat (n, 1)
&gt;&gt;&gt; ind
tensor([[1, 3, 5, 7, 9],
        [1, 3, 5, 7, 9],
        [1, 3, 5, 7, 9],
        [1, 3, 5, 7, 9],
        [1, 3, 5, 7, 9]])
&gt;&gt;&gt;
&gt;&gt;&gt; B[ind.T, ind] = A
&gt;&gt;&gt; B
tensor([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  1.,  0.,  2.,  0.,  3.,  0.,  4.,  0.,  5.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  6.,  0.,  7.,  0.,  8.,  0.,  9.,  0., 10.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0., 11.,  0., 12.,  0., 13.,  0., 14.,  0., 15.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0., 16.,  0., 17.,  0., 18.,  0., 19.,  0., 20.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0., 21.,  0., 22.,  0., 23.,  0., 24.,  0., 25.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]],
       grad_fn=&lt;IndexPutBackward0&gt;)
</code></pre>
<p>Best.</p>
<p>K. Frank</p>

username: Antonio_Lopez
cooked: <p>Thank you very much! As you said, non-leaf nodes are not trainable, my problem is solved. Thanks again!</p>