一维卷积torch.nn.Conv1d简单理解

torch.nn.Conv1d

torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True,padding_mode= ‘zeros’)

  • in_channels:输入通道数
  • out_channels:输出通道数(同卷积核个数)
  • kernel_size:卷积核“长度”,其另一维度值与输入的通道数相同,所以卷积核尺寸为kernel_size*in_channels
  • stride:滑动步长,默认为1
  • padding:补充0的个数,默认为0。例:当padding=1,则在输入的每一通道的数列的左右两端各补一个0
  • dilation:核的元素之间的间隔。 默认为1。(1应该是指元素间距,1即紧邻)
  • groups:分组数。例如,当groups=1,则所有输入都卷积到输出;groups=2时,这个操作就相当于有两个conv层并排,每个conv层作用于一半的输入通道,产生一半的输出通道,然后两者串联起来;groups= in_channels时,每个输入通道都用它自己的一组滤波器进行卷积,这些滤波器的大小为⌊in_channels/out_channels⌋

一维卷积过程

一维卷积是施加于两个数列(一个输入,一个核)的一种计算,过程可简单描述为:首先将两行数字左对齐,上下对应的数字分别相乘然后取和,得到一个新值;接着将核依照步长(stride)向右滑动,再次对应相乘取和得到新值;继续该滑动和计算过程,直到核的右端超出输入数组,此时不再计算,结束。例:

a=np.array([i for i in range(7)]).reshape(1,7,1)
conv1 = nn.Conv1d(in_channels=1,out_channels=1,kernel_size=2)
input = torch.Tensor(a) # shape (1,7,1) # in_channels=1
input = input.permute(0,2,1)    # shape (1,1,7) # in_channels=1
print(input)

nn.init.constant_(conv1.weight, 1)	# 将核的元素值初始化为全1
nn.init.constant_(conv1.bias, 0)	# 偏置值为0
print(conv1.weight)

out = conv1(input)
print(out.size())
print(out)
# 结果:
# tensor([[[0., 1., 2., 3., 4., 5., 6.]]])
# Parameter containing:
# tensor([[[1., 1.]]], requires_grad=True)
# torch.Size([1, 1, 6])
# tensor([[[ 1.,  3.,  5.,  7.,  9., 11.]]], grad_fn=<SqueezeBackward1>)

输入的形状(1,7,1),数值分别对应batch大小、数列(或文本分类中句子)的长度、通道数,即数列的个数(或文本分类中组成句子的单词的最大长度)。
nn.Conv1d的参数in_channels为输入的通道数,此例中1,即只有一个数列(或理解为该句子中每个单词仅一个字母),out_channels为输出的通道数(后面再具体说),kernel_size为核的长度。
permute函数将输入的形状进行了变换,以对应所生成的核的形状。
核的值被初始化为[1,1],卷积过程:01+11=1,11+21=3…51+61=11,得[1,3,5,7,9,11],结果为1个数列,即out_channels=1

上述为输入为一维的情况。当输入为二维,且第二个维度(通道数)值c>1,即有c个数列时,核也需要是二维(多通道),且第二个维度值(通道数)同样为c。例:(c=5)

a=np.array([i for i in range(35)]).reshape(1,7,5)
conv1 = nn.Conv1d(in_channels=5,out_channels=1,kernel_size=2)
input = torch.Tensor(a) # shape (1,7,5) # in_channels=5
input = input.permute(0,2,1)    # shape (1,5,7) # in_channels=5
print(input)

nn.init.constant_(conv1.weight, 1)	# 将核的元素值初始化为全1
nn.init.constant_(conv1.bias, 0)	# 偏置值为0
print(conv1.weight)

out = conv1(input)
print(out.size())
print(out)
# 结果
# tensor([[[ 0.,  5., 10., 15., 20., 25., 30.],
#          [ 1.,  6., 11., 16., 21., 26., 31.],
#          [ 2.,  7., 12., 17., 22., 27., 32.],
#          [ 3.,  8., 13., 18., 23., 28., 33.],
#          [ 4.,  9., 14., 19., 24., 29., 34.]]])
# Parameter containing:
# tensor([[[1., 1.],
#          [1., 1.],
#          [1., 1.],
#          [1., 1.],
#          [1., 1.]]], requires_grad=True)
# torch.Size([1, 1, 6])
# tensor([[[ 45.,  95., 145., 195., 245., 295.]]], grad_fn=<SqueezeBackward1>)

输入的通道数为5,即5个数列。第一行的数列与第一行的[1,1]进行卷积操作得到[5,15,25,35,45,55],第二行的数列与第二行的[1,1]进行卷积操作得到[7,17,27,37,47,57],同理,得到:

[5,15,25,35,45,55]
[7,17,27,37,47,57]
[9,19,29,39,49,59]
[11,21,31,41,51,61]
[13,23,33,43,53,63]

将五个结果的对应元素分别取和,得最终结果[ 45,95,145,195,245,295],out_channels仍为1。
可以看出,每个卷积核产生一个通道值,即out_channels=卷积核个数,当需要改变out_channels时,就需要增加卷积核个数,且每个卷积核的通道数=输入的通道数

  • 18
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值