LeNet5 神经网络的参数解析和图片尺寸解析

[复制链接]
发表于 2025-4-29 18:12:40 来自手机 | 显示全部楼层 |阅读模式
1.LeNet-5 神经网络

以下是针对 LeNet-5 神经网络的详细参数解析和图片尺寸变化分析,和原始论文设计,通太过步计算说明各层的张量变更过程。

经典的 LeNet-5架构简化版(原始论文输入为 32x32,MNIST 常用 28x28 需调整)。完备结构如下:


  • 网络结构
    输入 → Conv1 → 激活/池化 → Conv2 → 激活/池化 → 展平 → FC1 → FC2 → FC3 → 输出
  • 适用场景
    经典的小型 CNN,适合处理处罚低分辨率图像分类任务(如 MNIST、CIFAR-10)。
  1. class LeNet5(nn.Module):
  2.     def __init__(self):
  3.         super(LeNet5, self).__init__()
  4.         self.conv1 = nn.Conv2d(1, 6, 5)      # C1: 输入1通道,输出6通道,5x5卷积
  5.         self.pool1 = nn.AvgPool2d(2, 2)       # S2: 2x2平均池化
  6.         self.conv2 = nn.Conv2d(6, 16, 5)     # C3: 输入6,输出16,5x5卷积
  7.         self.pool2 = nn.AvgPool2d(2, 2)       # S4: 2x2平均池化
  8.         self.fc1 = nn.Linear(16*5*5, 120)    # C5: 全连接层
  9.         self.fc2 = nn.Linear(120, 84)        # F6: 全连接层
  10.         self.fc3 = nn.Linear(84, 10)         # 输出层
  11.     def forward(self, x):
  12.         x = F.relu(self.conv1(x))  # 卷积 + ReLU 激活
  13.         x = F.max_pool2d(x, 2)      # 2x2 最大池化
  14.         x = F.relu(self.conv2(x))
  15.         x = F.max_pool2d(x, 2)
  16.         x = x.view(-1, 16*5*5)      # 展平特征图
  17.         x = F.relu(self.fc1(x))
  18.         x = F.relu(self.fc2(x))
  19.         x = self.fc3(x)             # 输出层(通常不加激活函数)
  20.         return x
复制代码
1.2. 定义卷积层

定义
输入通道是指输入数据中独立的“特征平面”数目。对于图像数据,通常对应颜色通道或上一层的特征图数目。
  1. self.conv1 = nn.Conv2d(1, 6, 5)    # 第一层卷积
  2. self.conv2 = nn.Conv2d(6, 16, 5)   # 第二层卷积
  3. nn.Conv2d 参数说明
  4. conv1:
  5. 输入通道数 1(适用于单通道灰度图,如 MNIST)。
  6. 输出通道数 6(即 6 个卷积核,提取 6 种特征)。
  7. 卷积核大小 5x5。
  8. conv2:
  9. 输入通道数 6(与 conv1 的输出一致)。
  10. 输出通道数 16(更深层的特征映射)。
  11. 卷积核大小 5x5。
  12. 作用
  13. 通过卷积操作提取图像的空间特征(如边缘、纹理等),通道数的增加意味着学习更复杂的特征组合。
  14. 每个输出通道由一组卷积核生成:
  15. 如果输出通道数为 6,则会有 6 个不同的卷积核(每个核的尺寸为 5x5,在单输入通道下),分别提取不同的特征。
  16. 输出通道的维度:
  17. 输出数据的形状为 (batch_size, output_channels, height, width)。
  18. 例如:
  19. nn.Conv2d(3, 16, 5)  # 输入通道=3(RGB),输出通道=16
  20. 该层会使用 16 个卷积核,每个核的尺寸为 5x5x3(因为输入有 3 通道)。
  21. 每个核在输入数据上滑动计算,生成 1 个输出通道的特征图,最终得到 16 个特征图。
复制代码
 1.3定义全连接层

  1. self.fc1 = nn.Linear(16*5*5, 120)  # 第一个全连接层
  2. self.fc2 = nn.Linear(120, 84)      # 第二个全连接层
  3. self.fc3 = nn.Linear(84, 10)       # 输出层
  4. nn.Linear 参数说明
  5. fc1:
  6. 输入维度 16*5*5(假设卷积后特征图尺寸为 5x5,共 16 个通道,展平后为 400 维)。
  7. 输出维度 120(隐藏层神经元数量)。
  8. fc2:
  9. 输入维度 120,输出维度 84(进一步压缩特征)。
  10. fc3:
  11. 输入维度 84,输出维度 10(对应 10 个分类类别,如数字 0~9)。
  12. 作用
  13. 将卷积层提取的二维特征展平为一维向量,通过全连接层进行非线性变换,最终映射到分类结果。
复制代码

2. 参数解析(以输入 32x32 为例)

(1) 卷积层参数计算



  • 公式
    参数目 = (kernel_height × kernel_width × input_channels + 1) ×output_channels
    (+1 为偏置项)
层名参数定义参数目计算效果C1nn.Conv2d(1, 6, 5)(5×5×1 + 1)×6156C3nn.Conv2d(6, 16, 5)(5×5×6 + 1)×162416 (2) 全连接层参数计算



  • 公式
    参数目 = (input_features + 1) × output_features
层名参数定义参数目计算效果C5nn.Linear(16*5*5, 120)(400 + 1)×12048120F6nn.Linear(120, 84)(120 + 1)×8410164输出nn.Linear(84, 10)(84 + 1)×10850 总参数目:156 + 2416 + 48120 + 10164 + 850 = 61,706



3. 图片尺寸解析(输入 32x32)

(1) 尺寸变化公式



  • 卷积层
    H_out = floor((H_in + 2×padding - kernel_size) / stride + 1)
    (默认 stride=1, padding=0)
  • 池化层
    H_out = floor((H_in - kernel_size) / stride + 1)
    (通常 stride=kernel_size)
(2) 逐层尺寸变化

层名操作范例参数输入尺寸输出尺寸计算效果输入--1×32×32-1×32×32C1卷积kernel=5, stride=11×32×32(32 - 5)/1 + 1 = 286×28×28S2均匀池化kernel=2, stride=26×28×28(28 - 2)/2 + 1 = 146×14×14C3卷积kernel=5, stride=16×14×14(14 - 5)/1 + 1 = 1016×10×10S4均匀池化kernel=2, stride=216×10×10(10 - 2)/2 + 1 = 516×5×5C5展平+全连接-16×5×5展平为 400 维向量120F6全连接-120-84输出全连接-84-10 (3) 关键题目解答

Q1: 为什么全连接层 fc1 的输入是 16*5*5?



  • 经过两次卷积和池化后,特征图尺寸从 32x32 → 28x28 → 14x14 → 10x10 → 5x5,且最后一层有 16 个通道,因此展平后的维度为 16×5×5=400。
Q2: 如果输入是 28x28(如 MNIST),尺寸会如何变化?



  • 调整方式
    修改第一层卷积的 padding=2(在四周补零),使输出尺寸满足 (28+4-5)/1 +1=28(保持尺寸稳固),后续计算与原始 LeNet-5 划一。
    1. self.conv1 = nn.Conv2d(1, 6, 5, padding=2) # 保持28x28
    复制代码
    Q3: 参数目重要会集在哪部门?
  • 全连接层 C5 占总数 78% (48120/61706),这是 LeNet-5 的设计瓶颈。现代 CNN 通常用全局均匀池化(GAP)替换全连接层以淘汰参数。
5. 完备尺寸变更流程图(输入 32x32)

  1. 输入: 1×32×32
  2.   ↓ [C1] Conv2d(1,6,5)
  3. 6×28×28
  4.   ↓ [S2] AvgPool2d(2,2)
  5. 6×14×14
  6.   ↓ [C3] Conv2d(6,16,5)
  7. 16×10×10
  8.   ↓ [S4] AvgPool2d(2,2)
  9. 16×5×5
  10.   ↓ 展平
  11. 400
  12.   ↓ [C5] Linear(400,120)
  13. 120
  14.   ↓ [F6] Linear(120,84)
  15. 84
  16.   ↓ 输出
  17. 10
复制代码
 利用下面代码,可以看到详细参数目:
  1. # 遍历模型的所有子模块
  2. for name, param in model.named_parameters():
  3.     if param.requires_grad:
  4.         print(f"Layer: {name}")
  5.         if 'weight' in name:
  6.             print(f"Weights:{param.data.shape}")
  7.         if 'bias' in name:
  8.             print(f"Bias:{param.data.shape}\n")
复制代码
 输出:
  1. Layer: feature_extractor.0.weight
  2. Weights:torch.Size([6, 1, 5, 5])
  3. Layer: feature_extractor.0.bias
  4. Bias:torch.Size([6])
  5. Layer: feature_extractor.2.weight
  6. Weights:torch.Size([16, 6, 5, 5])
  7. Layer: feature_extractor.2.bias
  8. Bias:torch.Size([16])
  9. Layer: classifier.1.weight
  10. Weights:torch.Size([120, 400])
  11. Layer: classifier.1.bias
  12. Bias:torch.Size([120])
  13. Layer: classifier.2.weight
  14. Weights:torch.Size([84, 120])
  15. Layer: classifier.2.bias
  16. Bias:torch.Size([84])
  17. Layer: classifier.3.weight
  18. Weights:torch.Size([10, 84])
  19. Layer: classifier.3.bias
  20. Bias:torch.Size([10])
复制代码
   写完文章,疑问终于搞明白了。大家也可以参考下面这个连接。
   https://blog.csdn.net/lihuayong/article/details/145671336?fromshare=blogdetail&sharetype=blogdetail&sharerId=145671336&sharerefer=PC&sharesource=lihuayong&sharefrom=from_link

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5

GMT+8, 2025-7-9 10:05 , Processed in 0.084502 second(s), 31 queries 手机版|qidao123.com技术社区-IT企服评测▪应用市场 ( 浙ICP备20004199 )|网站地图

快速回复 返回顶部 返回列表