参考:
Pytorch 从 0 开始学(6)——Conv2d 详解 – 知乎 (zhihu.com)
Conv1d — PyTorch 1.11.0 documentation
本文结合图例说明Conv1d的基本计算过程。
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}C i n ,C o u t 分别表示输入输出channel数,L i n , L o u t L_{in}, L_{out}L i n ,L o u t 分别表示输入输出的channel内信号长度。
下文简写作Cin、Cout、Lin、Lout。
关键参数如下:
- in_channels, out_channels: 输入输出通道数
- kernel_size: 卷积核长度
- stride=1: 卷积核步长
- padding=0, padding_mode=’zeros’: 边沿扩充, 目前略过
- dilation=1: 采样间隔
- bias=True: 是否加入bias
计算过程
输入输出维度
本文关注简单情形,假设采用默认参数(即 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 L o u t =L i n −k e r n e l _s i z e +1。
参数假设:
- 模型:Cin = 4,Cout = 3,kernel_size = 2。
- 输入:batchsize=1, Cin = 4, Lin = 3,即shape为(1, 4, 3)
Lout 计算
由上述公式:
Lout = 3 – 2 + 1 = 2,见下图:
因此输出维度 (Cout, Lout) 为 (3, 2)。
下面将由这个例子出发,说明计算过程。
in, out分别表示输入、输出tensor。
; 模型参数
模型有两类可学习参数:
- weight: shape = (Cout, Cin, kernel_size) = (3, 4, 2)
- bias: bias=True 时有效, shape = (Cout) = (3)
互相关(cross-correlation)计算
根据 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)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 )
其中 ⋆ \star ⋆ 表示互相关算符(cross-correlation operator), 下面以 w e i g h t ( j , i ) ⋆ i n ( i ) weight(j, i) \star in(i)w e i g h t (j ,i )⋆i n (i ) 为例, 取 j=1, i=2。
求和符号 Σ 后每一项的计算过程如下图:
weight 以”窗口滑动”的方式, 与 in(2) 中的元素(i0, i1, i2)依次运算。
计算结果为(j1, j2),构成输出的一部分。
最终 out(j) 的计算方式如下图:
- 求 out(1),需要用到 weight(1,*) 和 bias(1)。
- 对输入的每个 channel i,与 weight(1,i) 运算后得到 Cin 个新向量,这里是 4 个 (1, 2) 向量[蓝/白色]。
- 4 个向量直接相加,合并为 1 个向量[黄色]。
- 合并后的向量各个位置加上 bias(1) [灰色],就得到了最终的 out(1)[橙色]。
; 过程总结
最终的out由out(1)、out(2)、out(3)拼接而成, 整体过程总结如下:
对输入的每个 channel,都算出一个与输出 shape 一致的 tensor,然后叠加。最后再加上 bias,即为输出。
- Cin 维度上:每个 in_channel 影响所有 out_channel,反过来每个 out_channel 也可包含所有 in_channel 的信息。
- Lin 维度上:通过 weight 将长为 kernel_size 的一段元素联系起来。
验证
python 代码如下,可以验证上述过程:
import numpy as np
import torch
import torch.nn as nn
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]]])
Original: https://blog.csdn.net/weixin_42410798/article/details/124451826
Author: Hughpp
Title: torch.nn.Conv1d计算过程简易图解
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/671504/
转载文章受原作者版权保护。转载请注明原作者出处!