一维和二维的区别
一维卷积层和池化层以及二维卷积层和池化层在处理数据的维度上有一些关键的区别。这些差异主要体现在数据的形状、卷积核的维度、以及计算中的一些细节上。
一维卷积层和池化层:
-
数据形状: 一维卷积和池化主要用于处理序列数据,比如时间序列或文本数据。输入数据是一个序列,可以看作是一维的,具有长度。
-
卷积核: 一维卷积核在一个维度上进行滑动操作,只考虑输入序列的局部信息。卷积核的大小是在这一个维度上的窗口大小。
-
池化层: 一维池化层通常是在一个维度上对局部信息进行池化操作,通常使用最大池化或平均池化。池化窗口的大小和步幅也是在这一个维度上。
二维卷积层和池化层:
-
数据形状: 二维卷积和池化主要用于处理图像数据,其形状是二维的,有宽度和高度。
-
卷积核: 二维卷积核在两个维度上进行滑动操作,同时考虑输入图像的横向和纵向的局部信息。卷积核的大小是在两个维度上的矩形窗口大小。
-
池化层: 二维池化层在两个维度上对局部信息进行池化操作,通常使用最大池化或平均池化。池化窗口的大小和步幅也是在两个维度上。
总的来说,一维卷积和池化主要用于处理序列数据,而二维卷积和池化主要用于处理图像数据。在卷积神经网络中,这些层的设计目标是保留重要的局部信息,并逐渐捕获更高级别的特征。在实践中,可以根据具体的任务和数据类型选择合适的卷积层和池化层。
一维卷积和池化的示例:
假设我们有一个包含 8 个时间步的温度序列数据:
[ 22.5 , 23.1 , 24.5 , 22.8 , 21.9 , 23.5 , 24.2 , 25.0 ] [22.5, 23.1, 24.5, 22.8, 21.9, 23.5, 24.2, 25.0] [22.5,23.1,24.5,22.8,21.9,23.5,24.2,25.0]
我们可以使用一维卷积和池化来提取序列中的模式。考虑一个卷积核大小为3的卷积层,步幅为1,然后使用大小为2的最大池化层。
- 输入序列: 22.5 , 23.1 , 24.5 , 22.8 , 21.9 , 23.5 , 24.2 , 25.0 22.5, 23.1, 24.5, 22.8, 21.9, 23.5, 24.2, 25.0 22.5,23.1,24.5,22.8,21.9,23.5,24.2,25.0
- 一维卷积输出: C 1 , C 2 , C 3 , C 4 , C 5 , C 6 C_1, C_2, C_3, C_4, C_5, C_6 C1,C2,C3,C4,C5,C6
- 最大池化输出: P 1 , P 2 , P 3 P_1, P_2, P_3 P1,P2,P3
在这个例子中,卷积层将窗口大小为3的卷积核沿时间步滑动,得到一维卷积的输出。然后,最大池化层在一维卷积的输出上进行池化,减小特征图的长度。
二维卷积和池化的示例:
考虑一个简单的灰度图像,每个像素的值表示亮度:
[ 120 125 130 110 115 120 100 105 110 ] \begin{bmatrix} 120 & 125 & 130 \\ 110 & 115 & 120 \\ 100 & 105 & 110 \\ \end{bmatrix} 120110100125115105130120110
我们可以使用二维卷积和池化来提取图像中的特征。考虑一个大小为 2 × 2 2 \times 2 2×2 的卷积核,步幅为1,然后使用大小为 2 × 2 2 \times 2 2×2的最大池化层。
- 输入图像:
[ 120 125 130 110 115 120 100 105 110 ] \begin{bmatrix} 120 & 125 & 130 \\ 110 & 115 & 120 \\ 100 & 105 & 110 \\ \end{bmatrix} 120110100125115105130120110 - 二维卷积输出:
[ C 11 C 12 C 21 C 22 ] \begin{bmatrix} C_{11} & C_{12} \\ C_{21} & C_{22} \\ \end{bmatrix} [C11C21C12C22] - 最大池化输出:
[ P 11 P 12 P 21 P 22 ] \begin{bmatrix} P_{11} & P_{12} \\ P_{21} & P_{22} \\ \end{bmatrix} [P11P21P12P22]
在这个例子中,二维卷积层在图像上滑动 2 × 2 2 \times 2 2×2 的卷积核,得到二维卷积的输出。然后,最大池化层在二维卷积的输出上进行 2 × 2 2 \times 2 2×2 的池化,减小特征图的宽度和高度。
这两个示例说明了一维和二维卷积层以及池化层的应用场景和计算方式。在实际中,这些层的参数和结构会根据任务和数据的特点进行调整。
二维
对于二维卷积层:
假设输入的大小是 W in × H in W_{\text{in}} \times H_{\text{in}} Win×Hin,其中 W in W_{\text{in}} Win 是宽度(width), H in H_{\text{in}} Hin 是高度(height)。卷积操作通常使用一个卷积核(filter)来滑动在输入上,产生输出。卷积核的大小通常表示为 W k × H k W_k \times H_k Wk×Hk,其中 W k W_k Wk是卷积核的宽度, H k H_k Hk是卷积核的高度。
在卷积操作中,输出的大小可以通过以下公式计算:
W out = floor ( ( W in − W k + 2 × padding_width ) stride_width ) + 1 W_{\text{out}} = \text{floor}\left(\frac{(W_{\text{in}} - W_k + 2 \times \text{padding\_width})}{\text{stride\_width}}\right) + 1 Wout=floor(stride_width(Win−Wk+2×padding_width))+1
H out = floor ( ( H in − H k + 2 × padding_height ) stride_height ) + 1 H_{\text{out}} = \text{floor}\left(\frac{(H_{\text{in}} - H_k + 2 \times \text{padding\_height})}{\text{stride\_height}}\right) + 1 Hout=floor(stride_height(Hin−Hk+2×padding_height))+1
其中,padding\_width
和 padding\_height
是在输入的宽度和高度上应用的填充(padding),stride\_width
和 stride\_height
是卷积核在输入上滑动的步幅。
对于池化层:
池化层通常有最大池化和平均池化两种常见类型。池化操作的目的是减小特征图的尺寸,同时保留重要的特征。
在最大池化中,输出的大小可以通过以下公式计算:
W out = floor ( ( W in − pool_size_width ) stride_width ) + 1 W_{\text{out}} = \text{floor}\left(\frac{(W_{\text{in}} - \text{pool\_size\_width})}{\text{stride\_width}}\right) + 1 Wout=floor(stride_width(Win−pool_size_width))+1
H out = floor ( ( H in − pool_size_height ) stride_height ) + 1 H_{\text{out}} = \text{floor}\left(\frac{(H_{\text{in}} - \text{pool\_size\_height})}{\text{stride\_height}}\right) + 1 Hout=floor(stride_height(Hin−pool_size_height))+1
其中,pool\_size\_width
和 pool\_size\_height
是池化窗口的宽度和高度,stride\_width
和 stride\_height
是池化窗口在输入上滑动的步幅。
总体来说,卷积层和池化层会根据其操作的性质导致输出的尺寸发生变化。通过调整卷积核的大小、步幅和填充,以及池化窗口的大小和步幅,可以控制输出尺寸的变化。这些调整通常是为了在保留关键特征的同时降低计算复杂性和内存需求。
一维数据
对于一维卷积层和池化层,输入和输出的计算公式如下:
一维卷积层(Conv1d):
输入大小: Input size = Batch size × Input channels × Input length \text{Input size} = \text{Batch size} \times \text{Input channels} \times \text{Input length} Input size=Batch size×Input channels×Input length
卷积核大小: Kernel size \text{Kernel size} Kernel size
填充(padding): Padding size \text{Padding size} Padding size
步幅(stride): Stride size \text{Stride size} Stride size
输出大小: Output size = floor ( Input length − Kernel size + 2 × Padding size Stride size ) + 1 \text{Output size} = \text{floor}\left(\frac{\text{Input length} - \text{Kernel size} + 2 \times \text{Padding size}}{\text{Stride size}}\right) + 1 Output size=floor(Stride sizeInput length−Kernel size+2×Padding size)+1
一维池化层(MaxPool1d 或 AvgPool1d):
输入大小: Input size = Batch size × Input channels × Input length \text{Input size} = \text{Batch size} \times \text{Input channels} \times \text{Input length} Input size=Batch size×Input channels×Input length
池化窗口大小: Pool size \text{Pool size} Pool size
步幅(stride): Stride size \text{Stride size} Stride size
输出大小: Output size = floor ( Input length − Pool size Stride size ) + 1 \text{Output size} = \text{floor}\left(\frac{\text{Input length} - \text{Pool size}}{\text{Stride size}}\right) + 1 Output size=floor(Stride sizeInput length−Pool size)+1
这里,“Input size” 是输入张量的大小,“Kernel size” 是卷积核的大小,“Padding size” 是填充的大小,“Stride size” 是步幅的大小,“Output size” 是输出张量的大小。对于池化层,池化窗口的大小和步幅取决于具体使用的是最大池化(MaxPool1d)还是平均池化(AvgPool1d)。
请根据你的具体情况和模型定义中的参数来使用这些公式。希望这能帮助你更好地理解一维卷积层和池化层的输入输出关系。
举例说明
class CNNSimpleModel(nn.Module):
def __init__(self):
super(CNNSimpleModel, self).__init__()
self.conv1 = nn.Conv1d(1, 16, kernel_size=3, stride=1, padding=1)
self.pool = nn.MaxPool1d(kernel_size=2, stride=2)
self.conv2 = nn.Conv1d(16, 32, kernel_size=3, stride=1, padding=1)
self.fc1 = nn.Linear(32 * 2, 64) # 根据输入序列长度调整
self.fc2 = nn.Linear(64, 2) # 输出2个值,对应X和Y轴坐标
def forward(self, x):
print(x.shape)
x = F.relu(self.conv1(x))
print(x.shape)
x = self.pool(x)
print(x.shape)
x = F.relu(self.conv2(x))
print(x.shape)
x = self.pool(x)
print(x.shape)
x = x.view(-1, 32 * 2) # 根据输入序列长度调整
print(x.shape)
x = F.relu(self.fc1(x))
print(x.shape)
x = self.fc2(x)
print(x.shape)
return x
# 我得到的结果是
torch.Size([135, 1, 8])
torch.Size([135, 16, 8])
torch.Size([135, 16, 4])
torch.Size([135, 32, 4])
torch.Size([135, 32, 2])
torch.Size([135, 64])
torch.Size([135, 64])
torch.Size([135, 2])
模型是一个简单的卷积神经网络(CNN)模型,用于处理一维序列数据。下面我会解释每一步的计算过程,以及为什么会得到相应的尺寸。
让我们一步一步计算模型中每一层的输出形状:
-
输入:
- 输入张量的大小是
[135, 1, 8]
,其中135
是批量大小(batch size),1
是通道数,8
是序列长度。
- 输入张量的大小是
-
第一个卷积层 (
self.conv1
):- 卷积核大小为 3,步幅为 1,填充为 1。
- 输出尺寸计算:
W out = floor ( ( W in − W k + 2 × padding ) stride ) + 1 W_{\text{out}} = \text{floor}\left(\frac{(W_{\text{in}} - W_k + 2 \times \text{padding})}{\text{stride}}\right) + 1 Wout=floor(stride(Win−Wk+2×padding))+1
W out = floor ( ( 8 − 3 + 2 × 1 ) 1 ) + 1 = 8 W_{\text{out}} = \text{floor}\left(\frac{(8 - 3 + 2 \times 1)}{1}\right) + 1 = 8 Wout=floor(1(8−3+2×1))+1=8 - 因此,卷积后的大小为
[135, 16, 8]
。 - 16 表示卷积层的输出通道数(output channels)。对于一维卷积层 nn.Conv1d,它的输出通道数是由用户设定的
-
第一个池化层 (
self.pool
):- 池化窗口大小为 2,步幅为 2。
- 输出尺寸计算:
W out = floor ( ( W in − pool_size ) stride ) + 1 W_{\text{out}} = \text{floor}\left(\frac{(W_{\text{in}} - \text{pool\_size})}{\text{stride}}\right) + 1 Wout=floor(stride(Win−pool_size))+1
W out = floor ( ( 8 − 2 ) 2 ) + 1 = 4 W_{\text{out}} = \text{floor}\left(\frac{(8 - 2)}{2}\right) + 1 = 4 Wout=floor(2(8−2))+1=4 - 因此,池化后的大小为
[135, 16, 4]
。
-
第二个卷积层 (
self.conv2
):- 卷积核大小为 3,步幅为 1,填充为 1。
- 输出尺寸计算:
W out = floor ( ( W in − W k + 2 × padding ) stride ) + 1 W_{\text{out}} = \text{floor}\left(\frac{(W_{\text{in}} - W_k + 2 \times \text{padding})}{\text{stride}}\right) + 1 Wout=floor(stride(Win−Wk+2×padding))+1
W out = floor ( ( 4 − 3 + 2 × 1 ) 1 ) + 1 = 4 W_{\text{out}} = \text{floor}\left(\frac{(4 - 3 + 2 \times 1)}{1}\right) + 1 = 4 Wout=floor(1(4−3+2×1))+1=4 - 因此,卷积后的大小为
[135, 32, 4]
。
-
第二个池化层 (
self.pool
):- 池化窗口大小为 2,步幅为 2。
- 输出尺寸计算:
W out = floor ( ( W in − pool_size ) stride ) + 1 W_{\text{out}} = \text{floor}\left(\frac{(W_{\text{in}} - \text{pool\_size})}{\text{stride}}\right) + 1 Wout=floor(stride(Win−pool_size))+1
W out = floor ( ( 4 − 2 ) 2 ) + 1 = 2 W_{\text{out}} = \text{floor}\left(\frac{(4 - 2)}{2}\right) + 1 = 2 Wout=floor(2(4−2))+1=2 - 因此,池化后的大小为
[135, 32, 2]
。
-
Flatten 操作 (
x.view(-1, 32 * 2)
):- 将池化后的张量展平,大小变为
[135, 32 * 2]
,即[135, 64]
。
- 将池化后的张量展平,大小变为
-
第一个全连接层 (
self.fc1
):- 输入大小为
64
,输出大小为64
。 - 因此,全连接层输出的大小为
[135, 64]
。
- 输入大小为
-
第二个全连接层 (
self.fc2
):- 输入大小为
64
,输出大小为2
。 - 因此,全连接层输出的大小为
[135, 2]
。
- 输入大小为
这就是每个数字的计算过程,希望这能够帮助你理解整个模型的前向传播过程。