Adding an input to every node in a layer

pdu: <p>I’m interested in adding a new input to every node in a layer for a defined architecture. I made a quick graphic in a simple network. The nodes and solid lines are the existing architecture, and I want to add a new input (dashed lines) to each node in a layer. I only want my new input to map a single connection to the corresponding node in the layer.</p>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/2X/b/b3366f15062453a1a4d7c8fb3f20306244a9db81.jpeg" data-download-href="https://discuss.pytorch.org/uploads/default/b3366f15062453a1a4d7c8fb3f20306244a9db81" title="Untitled-1"><img src="https://discuss.pytorch.org/uploads/default/optimized/2X/b/b3366f15062453a1a4d7c8fb3f20306244a9db81_2_526x500.jpeg" alt="Untitled-1" data-base62-sha1="pzo5F5ynGrHMUalsdkI5zVeKq2d" width="526" height="500" srcset="https://discuss.pytorch.org/uploads/default/optimized/2X/b/b3366f15062453a1a4d7c8fb3f20306244a9db81_2_526x500.jpeg, https://discuss.pytorch.org/uploads/default/optimized/2X/b/b3366f15062453a1a4d7c8fb3f20306244a9db81_2_789x750.jpeg 1.5x, https://discuss.pytorch.org/uploads/default/optimized/2X/b/b3366f15062453a1a4d7c8fb3f20306244a9db81_2_1052x1000.jpeg 2x" data-dominant-color="E4E4E4"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">Untitled-1</span><span class="informations">2622×2491 181 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>
<p>Sorry if this has an easy solution! I’m still learning my way around PyTorch.<br>
Thanks!</p>

ptrblck: <p>Would you like to add these values to the output activations of another layer?<br>
If so, just add this tensor to the output of a specific layer in your <code>forward</code> method:</p>
<pre><code class="lang-python">def forward(self, x, additional_x):
    x = F.relu(self.fc1(x))
    x = x + additional_x
    x = F.relu(self.fc2(x))
    ...
    return x
</code></pre>
<p>Let me know, if I misunderstood your use case.</p>

pdu: <p>If I’m understanding you correctly, then if I wanted every node in a layer to have 4 inputs, I could just do something like:</p>
<pre><code class="lang-auto">def forward(self, x1, x2, x3, x4):
    x = x1 + x2 + x3 + x4
    x = F.relu(self.fc(x))
</code></pre>
<p>And each input (x1 … x4) would be given its own weight parameter?</p>

pdu: <p>Also, I’m interested in implementing the reverse of this operation; how can I add a layer of output nodes to an existing layer?</p>
<p>Sorry if this violates forum rules. I’m happy to start a new thread</p>

ptrblck: <p>I might have misunderstood your question.<br>
<code>x1</code>, <code>x2</code>, … would be the inputs to your model which are just summed.<br>
Would you like to pass these inputs separately to the same layer?</p>
<aside class="quote no-group" data-username="pdu" data-post="4" data-topic="46442">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/p/f17d59/48.png" class="avatar"> pdu:</div>
<blockquote>
<p>how can I add a layer of output nodes to an existing layer?</p>
</blockquote>
</aside>
<p><code>x = self.fc(x)</code> will store the output activations in <code>x</code>. You can pass it to a new layer just by calling <code>self.fc2(x)</code>. Could you explain the first image a bit, as I’m still unsure about your use case?</p>

pdu: <p>Yes, I do not want my inputs to be fully connected – they should be passed separately to each node.</p>
<p>Let’s say I want to build an autoencoder like this</p>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/2X/0/035bb2b3fb7d7e7c61fca709ac2f860c8851fab8.jpeg" data-download-href="https://discuss.pytorch.org/uploads/default/035bb2b3fb7d7e7c61fca709ac2f860c8851fab8" title="Untitled-2"><img src="https://discuss.pytorch.org/uploads/default/optimized/2X/0/035bb2b3fb7d7e7c61fca709ac2f860c8851fab8_2_689x389.jpeg" alt="Untitled-2" data-base62-sha1="tHTsPle414GuNgnNxJqWL3fTTO" width="689" height="389" srcset="https://discuss.pytorch.org/uploads/default/optimized/2X/0/035bb2b3fb7d7e7c61fca709ac2f860c8851fab8_2_689x389.jpeg, https://discuss.pytorch.org/uploads/default/optimized/2X/0/035bb2b3fb7d7e7c61fca709ac2f860c8851fab8_2_1033x583.jpeg 1.5x, https://discuss.pytorch.org/uploads/default/optimized/2X/0/035bb2b3fb7d7e7c61fca709ac2f860c8851fab8_2_1378x778.jpeg 2x" data-dominant-color="E3E3E3"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">Untitled-2</span><span class="informations">4677×2637 406 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>
<p>where I have three types of data that contribute to every node, but the inputs are specific to that node. How would I implement the input and output layers?</p>

pdu: <p>I tried writing an autoencoder that does what I’m looking for. Does it match up with the picture I posted? Also, is there any way to parallelize the for loops?</p>
<pre><code class="lang-auto">class Model(nn.Module):
    def __init__(self, layer_size):
        super(Model, self).__init__()
        self.layer_size = layer_size
        self.relu = nn.ReLU()

        self.contract = nn.Linear(3, 1)
        self.fc1 = nn.Linear(layer_size, 100)
        self.fc2 = nn.Linear(100, layer_size)
        self.expand = nn.Linear(1, 3)

    def forward(self, x):
        # x.shape (batch_size, layer_size, 3)
        outs = []
        for i in range(self.layer_size):
            outs.append(self.relu(self.contract(x[:, i, :])))
        x = torch.cat(outs, dim=1)

        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))

        outs = []
        for i in range(self.layer_size):
            outs.append(self.relu(self.expand(x[:, [i]])))
        x = torch.stack(outs, dim=1)

        return x
</code></pre>

ptrblck: <p>You don’t need to slice and concatenate <code>x</code>, as <code>nn.Linear</code> layers will take an input of <code>[batch_size, *, in_features]</code> and apply the linear layer on all additional dimensions specified as <code>*</code>.</p>
<p>However, I’m still unsure about your picture.<br>
The dots represent the activations, while the lines should represent the weight matrices (or the linear layers in general).<br>
What would the first and last lines represent?</p>

pdu: <p>Thanks for your patience. I think it will be easier to explain my use case if I give an example.</p>
<p>Let’s say I have manufacturing data from 100 factories. All of these factories have 50 machines. For each machine, I have 3 features (time in use, machine type, number of times serviced). I can formulate my input tensor with the shape (100 factories, 50 machines, 3 features). I want the first layer of my network to have 50 nodes, each corresponding to one of the 50 machines. Each node in the first layer will take the 3 input features associated with one machine. So, each of the 3 features will have its own weight, which contributes to the activation of the “machine” node. This network can now be trained on an output label corresponding to each factory or as an autoencoder.</p>
<p>Now let’s say I have a pretrained model with this architecture, but I have a 4th feature that I want to incorporate. How can I add a 4th input to my “machine” layer?</p>
<p>I hope this is clear! Please tell me if anything needs clarification.</p>