Change input of a layer during an end-to-end training

username: Pymal
cooked: <p>I’m new to pytorch and I would like to design the following model:</p>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/7/a/7ad034a37dee8df80f12a665d7332bdc1f19ac75.jpeg" alt="Untitled drawing" data-base62-sha1="hwsks35nf9dPLvC5JhTpN8jyj5j" width="673" height="248"></p>
<p>“Generate Graph” building block is not part of the network and it just generates a graph using features <code>f</code> every batch. I also want the loss function to be end-to-end.</p>
<p>In fact I know how to design a network with two separate parts (<code>Encoder</code> and <code>GCN</code>) but I cannot connect them together with one loss function with the <code>graph_generator()</code> in between!</p>

username: ptrblck
cooked: <p>Could you explain a bit, what the “Generate Graph” block does, i.e. what operations are you using?</p>

username: Pymal
cooked: <p>Thanks for your reply. Sure I try elaborate more.</p>
<p>Generally, I would like to know how I could change the input of the GCN layer during training. I have a <code>GCN(nn.Module)</code> class that inputs a feature matrix, <code>X</code>, and an adjacency matrix, <code>A</code>, and I want to either modify <code>X</code> or <code>A</code> in every batch.</p>
<p>And to explain what “Generate Graph” block does: it uses the features generated by the CNN block to generate graph(s) using <em>k-nearest neighbor</em> approach.</p>
<p>I hope this explains it better.</p>

username: ptrblck
cooked: <p>You could set the <code>requires_grad</code> attribute of both input to <code>True</code> and pass these parameter to the optimizer.<br>
The first step will make sure, that both inputs get gradients, while the latter would of course optimize them using the current loss.</p>
<p>Did you create the “Generate Graph” block in PyTorch?<br>
If that’s the case and also if you didn’t detach the computation graph, you could train the model end2end.<br>
However, if you’ve used non-differentiable methods inside “Generate Graph” or if you’ve used another library such as numpy, you would have to implement the backward method manually.</p>

username: Pymal
cooked: <p>I appreciate your time and reply.</p>
<p>That’s exactly my problem. I didn’t create “generate graph” in pytorch, in fact I use an external library for that. So I believe it causes the computational graph to detach as you mentioned.</p>
<p>I think I don’t want the “generate graph” block to be included in the training process (there is nothing to be learned), is that possible?</p>

username: ptrblck
cooked: <p>Yes, that would be possible.<br>
However, would you want to train CNN and <code>f</code>?<br>
If so, that wouldn’t be possible, since the computation graph will be detached by “Generate Graph”.</p>

username: Pymal
cooked: <p>Yes I want to train CNN. Based on what you suggest I think my option is that I only update the feature matrix in the GCN network and keep the adjacency matrix <code>A</code> fixed.</p>
<pre><code class="lang-auto">f = CNN(input)
output = GCN(f, A)
</code></pre>
<p>where <code>A</code> is fixed and generated using a pre-processing module. Something like this:<br>
<img src="https://discuss.pytorch.org/uploads/default/original/3X/4/8/489c0a259327b9af491b66cee3a6c118b01d5e9a.jpeg" alt="Untitled drawing" data-base62-sha1="amkGRaiD7vlDsoY5h3eIRgJebMK" width="528" height="246"><br>
Is this feasible?</p>

username: ptrblck
cooked: <p>That would be possible, if e.g. you are multiplying <code>f</code> with <code>A</code> or use any other differentiable operation.</p>

username: pnnaman
cooked: <p>Hey <a class="mention" href="/u/ptrblck">@ptrblck</a><br>
If you don’t mind, I have a follow-up. I am trying to create a GCN model (using <code>dgl</code> with <code>PyTorch</code> backend). Layer 1 (a <a href="https://docs.dgl.ai/en/1.1.x/generated/dgl.nn.pytorch.conv.GraphConv.html" rel="noopener nofollow ugc">GraphConv</a> layer) takes as inputs an <code>n x d1</code> and outputs <code>m x d2</code>. The output of the first layer is then fed to the second layer.</p>
<pre><code class="lang-auto">x1 = layer1(f) # f is the original input to layer 1
x2 = layer2(x1)  # output of layer 1 is given as input to the layer 2.
</code></pre>
<p>I want to make changes to <code>x1</code> (for instance, update a few rows) before feeding it to the second layer. The current solution I have implemented is as follows -</p>
<pre><code class="lang-auto">x1 = layer1(f) # f is the original input to layer 1
y = torch.clone(x1) # since in place update isn't allowed
...                 # make changes to y
x1 = y          # assign y back to x1
x2 = layer2(x1)  # output of layer 1 is given as input to the layer 2.
</code></pre>
<p>Is this a valid way to do this? Would the backward pass work as expected in this case?</p>

username: ptrblck
cooked: <p>It depends on the manipulation of <code>y</code> and how it was performed.</p>

username: pnnaman
cooked: <p>I update some tensors in <code>y</code></p>
<pre><code class="lang-auto">y[indices_to_update] = tensor of appropriate dimensions
</code></pre>