参考:
Pytorch 从 0 开始学(6)——Conv2d 详解 - 知乎 (zhihu.com)
Conv1d — PyTorch 1.11.0 documentation
本文结合图例说明Conv1d的基本计算过程。
torch.nn.Conv1d(in_channels, out_channels, kernel_size,
stride=1, padding=0, dilation=1, groups=1,
bias=True, padding_mode='zeros', device=None, dtype=None)
输入维度(N, Cin, Lin)
输出维度(N, Cout, Lout)
这里,N为batchsize, C i n , C o u t C_{in}, C_{out} Cin,Cout分别表示输入输出channel数, L i n , L o u t L_{in}, L_{out} Lin,Lout分别表示输入输出的channel内信号长度。
下文简写作Cin、Cout、Lin、Lout。
关键参数如下:
本文关注简单情形,假设采用默认参数(即 stride=1, padding=0, dilation=1),
则 L o u t = L i n − k e r n e l _ s i z e + 1 L_{out} = L_{in} - kernel\_size + 1 Lout=Lin−kernel_size+1。
参数假设:
由上述公式:
因此输出维度 (Cout, Lout) 为 (3, 2)。
下面将由这个例子出发,说明计算过程。
in, out分别表示输入、输出tensor。
模型有两类可学习参数:
根据 pytorch 的计算公式:
o u t ( j ) = b i a s ( j ) + ∑ i = 0 C i n − 1 w e i g h t ( j , i ) ⋆ i n ( i ) out(j) = bias(j) + \sum_{i=0}^{C_{in}-1} weight(j, i) \star in(i) out(j)=bias(j)+i=0∑Cin−1weight(j,i)⋆in(i)
其中 ⋆ \star ⋆ 表示互相关算符(cross-correlation operator), 下面以 w e i g h t ( j , i ) ⋆ i n ( i ) weight(j, i) \star in(i) weight(j,i)⋆in(i) 为例, 取 j=1, i=2。
求和符号 Σ 后每一项的计算过程如下图:
weight 以"窗口滑动"的方式, 与 in(2) 中的元素(i0, i1, i2)依次运算。
计算结果为(j1, j2),构成输出的一部分。
最终的out由out(1)、out(2)、out(3)拼接而成, 整体过程总结如下:
对输入的每个 channel,都算出一个与输出 shape 一致的 tensor,然后叠加。最后再加上 bias,即为输出。
python 代码如下,可以验证上述过程:
import numpy as np
import torch
import torch.nn as nn
#print(torch.__version__) #1.8.0+cu111
#模型设置与参数赋值
conv = nn.Conv1d(in_channels=4, out_channels=3, kernel_size=2)
bias = torch.FloatTensor([0.1, 0.2, 0.3])
weight = np.arange(24).reshape(3,4,2)
weight = torch.FloatTensor(weight)
for name, param in conv.named_parameters():
if name == 'weight':
param.data = weight
if name == 'bias':
param.data = bias
print(name, param.shape, param)
#构造输入并计算输出
input = [
[0,0,0],
[0,0,1],
[0,1,1],
[1,1,1]
]
input = torch.FloatTensor(input).reshape(1,4,3)
with torch.no_grad():
print('\ninput:\n', input)
output = conv(input)
print('output:\n', output)
输出结果为:
#输出结果
weight torch.Size([3, 4, 2]) Parameter containing:
tensor([[[ 0., 1.],
[ 2., 3.],
[ 4., 5.],
[ 6., 7.]],
[[ 8., 9.],
[10., 11.],
[12., 13.],
[14., 15.]],
[[16., 17.],
[18., 19.],
[20., 21.],
[22., 23.]]], requires_grad=True)
bias torch.Size([3]) Parameter containing:
tensor([0.1000, 0.2000, 0.3000], requires_grad=True)
input:
tensor([[[0., 0., 0.],
[0., 0., 1.],
[0., 1., 1.],
[1., 1., 1.]]])
output:
tensor([[[ 18.1000, 25.1000],
[ 42.2000, 65.2000],
[ 66.3000, 105.3000]]])