卷积神经网络-- 3 多通道卷积与偏置过程
一、多通道卷积概念
核心思想:多通道卷积就是分别对每个通道进行卷积,然后把结果加起来。
在图像处理中,通道是指图像的不同分量。例如,灰度图像只有一个通道也就是亮度。彩色图像,有三个通道(RGB)。
以彩色图像为例,包含三个通道。输入为(3,5,5),分别表示3个通道,每个通道的宽为5,高为5。假设卷积核只有1个,卷积核通道为3,每个通道的卷积核大小仍为3x3,padding=0,stride=1。
每一个通道的像素值与对应的卷积核通道的数值进行卷积,因此每一个通道会对应一个输出卷积结果,三个卷积结果对应位置累加求和,得到最终的卷积结果,这里卷积输出结果通道只有1个,因为卷积核只有1。最终得到的卷积结果是原始图像各个通道上的综合信息结果。

因为对每个通道的像素进行卷积运算,所以每个卷积核的通道数量必须与输入通道数量保持一致。
如果把上述图像堆叠,计算原理一样:

二、单卷积核多通道

代码实例:
import torch
import torch.nn as nn
import numpy as np
'''创建一个大小为 28*28 的单通道图像
input_data = torch.randn(1, 3, 3, 3) '''
'''
使用创建一个 NumPy 数组来创建四维的'''
matrix_np = np.array([[[[0.0, 1.0, 1.0],
[0.0, 0.0, 1.0],
[0.0, 0.0, 0.0]],
[[0.0, 0.0, 1.0],
[1.0, 0.0, 1.0],
[0.0, 0.0, 0.0]],
[[1.0, 0.0, 1.0],
[1.0, 1.0, 1.0],
[1.0, 0.0, 0.0]]
]])
kernel = torch.tensor([[
[1., 0.],
[0., 0.]
],
[
[0., 1.],
[0., 0.]
],
[
[0., 0.],
[1., 0.]
]], dtype=torch.float32)
'''将数组的数据类型转换为32位读点书,确保数组中的元素与后面的张量Kernel具有相同的数据类型'''
matrix_np =matrix_np.astype(np.float32)
'''转换为 PyTorch 张量'''
input_data = torch.from_numpy(matrix_np)
'''创建卷积层
参数:
in_channels: 输入数据的通道数,3表示3通道(如彩色图像)
out_channels: 输出数据的通道数,1表示输出也是单通道
kernel_size=2: 卷积核的大小是2×2
stride=1: 卷积步长为1,表示每次移动1个像素
padding=0 表示不在输入特征图的周围填充任何像素,不进行任何额外的边界扩展
bias=False: 不使用偏置项
'''
conv_layer = nn.Conv2d(
in_channels=3,
out_channels=1,
stride=1,
kernel_size=2,
padding=0,
bias=False)
'''设置卷积核的权重
kernel.view(1,1,2,2)将kernel变量重新塑形为4维张量,形状为(1,1,2,2)
对应:
第1个1: 输出通道数
第2个3: 输入通道数
2,2: 卷积核的高度和宽度
'''
conv_layer.weight.data = kernel.view(1, 3, 2, 2)
'''手动设置卷积核偏置项(偏置项形状:[out_channels])
conv_layer.bias.data.fill_(-1.0),在输出结果的数字减去1'''
# 对输入数据进行卷积操作
output_data = conv_layer(input_data)
# 输出结果
print(output_data)
print(output_data.shape)#形状
print(torch.round(output_data))#取整
结果1(未手动设置卷积核偏置项):
tensor([[[[1., 3.],
[1., 1.]]]], grad_fn=<ConvolutionBackward0>)
torch.Size([1, 1, 2, 2])
tensor([[[[1., 3.],
[1., 1.]]]], grad_fn=<RoundBackward0>)
结果2(手动设置卷积核偏置项):
tensor([[[[1., 3.],
[1., 1.]]]], grad_fn=<ConvolutionBackward0>)
torch.Size([1, 1, 2, 2])
tensor([[[[0., 2.],
[0., 0.]]]], grad_fn=<RoundBackward0>)
三、多卷积多通道

未设置偏置项的代码实例:
import torch
import torch.nn as nn
import numpy as np
'''创建一个大小为 28*28 的单通道图像
input_data = torch.randn(1, 3, 3, 3) '''
'''
使用创建一个 NumPy 数组来创建四维的'''
matrix_np = np.array([[[[0.0, 1.0, 1.0],
[0.0, 0.0, 1.0],
[0.0, 0.0, 0.0]],
[[0.0, 0.0, 1.0],
[1.0, 0.0, 1.0],
[0.0, 0.0, 0.0]],
[[1.0, 0.0, 1.0],
[1.0, 1.0, 1.0],
[1.0, 0.0, 0.0]]
]])
kernel = torch.tensor([
[
[
[1., 0.],
[0., 0.]
]
,
[
[0., 1.],
[0., 0.]
]
,
[
[0., 0.],
[1., 0.]
]
],
[
[
[1., 0.],
[0., 0.]
]
,
[
[1., 0.],
[0., 0.]
]
,
[
[1., 0.],
[0., 0.]
]
]
], dtype=torch.float32)
'''将数组的数据类型转换为32位读点书,确保数组中的元素与后面的张量Kernel具有相同的数据类型'''
matrix_np =matrix_np.astype(np.float32)
'''转换为 PyTorch 张量'''
input_data = torch.from_numpy(matrix_np)
'''创建卷积层
参数:
in_channels: 输入数据的通道数,3表示3通道(如彩色图像)
out_channels: 输出数据的通道数,1表示输出也是单通道
kernel_size=2: 卷积核的大小是2×2
stride=1: 卷积步长为1,表示每次移动1个像素
padding=0 表示不在输入特征图的周围填充任何像素,不进行任何额外的边界扩展
bias=False: 使用偏置项
'''
conv_layer = nn.Conv2d(
in_channels=3,
out_channels=2,
stride=1,
kernel_size=2,
padding=0,
bias=True)
'''设置卷积核的权重
kernel.view(1,1,2,2)将kernel变量重新塑形为4维张量,形状为(1,1,2,2)
对应:
第1个1: 输出通道数
第2个3: 输入通道数
2,2: 卷积核的高度和宽度
'''
conv_layer.weight.data = kernel.view(2, 3, 2, 2)
'''手动设置卷积核偏置项(偏置项形状:[out_channels])
conv_layer.bias.data.fill_(-1.0),在输出结果的数字减去1'''
# 对输入数据进行卷积操作
output_data = conv_layer(input_data)
# 输出结果
print(output_data)
print(output_data.shape)#形状
print(torch.round(output_data))#取整
结果:
tensor([[[[0.8839, 2.8839],
[0.8839, 0.8839]],
[[1.1880, 1.1880],
[2.1880, 1.1880]]]], grad_fn=<ConvolutionBackward0>)
torch.Size([1, 2, 2, 2])
tensor([[[[1., 3.],
[1., 1.]],
[[1., 1.],
[2., 1.]]]], grad_fn=<RoundBackward0>)
设置偏置项的情况实例,设置第一个卷积核偏置项=-1,第二个偏置项=1。
import torch
import torch.nn as nn
import numpy as np
'''创建一个大小为 28*28 的单通道图像
input_data = torch.randn(1, 3, 3, 3) '''
'''
使用创建一个 NumPy 数组来创建四维的'''
matrix_np = np.array([[[[0.0, 1.0, 1.0],
[0.0, 0.0, 1.0],
[0.0, 0.0, 0.0]],
[[0.0, 0.0, 1.0],
[1.0, 0.0, 1.0],
[0.0, 0.0, 0.0]],
[[1.0, 0.0, 1.0],
[1.0, 1.0, 1.0],
[1.0, 0.0, 0.0]]
]])
kernel = torch.tensor([
[
[
[1., 0.],
[0., 0.]
]
,
[
[0., 1.],
[0., 0.]
]
,
[
[0., 0.],
[1., 0.]
]
],
[
[
[1., 0.],
[0., 0.]
]
,
[
[1., 0.],
[0., 0.]
]
,
[
[1., 0.],
[0., 0.]
]
]
], dtype=torch.float32)
'''将数组的数据类型转换为32位读点书,确保数组中的元素与后面的张量Kernel具有相同的数据类型'''
matrix_np =matrix_np.astype(np.float32)
'''转换为 PyTorch 张量'''
input_data = torch.from_numpy(matrix_np)
'''创建卷积层
参数:
in_channels: 输入数据的通道数,3表示3通道(如彩色图像)
out_channels: 输出数据的通道数,1表示输出也是单通道
kernel_size=2: 卷积核的大小是2×2
stride=1: 卷积步长为1,表示每次移动1个像素
padding=0 表示不在输入特征图的周围填充任何像素,不进行任何额外的边界扩展
bias=False: 使用偏置项
'''
conv_layer = nn.Conv2d(
in_channels=3,
out_channels=2,
stride=1,
kernel_size=2,
padding=0,
bias=True)
'''设置卷积核的权重
kernel.view(1,1,2,2)将kernel变量重新塑形为4维张量,形状为(1,1,2,2)
对应:
第1个1: 输出通道数
第2个3: 输入通道数
2,2: 卷积核的高度和宽度
'''
conv_layer.weight.data = kernel.view(2, 3, 2, 2)
'''手动设置卷积核偏置项(偏置项形状:[out_channels]),在输出结果的数字减去1'''
conv_layer.bias.data[0].fill_(-1.0)#对第一个卷积核设置偏置项
conv_layer.bias.data[1].fill_(1.0)#对第二个卷积核设置偏置项
# 对输入数据进行卷积操作
output_data = conv_layer(input_data)
# 输出结果
print(output_data)
print(output_data.shape)#形状
print(torch.round(output_data))#取整
结果:
tensor([[[[0., 2.],
[0., 0.]],
[[2., 2.],
[3., 2.]]]], grad_fn=<ConvolutionBackward0>)
torch.Size([1, 2, 2, 2])
tensor([[[[0., 2.],
[0., 0.]],
[[2., 2.],
[3., 2.]]]], grad_fn=<RoundBackward0>)
结论:
-
输入特征的通道数决定了卷积核的通道数(卷积核通道个数=输入特征通道个数)。
-
卷积核的个数决定了输出特征矩阵的通道数与偏置矩阵的通道数(卷积核个数=输出特征通道数=偏置矩阵通道数)。
更多推荐
所有评论(0)