torch.nn.Conv1d(kernel_size=1, stride=1)与nn.Linear()对比

nn.Conv1d()

或许对你有帮助的网址(conv1d与conv2d的区别,为确保阅读没有问题,建议科学上网)


下面举个简单的计算例子分析nn.Conv1d() (kerner_size=1, stride=1) 是如何进行计算的,以及他与nn.Linear()的区别


>>> a  #这里定义一个输入矩阵:3 token, each token‘s dimension is 6(6个feature)
tensor([[[ 0.7000,  0.2000, -0.5000,  0.6000,  0.3000, -0.5000],
         [ 0.4000, -0.1000,  0.4000,  0.3000, -0.1000,  0.4000],
         [ 0.5000,  0.1000,  0.1000,  0.5000,  0.2000,  0.1000]]])
>>> a.shape
torch.Size([1, 3, 6])

>>> conv1 = nn.Conv1d(6, 8, kernel_size=1, bias=False)
>>> conv1.weight.shape
torch.Size([8, 6, 1])

>>> conv1.weight
Parameter containing:
tensor([[[ 0.2758],
         [-0.0141],
         [ 0.1317],
         [ 0.0359],
         [-0.3211],
         [-0.0772]],

        [[ 0.2688],
         [ 0.3090],
         [ 0.3472],
         [-0.2065],
         [ 0.3341],
         [ 0.3242]],

        [[-0.3243],
         [-0.0492],
         [ 0.0593],
         [-0.2374],
         [-0.1905],
         [ 0.2047]],

        [[-0.3278],
         [ 0.3429],
         [-0.2414],
         [-0.0237],
         [ 0.2726],
         [ 0.3205]],

        [[-0.0105],
         [ 0.2715],
         [-0.3571],
         [-0.2210],
         [-0.3023],
         [-0.1792]],

        [[-0.3150],
         [ 0.3326],
         [-0.3559],
         [-0.1205],
         [ 0.2597],
         [ 0.3533]],

        [[ 0.3359],
         [-0.2941],
         [-0.3177],
         [-0.3294],
         [ 0.2743],
         [ 0.0651]],

        [[-0.2750],
         [-0.2631],
         [-0.2080],
         [ 0.1378],
         [ 0.3089],
         [-0.2562]]], requires_grad=True)

>>> conv1(a.transpose(1, 2)).transpose(1, 2)   #attention, the difference between conv1d and linear   [1, 3, 6] --> [1, 3, 8]
tensor([[[ 0.0882, -0.1094, -0.5685, -0.1329,  0.0917, -0.1470,  0.1873,
           0.1623],
         [ 0.1764,  0.2498, -0.0714, -0.1681, -0.2819, -0.2224, -0.0635,
          -0.2589],
         [ 0.0957,  0.1960, -0.2975, -0.0790, -0.2027, -0.1328,  0.0035,
          -0.0796]]], grad_fn=<TransposeBackward0>)
>>> conv1(a.transpose(1, 2)).transpose(1, 2).shape
torch.Size([1, 3, 8])

下面以求输出矩阵中的第一个元素为例子, 具体说明如何进行运算:

​ >>这是a的第一行数据

0.70000.2000-0.50000.60000.3000-0.5000

​ >>这是a与conv1.weight做乘法时对应的conv1.weight的数据

0.2758
-0.0141
0.1317
0.0359
-0.3211
-0.0772

这两部分相乘后求和可以求出第一个元素为0.0882(bias=0),如下

>>> 0.7 * 0.2758 + 0.2 * (-0.0141) + (-0.5) * 0.1317 + 0.6 * 0.0359 + 0.3 * (-0.3211) + (-0.5) * (-0.0772)

0.08819999999999997



下面对比一下conv1d与linear的区别,先说结论,当kernel_size = 1, stride = 1时, conv1d的效果与linear的效果可以相同(但需要注意进行transpose), 对比linear与conv1d的输出,发现相同的权重与输入对应的输出是相同的, 也就是在transformer中的feed forward模块中二者是可以相互替代的

>>> fc = nn.Linear(6, 8, bias=False)   #initialize a linear layer
#then, we assign the conv1.weight.data above to fc.weight.data
>>> fc.weight.data = conv1.weight[:, :, 0]
>>> fc.weight.data
tensor([[ 0.2758, -0.0141,  0.1317,  0.0359, -0.3211, -0.0772],
        [ 0.2688,  0.3090,  0.3472, -0.2065,  0.3341,  0.3242],
        [-0.3243, -0.0492,  0.0593, -0.2374, -0.1905,  0.2047],
        [-0.3278,  0.3429, -0.2414, -0.0237,  0.2726,  0.3205],
        [-0.0105,  0.2715, -0.3571, -0.2210, -0.3023, -0.1792],
        [-0.3150,  0.3326, -0.3559, -0.1205,  0.2597,  0.3533],
        [ 0.3359, -0.2941, -0.3177, -0.3294,  0.2743,  0.0651],
        [-0.2750, -0.2631, -0.2080,  0.1378,  0.3089, -0.2562]])
>>> fc.weight.data.shape
torch.Size([8, 6])
>>> fc(a)    #aW^T    [1, 3, 6] --> [1, 3, 8]
tensor([[[ 0.0882, -0.1094, -0.5685, -0.1329,  0.0917, -0.1470,  0.1873,
           0.1623],
         [ 0.1764,  0.2498, -0.0714, -0.1681, -0.2819, -0.2224, -0.0635,
          -0.2589],
         [ 0.0957,  0.1960, -0.2975, -0.0790, -0.2027, -0.1328,  0.0035,
          -0.0796]]], grad_fn=<UnsafeViewBackward>)
>>> fc(a).shape
torch.Size([1, 3, 8])


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这段代码定义了一个名为 VGG19Encoder 的神经网络模型。它使用了预训练的 VGG19 模型的前四个卷积层和最后一个全连接层作为特征提取器,其中前四个卷积层被分别用于提取不同层级的特征。然后,通过几个额外的卷积层和全连接层将提取的特征转换为对输入图像中物体类别的预测。其中,提取的特征被分别送入四个全连接层中进行分类。 具体来说,代码中的各个部分的功能如下: - `features_list = list(vgg19.features.children())`:获取 VGG19 模型的所有卷积层。 - `self.conv2_2 = torch.nn.Sequential(*features_list[:13])`:将前 13 层卷积层作为 conv2_2 层。 - `self.conv3_4 = torch.nn.Sequential(*features_list[13:26])`:将第 14 层到第 26 层卷积层作为 conv3_4 层。 - `self.conv4_4 = torch.nn.Sequential(*features_list[26: 39])`:将第 27 层到第 39 层卷积层作为 conv4_4 层。 - `self.conv5_4 = torch.nn.Sequential(*features_list[39:-1])`:将第 40 层到倒数第二层卷积层作为 conv5_4 层。 - `self.tail_layer = features_list[-1]`:将最后一层卷积层作为尾部层。 - `self.fc_layers = list(vgg19.classifier.children())[:-2]`:获取 VGG19 模型的所有全连接层,但不包括最后两层。 - `self.fc_layers = torch.nn.Sequential(*list(self.fc_layers))`:将所有全连接层组成一个新的连续的全连接层。 - `self.extract_0 = torch.nn.Sequential(torch.nn.MaxPool2d(kernel_size=8, stride=8), torch.nn.Conv2d(128, self.k, kernel_size=1, stride=1))`:将 conv2_2 层的输出进行最大池化和卷积操作,以提取更高级别的特征。 - `self.extract_1 = torch.nn.Sequential(torch.nn.MaxPool2d(kernel_size=4, stride=4), torch.nn.Conv2d(256, self.k, kernel_size=1, stride=1))`:将 conv3_4 层的输出进行最大池化和卷积操作,以提取更高级别的特征。 - `self.extract_2 = torch.nn.Sequential(torch.nn.MaxPool2d(kernel_size=2, stride=2), torch.nn.Conv2d(512, self.k, kernel_size=1, stride=1))`:将 conv4_4 层的输出进行最大池化和卷积操作,以提取更高级别的特征。 - `self.extract_3 = torch.nn.Sequential(torch.nn.Conv2d(512, self.k, kernel_size=1, stride=1))`:将 conv5_4 层的输出进行卷积操作,以提取更高级别的特征。 - `self.fc0 = torch.nn.Linear(196, 1, bias=True)`:定义一个输入为 196 的全连接层,用于分类。 - `self.fc1 = torch.nn.Linear(196, 1, bias=True)`:定义第二个输入为 196 的全连接层,用于分类。 - `self.fc2 = torch.nn.Linear(196, 1, bias=True)`:定义第三个输入为 196 的全连接层,用于分类。 - `self.fc3 = torch.nn.Linear(196, 1, bias=True)`:定义第四个输入为 196 的全连接层,用于分类。 - `self.fc4 = torch.nn.Linear(4096, 2 * k, bias=True)`:定义一个输入为 4096 的全连接层,用于分类。 - `self.bn1 = torch.nn.BatchNorm1d(k)`:定义一个 Batch Normalization 层,用于归一化数据。 - `self.bn2 = torch.nn.BatchNorm1d(k)`:定义第二个 Batch Normalization 层,用于归一化数据。 - `weight_init(self.fc0, self.fc1, self.fc2, self.fc3, self.fc4)`:对所有全连接层进行权重初始化,以提高模型的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值