在Pytorch中创建自定义连接/非链接的层

发布于 2025-02-09 19:16:27 字数 449 浏览 1 评论 0 原文

,如图所示,它是一个带有NN的3层,即输入层,隐藏层和输出层。我想设计NN(在Pytorch,Just Arch),其中隐藏层的输入完全连接。但是,从隐藏层到输出,隐藏层的前两个神经元应连接到输出层的第一个神经元,第二两个应连接到输出层中的第二个神经元,依此类推。应该如何设计?

from torch import nn
layer1 = nn.Linear(input_size, hidden_size)
layer2 = ??????

A NN with first layer is fully connected and second is custom connection

As shown in the figure, it is a 3 layer with NN, namely input layer, hidden layer and output layer. I want to design the NN(in PyTorch, just the arch) where the input to hidden layer is fully-connected. However, from hidden layer to output, the first two neurons of the hidden layer should be connected to first neuron of the output layer, second two should be connected to the second in the output layer and so on. How shall this should be designed ?

from torch import nn
layer1 = nn.Linear(input_size, hidden_size)
layer2 = ??????

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

忱杏 2025-02-16 19:16:27

AS @jan /a>,您可以超载 > 并提供一个点的面膜,以掩盖您要避免的相互作用。请记住,完全连接的层仅是具有可选添加偏置的矩阵乘法。

查看其 source code 我们可以做:

class MaskedLinear(nn.Linear):
    def __init__(self, *args, mask, **kwargs):
        super().__init__(*args, **kwargs)
        self.mask = mask

    def forward(self, input):
        return F.linear(input, self.weight, self.bias)*self.mask

具有 f 定义为 torch。 nn.功能

考虑您对第二层的约束:

隐藏层的前两个神经元应连接到输出层的第一个神经元

似乎您正在寻找这种模式:

tensor([[1., 0., 0.],
        [1., 0., 0.],
        [0., 1., 0.],
        [0., 1., 0.],
        [0., 0., 1.],
        [0., 0., 1.]])

可以使用 torch.block_diag

mask = torch.block_diag(*[torch.ones(2,1),]*output_size)

可以将网络定义为:

net = nn.Sequential(nn.Linear(input_size, hidden_size),
                    MaskedLinear(hidden_size, output_size, mask))

有了这个,您 它在自定义层中:

class LocalLinear(nn.Linear):
    def __init__(self, *args, kernel_size=2, **kwargs):
        super().__init__(*args, **kwargs)

        assert self.in_features == kernel_size*self.out_features
        self.mask = torch.block_diag(*[torch.ones(kernel_size,1),]*self.out_features)

def forward(self, input):
    return F.linear(input, self.weight, self.bias)*self.mask

然后像这样定义:

net = nn.Sequential(nn.Linear(input_size, hidden_size),
                    LocalLinear(hidden_size, output_size))

As @Jan said here, you can overload nn.Linear and provide a point-wise mask to mask the interaction you want to avoid having. Remember that a fully connected layer is merely a matrix multiplication with an optional additive bias.

Looking at its source code, we can do:

class MaskedLinear(nn.Linear):
    def __init__(self, *args, mask, **kwargs):
        super().__init__(*args, **kwargs)
        self.mask = mask

    def forward(self, input):
        return F.linear(input, self.weight, self.bias)*self.mask

Having F defined as torch.nn.functional

Considering the constraint you have given to the second layer:

the first two neurons of the hidden layer should be connected to the first neuron of the output layer

It seems you are looking for this pattern:

tensor([[1., 0., 0.],
        [1., 0., 0.],
        [0., 1., 0.],
        [0., 1., 0.],
        [0., 0., 1.],
        [0., 0., 1.]])

Which can be obtained using torch.block_diag:

mask = torch.block_diag(*[torch.ones(2,1),]*output_size)

Having this, you can define your network as:

net = nn.Sequential(nn.Linear(input_size, hidden_size),
                    MaskedLinear(hidden_size, output_size, mask))

If you feel like it, you can even implement it inside the custom layer:

class LocalLinear(nn.Linear):
    def __init__(self, *args, kernel_size=2, **kwargs):
        super().__init__(*args, **kwargs)

        assert self.in_features == kernel_size*self.out_features
        self.mask = torch.block_diag(*[torch.ones(kernel_size,1),]*self.out_features)

def forward(self, input):
    return F.linear(input, self.weight, self.bias)*self.mask

And defining it like so:

net = nn.Sequential(nn.Linear(input_size, hidden_size),
                    LocalLinear(hidden_size, output_size))
十二 2025-02-16 19:16:27

而不是直接使用 nn.lin.linear ,而是创建权重张量 wigith 和一个掩码 mask 掩盖了您不打算使用的权重。然后,您使用 torch.nn.functional.linear(输入,重量 * mask) https://pytorch.org/docs/stable/generated/generated/torch.nn.functional.linear.linear.html )向第二层转发。请注意,这是在您的 torch.nn.module 's forward 函数中实现的。重量需要注册为 nn.module 的参数,以便通过 nn.module.parameters()识别。请参阅

Instead of using nn.Linear directly, create a weights tensor weight and a mask tensor mask that masks those weights that you do not intend to use. Then you use torch.nn.functional.linear(input, weight * mask) (https://pytorch.org/docs/stable/generated/torch.nn.functional.linear.html) to forward the second layer. Note that this is implemented in your torch.nn.Module's forward function. The weight needs to be registered as a parameter to your nn.Module so that it's recognized by nn.Module.parameters(). See https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.register_parameter.

不寐倦长更 2025-02-16 19:16:27

伊万的一般方法(掩盖了完全连接的层)可能会像我的评论一样进行修改,但它增加了很多无用的计算!

最好在此处写一个自定义图层,并具有形状的权重矩阵(2,hidden_​​size // 2)。然后重新设计从(hidden_​​size)(sideen_size // 2,2) 的输入从隐藏层的输出到层的输入。

这样的东西(未经测试):

class MyLayer(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.weight = torch.zeros(2, in_channels // 2)
        self.bias = torch.zeros(in_channels // 2)

    def forward(self, inp):
        return torch.matmul(inp.reshape(-1, inp.shape[-1]//2, 2), self.weight) + self.bias

Ivan's general approach (masking the fully connected layer) may work with modifications as in my comment, but it adds a lot of useless computation!

It's probably best to write a custom layer here, with a weight matrix of shape (2, hidden_size//2). Then reshape the input to the layer from output of the hidden layer from (hidden_size) to (hidden_size//2, 2) and do the matrix multiply.

Something like this (untested):

class MyLayer(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.weight = torch.zeros(2, in_channels // 2)
        self.bias = torch.zeros(in_channels // 2)

    def forward(self, inp):
        return torch.matmul(inp.reshape(-1, inp.shape[-1]//2, 2), self.weight) + self.bias
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文