news 2026/6/10 18:35:08

[深度学习网络从入门到入土] lenet

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[深度学习网络从入门到入土] lenet

[深度学习网络从入门到入土] lenet

个人导航

知乎:https://www.zhihu.com/people/byzh_rc

CSDN:https://blog.csdn.net/qq_54636039

注:本文仅对所述内容做了框架性引导,具体细节可查询其余相关资料or源码

参考文章:各方资料

文章目录

  • [深度学习网络从入门到入土] lenet
  • 个人导航
  • 参考资料
  • 背景
  • 架构(公式)
        • 1.输入层
        • 2.卷积层(Convolution)
        • 3.下采样层(Pooling)
        • 4.全连接层(Fully Connected)
        • 5.激活函数
  • 创新点
        • 1. LeNet 第一次完整定义了 CNN 的结构模板
        • 2. 从“人工特征”到“特征学习”
  • 代码实现

参考资料

Gradient-based learning applied to document recognition

背景

在 LeNet 出现之前,图像任务基本是“手工特征 + 传统分类器”

  1. 边缘检测(Edge Detection)
  2. 人工特征(HOG / SIFT)
  3. 降维PCA / 投影LDA
  4. 最后接 SVM / KNN

这些方法有一个致命问题:特征是人为设计的,模型本身不会“学特征”

LeNet:第一次系统性地证明了:神经网络可以端到端地从原始图像中学习特征并完成分类

  • 手写数字识别(MNIST)
  • 支票 / 邮政编码识别

架构(公式)

1.输入层

输入通常为灰度图像(channel=1):
X ∈ R 1 × 32 × 32 X \in \mathbb{R}^{1 \times 32 \times 32}XR1×32×32

  • MNIST 原始是28 × 28 28\times2828×28-> LeNet 里通常padding 到32 × 32 32\times3232×32
2.卷积层(Convolution)

卷积的本质不是“滑窗”,而是局部连接 + 权值共享

对单通道输入,卷积可写为:
Y k ( i , j ) = ∑ c ∑ u , v W k , c ( u , v ) X c ( i + u , j + v ) + b k Y_{k}(i,j) = \sum_{c}\sum_{u,v} W_{k,c}(u,v)\,X_c(i+u,j+v) + b_kYk(i,j)=cu,vWk,c(u,v)Xc(i+u,j+v)+bk
LeNet 中的特点:

  • 小卷积核(5 × 5 5\times55×5
  • 通道数逐步增加
  • 没有 padding(尺寸会缩小)
3.下采样层(Pooling)

LeNet 使用的是平均池化(Average Pooling)
Y ( i , j ) = 1 ∣ R ∣ ∑ ( u , v ) ∈ R X ( u , v ) Y(i,j) = \frac{1}{|R|}\sum_{(u,v)\in R} X(u,v)Y(i,j)=R1(u,v)RX(u,v)
这里和现代 CNN 有明显区别:

  • 没有 MaxPool
  • 平均池化 + 可学习参数(早期版本)

作用只有一个:降维 + 平移不变性

4.全连接层(Fully Connected)

经过两次 Conv + Pool 后,特征图被拉平成向量:
z = v e c ( X ) \mathbf{z} = \mathrm{vec}(X)z=vec(X)
再经过多层线性映射:
h = σ ( W z + b ) \mathbf{h} = \sigma(W\mathbf{z} + b)h=σ(Wz+b)
最终输出类别概率。

5.激活函数

LeNet 使用的是tanh / sigmoid
σ ( x ) = tanh ⁡ ( x ) \sigma(x) = \tanh(x)σ(x)=tanh(x)
这是时代局限:

  • ReLU 当时还没流行
  • 梯度消失问题在那时并未被系统性认识

创新点

1. LeNet 第一次完整定义了 CNN 的结构模板
  • 局部感受野
  • 权值共享
  • 多层特征抽象
  • 端到端训练
2. 从“人工特征”到“特征学习”

LeNet 的核心思想不是网络多深,而是特征不再由人设计,而是由数据驱动学习得到

这是现代深度学习的思想源头

代码实现

importtorchfrombyzh.ai.BtrainerimportB_Trainerfrombyzh.ai.BdataimportB_Download_MNIST,b_get_dataloader_from_tensorfrombyzh.ai.Bmodel.study_cnnimportB_LeNet5_Paperfrombyzh.ai.Butilsimportb_get_device##### data #####downloader=B_Download_MNIST(save_dir='D:/study_cnn/datasets/MNIST')data_dict=downloader.get_data()X_train=data_dict['X_train_standard']y_train=data_dict['y_train']X_test=data_dict['X_test_standard']y_test=data_dict['y_test']num_classes=data_dict['num_classes']train_dataloader,val_dataloader=b_get_dataloader_from_tensor(X_train,y_train,X_test,y_test)##### model #####model=B_LeNet5_Paper(num_classes=num_classes)##### else #####optimizer=torch.optim.Adam(model.parameters(),lr=1e-3)criterion=torch.nn.CrossEntropyLoss()device=b_get_device(use_idle_gpu=True)epochs=10##### trainer #####trainer=B_Trainer(model=model,optimizer=optimizer,criterion=criterion,train_loader=train_dataloader,val_loader=val_dataloader,device=device)if__name__=='__main__':trainer.train_eval_s(epochs=epochs)
importtorchimporttorch.nnasnnimporttorch.nn.functionalasFclassScaledTanh(nn.Module):""" 原论文常用的缩放版 tanh f(x) = 1.7159 * tanh((2/3) * x) """def__init__(self,A=1.7159,S=2.0/3.0):super().__init__()self.A=A self.S=Sdefforward(self,x):returnself.A*torch.tanh(self.S*x)classSubsamplingLayer(nn.Module):""" 原论文的 S 层(subsampling layer) 不是纯 AvgPool,而是: y = a * avgpool(x) + b 其中 a,b 对每个通道(feature map)可学习 输入: (N, C, H, W) 输出: (N, C, H/2, W/2) (当 kernel=2, stride=2) """def__init__(self,channels,kernel_size=2,stride=2):super().__init__()# 平均池化:负责下采样self.pool=nn.AvgPool2d(kernel_size=kernel_size,stride=stride)# 每个通道一个可学习的缩放系数 a 和偏置 b# 形状是 (C,) ,forward 时会 reshape 成 (1,C,1,1) 以便广播self.a=nn.Parameter(torch.ones(channels))self.b=nn.Parameter(torch.zeros(channels))defforward(self,x):# 先做下采样x=self.pool(x)# (N,C,H/2,W/2)# 做通道级的仿射变换:a * x + ba=self.a.view(1,-1,1,1)b=self.b.view(1,-1,1,1)x=a*x+breturnxclassB_LeNet5_Paper(nn.Module):""" 输入: (N, 1, 32, 32) 注意: - 这里把 S2/S4 改成论文里的 subsampling(avgpool + 可学习 a,b) - 激活用论文常用的 scaled tanh - C3 的“部分连接表”(partial connectivity) 这里仍使用现代全连接卷积(更常见的复现做法) 如果你要严格复刻 C3 的连接表,我也可以再给一版 工作流(形状): (N,1,32,32) -> conv5x5 -> (N,6,28,28) [可学习] -> tanh -> paper-sub -> (N,6,14,14) [可学习 a,b] -> conv5x5 -> (N,16,10,10) [可学习] -> tanh -> paper-sub -> (N,16,5,5) [可学习 a,b] -> conv5x5 -> (N,120,1,1) [可学习] -> tanh -> flatten -> (N,120) -> linear -> (N,84) [可学习] -> tanh -> linear -> (N,10) [可学习] """def__init__(self,num_classes=10):super().__init__()# 论文风格激活self.act=ScaledTanh()# C1: 1 -> 6self.conv1=nn.Conv2d(1,6,kernel_size=5,stride=1,padding=0)# S2: 6 通道的论文风格下采样(avgpool + 可学习 a,b)# 是否在 S 层后再接激活:这里先不接(更保守、也更常见)self.pool2=SubsamplingLayer(channels=6,kernel_size=2,stride=2)# C3: 6 -> 16self.conv3=nn.Conv2d(6,16,kernel_size=5,stride=1,padding=0)# S4: 16 通道的论文风格下采样self.pool4=SubsamplingLayer(channels=16,kernel_size=2,stride=2)# C5: 16 -> 120,输入正好是 5x5,所以输出 1x1self.conv5=nn.Conv2d(16,120,kernel_size=5,stride=1,padding=0)# F6self.fc6=nn.Linear(120,84)# F7self.fc7=nn.Linear(84,num_classes)defforward(self,x):# 兼容 MNIST 原始 28x28:先 pad 到 32x32ifx.shape[-2:]==(28,28):x=F.pad(x,(2,2,2,2))# left,right,top,bottom# conv + actx=self.conv1(x)# (N,6,28,28)x=self.act(x)# poolx=self.pool2(x)# (N,6,14,14)# conv + actx=self.conv3(x)# (N,16,10,10)x=self.act(x)# poolx=self.pool4(x)# (N,16,5,5)# conv + actx=self.conv5(x)# (N,120,1,1)x=self.act(x)# flattenx=x.view(x.size(0),-1)# (N,120)# linear + actx=self.fc6(x)# (N,84)x=self.act(x)# linearlogits=self.fc7(x)# (N,10)returnlogitsif__name__=='__main__':net=B_LeNet5_Paper(num_classes=2)a=torch.randn(50,1,28,28)result=net(a)print(result.shape)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 21:31:33

Qwen-Turbo-BF16在心理咨询中的应用探索

Qwen-Turbo-BF16在心理咨询中的应用探索 最近跟几位做心理服务的朋友聊天,他们都在感叹,现在寻求心理支持的人越来越多,但专业的心理咨询师数量有限,而且很多人因为时间、地点或者费用问题,很难获得及时、持续的支持。…

作者头像 李华
网站建设 2026/6/9 22:19:53

Nano-Banana Studio企业级应用:SpringBoot+MyBatis服装拆解系统开发

Nano-Banana Studio企业级应用:SpringBootMyBatis服装拆解系统开发 1. 从像素级拆解到企业级系统:为什么需要一套专属工具 最近在设计团队里,我常看到同事把一张模特穿着新款连衣裙的照片拖进Nano Banana Pro,输入提示词&#x…

作者头像 李华
网站建设 2026/6/5 20:57:37

基于灵毓秀-牧神-造相Z-Turbo的智能体开发

基于灵毓秀-牧神-造相Z-Turbo的智能体开发 1. 当AI角色开始自己做决定 你有没有想过,如果一个能画出灵毓秀的AI,不只是听你指令画画,而是能主动思考“该画什么”、“怎么画更好”、“用户可能还想要什么”,会是什么样子&#xf…

作者头像 李华
网站建设 2026/6/10 12:15:06

Pi0视觉-语言-动作模型教程:错误指令检测与安全动作熔断机制

Pi0视觉-语言-动作模型教程:错误指令检测与安全动作熔断机制 1. 什么是Pi0?——给机器人装上“眼睛、耳朵和肌肉”的新思路 你有没有想过,让机器人真正听懂人话、看懂环境、再稳稳执行动作?不是靠一堆预设脚本,而是像…

作者头像 李华