【机器学习】卷积神经网络(CNN)的特征数计算
基本步骤
在卷积神经网络(CNN)中,计算最后的特征数通常涉及到以下步骤:
-  确定输入尺寸: 首先,你需要知道输入数据的尺寸。对于图像数据,这通常是 (batch_size, channels, height, width)。
-  应用卷积层: 在卷积操作过程中,图像与卷积核进行滑动窗口式的乘加运算,这会导致图像尺寸的变化。特征数会根据卷积核的数量和大小以及步长等因素发生变化。 - in_channels:输入数据的通道数。
- out_channels:卷积层产生的输出特征图的数量,即卷积核的数量。
- kernel_size:卷积核(- filter)的大小(- FxF)(- kernel_size的选择对模型的性能有很大影响,因为它决定了模型能够捕捉到的特征的尺度和复杂性。增大- kernel_size可以捕获更大范围的特征,但可能会增加计算复杂性和过拟合的风险;减小- kernel_size则可以关注更细节、局部的特征,但可能忽略掉一些重要的全局信息。因此,选择合适的- kernel_size是- CNN设计中的一个重要环节)。
- stride:卷积核在输入数据上滑动的步长。
- padding:在输入数据边缘添加的零填充的数量。
 
 卷积层的输出尺寸可以通过以下公式计算(floor()是向下取整函数):output_height = floor((input_height - kernel_size + 2 * padding) / stride) + 1 output_width = floor((input_width - kernel_size + 2 * padding) / stride) + 1特征数(或通道数)在卷积层后变为 out_channels。
-  应用池化层: 池化层通常不会改变特征数,但会改变特征图的高度和宽度。 池化层的输出尺寸可以通过以下公式计算: output_height = floor((input_height - kernel_size) / stride) + 1 output_width = floor((input_width - kernel_size) / stride) + 1
-  重复以上步骤: 继续应用卷积层和池化层,每次更新特征图的尺寸和特征数。 
-  全局平均池化或全连接层: 在某些情况下,网络可能包含全局平均池化层或全连接层,这些层可以进一步改变特征数。为了将这些特征图转换为一维向量以输入到全连接层,你需要将特征图的元素"展平" (flatten)。展平的过程是将所有元素按顺序排列成一个单一的向量。计算展平后的输入维度( in_features)的公式为:in_features = channels * height * width
-  最终特征数: 网络的最后一层之前的特征图的通道数就是最后的特征数。 
示例
以下是一个简单的例子来说明如何计算最后特征图的尺寸:给定 RGB 图像 (batch_size=32,channels=3,height=60,width=90)
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv_block1 = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True),
            nn.Conv2d(32, 32, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        self.conv_block2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        self.fc2 = nn.Sequential(
            nn.Linear(18816, 9408),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(9408, 4704),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(4704, 5)
        )
    def forward(self, x):
        x = self.conv_block1(x)
        x = self.conv_block2(x)
        x = x.reshape(x.shape[0], -1)
        x = self.fc2(x)
        return x
在上述代码中,给定一个 RGB 图像 (batch_size=32,channels=3,height=60,width=90),我们将图像输入到 self.conv_block1 和 self.conv_block2 进行处理。
首先,我们计算经过 self.conv_block1 后的特征数:
- 输入数据有 3个通道(RGB 图像)。
- 第一个卷积层将输出通道数增加到 32。
由于 kernel_size=3, stride=1, padding=1,即卷积核的大小为 3×3,步长为 1,填充为 1,我们可以计算新的特征图尺寸:
output_height = (60 - 3 + 2 * 1) / 1 + 1 = 60
output_width = (90 - 3 + 2 * 1) / 1 + 1 = 90
- 经过 ReLU激活函数后,特征数保持为32。
- 第二个卷积层仍然保持 32个输出通道,同上特征图的高度和宽度不变。
- 再经过 ReLU激活函数后,特征数仍为32。
- 最后,最大池化层不会改变通道数,但会减小特征图的高度和宽度。
由于 nn.MaxPool2d(kernel_size=3, stride=2),即最大池化层的池化窗口的大小为 3×3 步长为 2,我们可以计算新的特征图尺寸:
output_height = (60 - 3) / 2 + 1 = 29
output_width = (90 - 3) / 2 + 1 = 44
所以,经过self.conv_block1后,特征图的尺寸为(1, 32, 29, 44),特征数为 32。
接下来,我们将这个 32 通道的特征图输入到self.conv_block2:
- 第一个卷积层将输出通道数从 32增加到64,同上特征图的高度和宽度不变。
- 经过 ReLU激活函数后,特征数保持为64。
- 第二个卷积层仍然保持 64个输出通道,同上特征图的高度和宽度不变。
- 再经过 ReLU激活函数后,特征数仍为64。
- 最后,最大池化层不会改变通道数,但会进一步减小特征图的高度和宽度。
同样地,最大池化层的池化窗口的大小为 3×3 步长为 2,我们可以计算新的特征图尺寸:
output_height = (29 - 3) / 2 + 1 = 14
output_width = (29 - 3) / 2 + 1 = 21
因此,经过 self.conv_block1 和 self.conv_block2 后,最终的特征图的尺寸为 (32, 64, 14, 21)
nn.Linear 是 PyTorch 中的一个全连接层(Fully Connected Layer),它用于执行线性变换。全连接层的输入和输出维度通常是由网络架构和数据的特性决定的。
nn.Linear 的第一个参数,即输入维度(input_features 或 in_features)
为了将这些特征图转换为一维向量以输入到全连接层,你需要将特征图的元素“展平”(flatten)。展平的过程是将所有元素按顺序排列成一个单一的向量。我们可以计算展平后新的特征数,即输入维度 (in_features):
in_features = 64 * 14 * 21 = 18816
第一个全连接层输出维度为 9408,再经过 ReLU 激活函数。
nn.Dropout 是 PyTorch 库中的一种正则化技术的实现,常用于防止过拟合。在深度学习模型训练过程中,dropout 通过随机忽略(“丢弃”)一部分神经元的输出来降低模型的复杂性。这里 dropout 比例为 0.5,那么在训练过程中,每一步有 50% 的神经元输出会被随机设置为0。
同上过程,再来一次最后输出维度为 5,显然这是个 5-分类问题。
图解过程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!