清湖做网站的,最美情侣免费观看,上海的网站名,国内网页设计公司前十名[深度学习网络从入门到入土] lenet 个人导航 知乎#xff1a;https://www.zhihu.com/people/byzh_rc CSDN#xff1a;https://blog.csdn.net/qq_54636039 注#xff1a;本文仅对所述内容做了框架性引导#xff0c;具体细节可查询其余相关资料or源码 参考文章#xff…[深度学习网络从入门到入土] lenet个人导航知乎https://www.zhihu.com/people/byzh_rcCSDNhttps://blog.csdn.net/qq_54636039注本文仅对所述内容做了框架性引导具体细节可查询其余相关资料or源码参考文章各方资料文章目录[深度学习网络从入门到入土] lenet个人导航参考资料背景架构(公式)1.输入层2.卷积层Convolution3.下采样层Pooling4.全连接层Fully Connected5.激活函数创新点1. LeNet 第一次完整定义了 CNN 的结构模板2. 从“人工特征”到“特征学习”代码实现参考资料Gradient-based learning applied to document recognition背景在 LeNet 出现之前图像任务基本是“手工特征 传统分类器”边缘检测(Edge Detection)人工特征(HOG / SIFT)降维PCA / 投影LDA最后接 SVM / KNN这些方法有一个致命问题特征是人为设计的模型本身不会“学特征”LeNet第一次系统性地证明了神经网络可以端到端地从原始图像中学习特征并完成分类手写数字识别MNIST支票 / 邮政编码识别架构(公式)1.输入层输入通常为灰度图像(channel1)X ∈ R 1 × 32 × 32 X \in \mathbb{R}^{1 \times 32 \times 32}X∈R1×32×32MNIST 原始是28 × 28 28\times2828×28- LeNet 里通常padding 到32 × 32 32\times3232×322.卷积层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(iu,jv) b_kYk​(i,j)c∑​u,v∑​Wk,c​(u,v)Xc​(iu,jv)bk​LeNet 中的特点小卷积核5 × 5 5\times55×5通道数逐步增加没有 padding尺寸会缩小3.下采样层PoolingLeNet 使用的是平均池化Average PoolingY ( 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)∣R∣1​(u,v)∈R∑​X(u,v)这里和现代 CNN 有明显区别没有 MaxPool平均池化 可学习参数早期版本作用只有一个降维 平移不变性4.全连接层Fully Connected经过两次 Conv Pool 后特征图被拉平成向量z v e c ( X ) \mathbf{z} \mathrm{vec}(X)zvec(X)再经过多层线性映射h σ ( W z b ) \mathbf{h} \sigma(W\mathbf{z} b)hσ(Wzb)最终输出类别概率。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 #####downloaderB_Download_MNIST(save_dirD:/study_cnn/datasets/MNIST)data_dictdownloader.get_data()X_traindata_dict[X_train_standard]y_traindata_dict[y_train]X_testdata_dict[X_test_standard]y_testdata_dict[y_test]num_classesdata_dict[num_classes]train_dataloader,val_dataloaderb_get_dataloader_from_tensor(X_train,y_train,X_test,y_test)##### model #####modelB_LeNet5_Paper(num_classesnum_classes)##### else #####optimizertorch.optim.Adam(model.parameters(),lr1e-3)criteriontorch.nn.CrossEntropyLoss()deviceb_get_device(use_idle_gpuTrue)epochs10##### trainer #####trainerB_Trainer(modelmodel,optimizeroptimizer,criterioncriterion,train_loadertrain_dataloader,val_loaderval_dataloader,devicedevice)if__name____main__:trainer.train_eval_s(epochsepochs)importtorchimporttorch.nnasnnimporttorch.nn.functionalasFclassScaledTanh(nn.Module): 原论文常用的缩放版 tanh f(x) 1.7159 * tanh((2/3) * x) def__init__(self,A1.7159,S2.0/3.0):super().__init__()self.AA self.SSdefforward(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) (当 kernel2, stride2) def__init__(self,channels,kernel_size2,stride2):super().__init__()# 平均池化负责下采样self.poolnn.AvgPool2d(kernel_sizekernel_size,stridestride)# 每个通道一个可学习的缩放系数 a 和偏置 b# 形状是 (C,) forward 时会 reshape 成 (1,C,1,1) 以便广播self.ann.Parameter(torch.ones(channels))self.bnn.Parameter(torch.zeros(channels))defforward(self,x):# 先做下采样xself.pool(x)# (N,C,H/2,W/2)# 做通道级的仿射变换a * x baself.a.view(1,-1,1,1)bself.b.view(1,-1,1,1)xa*xbreturnxclassB_LeNet5_Paper(nn.Module): 输入: (N, 1, 32, 32) 注意 - 这里把 S2/S4 改成论文里的 subsamplingavgpool 可学习 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_classes10):super().__init__()# 论文风格激活self.actScaledTanh()# C1: 1 - 6self.conv1nn.Conv2d(1,6,kernel_size5,stride1,padding0)# S2: 6 通道的论文风格下采样avgpool 可学习 a,b# 是否在 S 层后再接激活这里先不接更保守、也更常见self.pool2SubsamplingLayer(channels6,kernel_size2,stride2)# C3: 6 - 16self.conv3nn.Conv2d(6,16,kernel_size5,stride1,padding0)# S4: 16 通道的论文风格下采样self.pool4SubsamplingLayer(channels16,kernel_size2,stride2)# C5: 16 - 120输入正好是 5x5所以输出 1x1self.conv5nn.Conv2d(16,120,kernel_size5,stride1,padding0)# F6self.fc6nn.Linear(120,84)# F7self.fc7nn.Linear(84,num_classes)defforward(self,x):# 兼容 MNIST 原始 28x28先 pad 到 32x32ifx.shape[-2:](28,28):xF.pad(x,(2,2,2,2))# left,right,top,bottom# conv actxself.conv1(x)# (N,6,28,28)xself.act(x)# poolxself.pool2(x)# (N,6,14,14)# conv actxself.conv3(x)# (N,16,10,10)xself.act(x)# poolxself.pool4(x)# (N,16,5,5)# conv actxself.conv5(x)# (N,120,1,1)xself.act(x)# flattenxx.view(x.size(0),-1)# (N,120)# linear actxself.fc6(x)# (N,84)xself.act(x)# linearlogitsself.fc7(x)# (N,10)returnlogitsif__name____main__:netB_LeNet5_Paper(num_classes2)atorch.randn(50,1,28,28)resultnet(a)print(result.shape)