ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AlexNet核心解析:ReLU与Dropout如何开启深度学习革命

AlexNet核心解析:ReLU与Dropout如何开启深度学习革命 2012年那会儿整个计算机视觉圈子都在用SIFT、HOG这些手工特征做图像识别顶多玩到几万张图片的小数据集。ImageNet竞赛已经办了两年最好成绩的错误率也高得吓人。直到AlexNet横空出世直接把ImageNet分类错误率从26.2%砍到15.3%比第二名低了将近11个百分点所有人都在问这人到底做了什么答案其实就藏在它的名字里——深度卷积神经网络加上两个如今看来稀松平常、当时却堪称激进的操作ReLU激活函数和Dropout正则化。这篇博客就带你把这些关键技术点掰开揉碎看看它们是怎么一步步成为现代深度学习标配的。这篇文章适合所有对深度学习原理感兴趣的人不管是刚看完吴恩达课程想弄懂经典模型细节的初学者还是已经在用PyTorch跑项目、想回头补一补基本功的开发者。我会从AlexNet的设计思路讲起聊清楚ReLU为什么能解决梯度消失问题、Dropout为什么能抑制过拟合再讲GPU并行、LRN、重叠池化这些配套设计背后的考量最后给出一个可以照着跑的PyTorch实现和踩坑记录。读完之后你不光能背出AlexNet的网络结构更能理解那些看似不起眼的细节设计到底解决了什么实际问题。1. AlexNet的整体设计思路赌一把深度和宽度1.1 2012年那个时间节点深度学习到底难在哪里在聊AlexNet的具体结构之前得先把当时的技术背景交代清楚。2006年Hinton提出深度信念网络的时候深度学习这个概念已经复活了但真正能跑的模型都非常小因为几个致命问题卡在那里算力不够当时的GPU虽然可以用来做通用计算但显存普遍只有1GB上下一个稍微大点的卷积网络根本塞不进去。数据不够ImageNet这种百万级标注数据集刚发布没多久大家习惯的还是CIFAR-10这种6万张图片的小规模数据。训练不稳定深层网络用传统sigmoid激活函数训练时误差信号传到前面几层就衰减得差不多了梯度消失问题严重网络根本深不下去。过拟合严重模型参数比训练样本还多的时候训练集上跑得很好验证集上直接崩。AlexNet的做法可以概括成一句话在算力勉强够用、数据勉强够用的边缘条件上把网络的深度和宽度都推上一个量级然后用一系列工程技巧把训练不稳定和过拟合的问题“压”下去。它的结构有8层——5个卷积层加3个全连接层参数量约6000万比之前的LeNet大了好几个数量级。1.2 网络结构拆解8层怎么撑起百万级图像分类我先把AlexNet的完整结构用表格列出来后面再逐个部件分析。这张表我一直视为经典因为每一行都对应着一个设计决策层名称输出尺寸卷积核/池化配置激活函数备注输入层224x224x3--原始图像裁剪/缩放Conv155x55x9611x11, stride4, pad2ReLU96个卷积核Pool127x27x963x3, stride2重叠池化-后接LRNConv227x27x2565x5, pad2ReLU256个卷积核Pool213x13x2563x3, stride2-后接LRNConv313x13x3843x3, pad1ReLU384个卷积核Conv413x13x3843x3, pad1ReLU384个卷积核Conv513x13x2563x3, pad1ReLU256个卷积核Pool36x6x2563x3, stride2-不加LRNFC64096全连接ReLU后接DropoutFC74096全连接ReLU后接DropoutFC81000全连接SoftmaxImageNet的1000类注意Conv1的卷积核是11x11步长是4这说明第一层就用了大感受野快速下采样目的是在图像分辨率还比较高的阶段尽快提取全局轮廓信息。后面几层逐步减小卷积核尺寸、增加通道数则是在捕捉更精细的局部纹理。这个“大核起步、小核渐进、通道数递增”的思路后来成为CNN设计的通用范式。补充说明一下这张表里所有尺寸都假设输入是224x224但原文在实验部分其实用了多种尺寸的裁剪做数据增强比如把256x256的图片随机裁剪出224x224的块。不同实现里Conv1的pad参数略有出入因为原始论文在GPU分卡的部分留了一行说明实际代码里pad可以是2也可以不补。这里用的是最主流的实现方式。1.3 为什么要把网络放在“两块GPU”上训练AlexNet训练时用了两块GTX 580每块只有3GB显存这在今天是无法想象的小。模型并行——也就是把60万参数分到两张卡上卷积层在两卡之间交替通信全连接层则彻底分开——是为了应对显存瓶颈的无奈之举但也带来一个附加好处网络被强制切分成两个分支某种程度上相当于做了多网络集成。这个设计的代价是当时的CUDA代码非常难写数据对齐、通信开销、同步问题一个接一个。后来随着K40、Titan X这些大显存GPU普及单卡就能装下整个模型这种双分支结构就不再是必需品。现代PyTorch实现里你只需要用nn.DataParallel或者直接不用逻辑上把它当成一个整体网络就行。但理解这段历史很重要——因为“模型太大放不进显存”的问题并没有消失只是从单机双卡变成了分布式多机多卡。2. ReLU激活函数一个简单函数如何解决梯度消失2.1 sigmoid和tanh为什么撑不起深层网络传统神经网络在AlexNet之前基本都用sigmoid或tanh作为激活函数。这两个函数的曲线都是S型输出范围被压缩在0到1sigmoid或者-1到1tanh之间好处是数学性质好、导数容易求坏处非常致命饱和区梯度趋近于零。拿sigmoid举例它的导数公式是σ(x) σ(x)(1 - σ(x))最大值也只有0.25。你想一下一个几十层的网络误差从输出层往回传每通过一层激活函数梯度就乘一次小于1的数越乘越小传到前几层基本就是0。这意味着网络前面的卷积层根本学不到东西只能随机初始化后“躺在那里”。这还不算完sigmoid的输出均值不是0导致上一层传给下一层的信号产生偏移训练时收敛缓慢到让人崩溃。我当时第一次用纯sigmoid堆一个5层以上的网络时观察到训练loss在前几百个迭代几乎纹丝不动当时还以为是学习率调得不对后来才明白是梯度消失把前几层“锁死”了。2.2 ReLU为什么能救场正区间梯度恒定为1ReLU的数学形式特别简单f(x) max(0, x)导数在正区间恒为1负区间为0。这个“恒为1”意味着什么呢误差反传时只要某个神经元的输入为正梯度就能原封不动地传到下一层不会像sigmoid那样每层衰减。理论上只要网络里的每个神经元在反向传播时都是“激活”状态梯度就可以穿过整个网络解决梯度消失问题。当然实际训练中会有部分神经元输出为0Dead ReLU问题后面细说但整体上反向传播的信号强度比sigmoid时代提高了几个数量级。ReLU带来的另一个好处是“稀疏激活”。sigmoid和tanh几乎是处处非零的大部分神经元都在输出一个非饱和值计算量大且信息冗余。ReLU则会把负区间全部置零让网络自动学出一种稀疏表示——每个样本只激活一小部分神经元。这在直觉上很像生物神经元的“发放”机制不是所有神经元都同时兴奋只有跟当前输入相关的神经元才被激活。论文里也明确提到ReLU让训练速度比tanh快了好几倍我当时在自己数据集上实测同样的网络结构ReLU在第三个epoch就能达到tanh训练十几个epoch的准确率。2.3 ReLU的代价你早晚会撞见Dead ReLUReLU这么好用副作用也特别明显某个神经元一旦在训练中被推入负区间它的导数就是0之后再也没办法恢复。梯度更新永远不会让它重新变正于是这个神经元就“死”了——无论输入是什么它永远输出0。这个问题在训练初期特别容易发生尤其是学习率设太大的时候。一个常见的现象是loss在某个迭代突然变成NaN或者训练到一半准确率骤降查来查去发现是大量神经元死了模型表达能力断崖式下跌。解决办法有几个都是后来实践中摸索出来的调小学习率这个是首选。学习率太大权重更新幅度太猛容易一下把神经元推到负区间。用Adam优化器配合warmup策略可以显著降低Dead ReLU的概率。用Leaky ReLU或PReLU替代Leaky ReLU在负区间给一个很小的斜率比如0.01梯度不为0神经元不会彻底死亡。PReLU则把这个斜率也当作可学习参数让网络自己去学。控制初始化尽量让权重初始值使得ReLU的输入落在正区间的概率大一些。Kaiming初始化就是专门针对ReLU设计的用均匀分布或正态分布方差跟上一层神经元数量有关能保证激活值在前向传播和反向传播中的方差基本稳定。注意AlexNet原文用的是普通ReLU当时并没有解决Dead ReLU的成熟方案但它在实践中发现问题不大原因在于Dropout和正则化的存在让权重更新相对温和。今天你在项目里用ReLU时最好一开始就配上Kaiming初始化和较小学习率等熟练了再考虑PReLU这些变体。3. Dropout正则化为什么“随机丢弃”能提升泛化能力3.1 从“多模型集成”的视角理解Dropout过拟合是深度学习一直以来的老问题在AlexNet那种6000万参数对上120万训练样本的场景下尤其严重。全连接层占了绝大多数参数它们可以轻松“记住”整个训练集但这没有任何泛化意义。Dropout的思路特别巧妙训练时随机丢弃一部分神经元连同它们的连接让每次前向传播都变成一个“瘦身”后的子网络。因为丢弃是随机的每个batch训练的模型结构都不一样。假设一个层有n个神经元开启Dropout后每次训练等效于从2^n种子网络中随机采样一种来更新参数。等训练结束时整个网络相当于做了大量不同子网络的隐式集成泛化能力自然更强。我在实践中喜欢用一个比喻Dropout就像团队合作时随机让一些成员休假剩下的成员被迫把活儿全扛起来。这样每个人都会变得更能打而不是过度依赖某个特定成员。神经网络也是这个道理——它被迫学到更加鲁棒的特征不依赖某一个神经元的输出。3.2 Dropout的两个关键参数概率p和推理缩放标准Dropout有一个超参数p表示神经元被保留的概率。AlexNet原文用的是p0.5并且在两个全连接层FC6和FC7后面都加了Dropout。作者在论文里的解释很直接p0.5对全连接层来说在多种任务和网络结构上都是接近最优的选择因为0.5的随机组合生成空间最大——每个神经元都有50%的概率出现组合数量最大。但这里有一个很多人容易忽略的细节推理时Dropout必须关闭。如果你在测试模型时还开着Dropout神经元的输出会被随机置零模型的预测结果每次都不一样乱套了。正确的做法是推理时让所有神经元都参与计算但为了保持期望输出一致每个神经元的输出要乘以保留概率p。举个例子训练时某个神经元输出值为x以概率p被保留、以概率1-p被置0那它的期望输出是px。推理时如果你不做任何处理神经元的输出是x比训练时大了一个系数。所以要么在推理时直接乘p要么在训练时将输出除p这种叫inverted dropout现代深度学习框架默认用这种它把缩放因子融到训练阶段推理时就完全不用管。PyTorch中的nn.Dropout(p)实际上执行的就是inverted dropout训练时它将保留的神经元输出除以p推理时不做任何操作。3.3 怎么设Dropout的位置和比例在实际工程中Dropout并不是随便加在任意层都有效果的。我总结了几条经验优先加在全连接层因为全连接层参数量最大、最容易过拟合。AlexNet只在两个全连接层加Dropout卷积层没加这是合理的。今天很多ResNet的实现也在最后的全连接或全局池化之后加Dropout。卷积层通常配合BatchNorm使用BatchNorm本身有正则化效果再加Dropout效果未必更好甚至可能互相干扰。我在一些分割任务里试过在卷积层加Dropout结果要么没什么提升要么训练变慢。p值不要碰得太高常见设置是0.3到0.5。p0.5是一把标准尺子但如果你发现过拟合特别严重训练集准确率接近100%验证集差很多可以加大丢弃比例如果模型欠拟合或训练不稳定则应该减小。动态Dropout现在也有人尝试训练早期用较小的p后期逐渐增大类似学习率warmup的反向操作在部分任务上有效果但AlexNet时代没有这个概念属于后人优化。3.4 Dropout和L2正则化的组合拳AlexNet在训练中还用了权重衰减weight decay也就是L2正则化系数设的是0.0005。论文解释这个很小的权重衰减对模型训练很重要——不光是为了正则化更是为了让权重更新保持在合适的“量级”内。L2正则化给损失函数加了所有权重的平方和等效于在每次参数更新时做一次“权重收缩”。它和Dropout的机制不同Dropout是通过随机化结构来降低过拟合L2是通过限制权重大小来降低模型复杂度。两者配合使用时Dropout负责破坏神经元间的协同适应co-adaptationL2负责控制权重的整体尺度。在AlexNet那个参数规模下少了任何一个训练集上都会迅速跑飞。4. 那些不常被提起的技术细节LRN、重叠池化、数据增强4.1 LRN局部响应归一化为了侧抑制但今天已经很少用了AlexNet里还有一个专门设计的模块叫Local Response Normalization局部响应归一化放在Conv1和Conv2之后、激活函数之后。LRN做的事情是模拟生物神经元的侧抑制现象对同一个位置上不同卷积核的输出做归一化让响应比较大的值相对更突出响应比较小的值被压下去。公式是这样的b(i, j) a(i, j) / (k α * Σ(a(n, j)^2))^β其中Σ是在同一空间位置、相邻的n个通道上求和。AlexNet设置k2n5α0.0001β0.75。它做的是跨通道的局部归一化而不是空间上的归一化。当时作者的意图是让网络在多个卷积核竞争时每个位置的输出更有区分度。但后来大家逐渐发现LRN带来的提升非常有限甚至在某些实现里根本不带来提升。BatchNorm出现之后LRN基本被淘汰了因为BatchNorm在归一化效果和训练稳定性上全面优于LRN。我现在做实验时基本不会用LRN但如果你想严格复现AlexNet的原始结果还是建议保留毕竟论文的实验设置里包含了它。4.2 重叠池化stride小于kernel size的PoolingAlexNet用的池化是max pooling但它的特殊之处在于池化窗口是3x3步长却是2。这意味着相邻的池化窗口有1像素的重叠这跟当时主流的“池化窗口等于步长”比如2x2窗口、步长2完全不重叠做法不一样。作者从实验中观察到重叠池化能稍微降低错误率而且理论上可以有效避免过拟合。重叠池化相当于让相邻区域的信息得到一定程度的混合增加了特征的连续性同时因为窗口更大每个池化结果能看到更多上下文。代价是计算量略增但跟整个网络的计算量比可以忽略不计。今天大部分CNN模型还是用重叠池化或者干脆改用stride2的卷积来下采样pooling层已经逐渐退居次要地位但了解这段历史能帮你理解为什么很多老模型会有这种“看起来奇怪”的参数设置。4.3 数据增强把120万张图变成几亿张AlexNet参数有6000万训练集只有120万张图如果不对数据进行扩充过拟合几乎是必然的。论文里用了两招数据增强每一招都是在“不改语义”的前提下制造更多训练样本随机裁剪和水平翻转训练时从256x256的图像中随机裁剪出224x224的区域并随机做水平翻转。这就把一张图变成了很多张语义相同但像素不同的训练样本。预测时再对图像的四个角加中心做5次224x224裁剪以及它们各自的水平翻转版本共10张把10次预测结果取平均作为最终输出。这种方式叫“测试时增强”test-time augmentation能明显提升预测稳定性和准确率。PCA颜色抖动对图像的RGB三通道做PCA分解沿主成分方向添加一个小的随机扰动量模拟光照和颜色变化。AlexNet的RGB通道是直接使用ImageNet原始图像的不像今天很多模型先做标准化所以颜色扰动对训练数据的影响比今天更直接。这两招今天的项目里仍然非常常用。特别是随机裁剪和随机翻转几乎是图像分类任务的标配PCA颜色抖动用得相对少主要是因为现在大家喜欢用更复杂的颜色扰动方法如RandAugment、Cutout等但思想内核是一样的。5. 从头用PyTorch实现AlexNet可以照着抄的代码和训练配置5.1 一个简洁但完整的AlexNet实现我之前在PyTorch里复现AlexNet时将网络定义封装成一个模块。因为原始论文的双GPU设计在现代框架里不是必需的所以下面这个实现是“单卡逻辑”跟论文在数学上是等价的import torch import torch.nn as nn class AlexNet(nn.Module): def __init__(self, num_classes1000, dropout_prob0.5): super(AlexNet, self).__init__() # 特征提取部分5个卷积层 self.features nn.Sequential( # Conv111x11卷积核步长4输出96通道 nn.Conv2d(3, 96, kernel_size11, stride4, padding2), nn.ReLU(inplaceTrue), nn.MaxPool2d(kernel_size3, stride2), # 重叠池化 nn.LocalResponseNorm(size5, alpha0.0001, beta0.75, k2), # LRN # Conv25x5卷积核padding 2输出256通道 nn.Conv2d(96, 256, kernel_size5, stride1, padding2), nn.ReLU(inplaceTrue), nn.MaxPool2d(kernel_size3, stride2), nn.LocalResponseNorm(size5, alpha0.0001, beta0.75, k2), # Conv33x3卷积核输出384通道 nn.Conv2d(256, 384, kernel_size3, stride1, padding1), nn.ReLU(inplaceTrue), # Conv43x3卷积核输出384通道 nn.Conv2d(384, 384, kernel_size3, stride1, padding1), nn.ReLU(inplaceTrue), # Conv53x3卷积核输出256通道 nn.Conv2d(384, 256, kernel_size3, stride1, padding1), nn.ReLU(inplaceTrue), nn.MaxPool2d(kernel_size3, stride2), ) # 分类器部分3个全连接层 Dropout self.classifier nn.Sequential( nn.Dropout(pdropout_prob), nn.Linear(256 * 6 * 6, 4096), nn.ReLU(inplaceTrue), nn.Dropout(pdropout_prob), nn.Linear(4096, 4096), nn.ReLU(inplaceTrue), nn.Linear(4096, num_classes), ) # 初始化权重这个对训练稳定性很关键 self._initialize_weights() def _initialize_weights(self): for m in self.modules(): if isinstance(m, nn.Conv2d): nn.init.kaiming_normal_(m.weight, modefan_in, nonlinearityrelu) if m.bias is not None: nn.init.constant_(m.bias, 0) elif isinstance(m, nn.Linear): nn.init.kaiming_normal_(m.weight, modefan_in, nonlinearityrelu) nn.init.constant_(m.bias, 0) def forward(self, x): x self.features(x) x torch.flatten(x, 1) x self.classifier(x) return x这里我用nn.LocalResponseNorm模拟LRN它的参数跟论文里的设置一一对应。如果你不想用LRN也可以直接注释掉现代实现里很多都不带LRN了。权重初始化用的是Kaiming初始化这是针对ReLU专门设计的初始化方法也是后来从AlexNet实践经验中总结出来的标准配置。5.2 训练时需要注意的配置和参数用上面的代码训练时我踩过的坑和总结出的经验如下输入尺寸别搞错上面代码在forward里默认输入是224x224如果你的输入不是这个尺寸特征图经过三次最大池化后flatten出来的维度就不是256x6x6会报错。所以要么在输入前做resize要么根据输入尺寸动态计算全连接层输入维度。我建议在数据加载时统一resize到224x224。学习率起点建议0.01原文用SGD momentum0.9 weight_decay0.0005学习率从0.01开始在训练中手动衰减。这个配置对AlexNet是验证过的。如果你换Adam建议把初始学习率降到0.001以下否则很容易出现训练初期loss直接冲上天的现象。Batch Size的选择原文用128放到今天来说如果你的显存不够也可以减半到64甚至32。但注意batch size变小后梯度噪声变大训练稳定性会变差。我一般会配合学习率做线性缩放batch size减半学习率也乘以0.8或0.5。验证时记得关DropoutPyTorch的model.eval()会自动关闭Dropout和BatchNorm的训练状态所以验证时一定要调用model.eval()训练时调用model.train()。我见过不止一次有人忘了写eval验证准确率忽高忽低还以为是模型有问题。测试时增强跟AlexNet一样预测阶段做多次裁剪然后取平均能带来1%-2%的准确率提升。代码上可以用torchvision.transforms.FiveCrop和TenCrop实现非常简单。5.3 训练资源和时间参考AlexNet在2012年用两块GTX 580训练了大约5到6天这放在今天来看效率低得感人。我拿一张RTX 3060在CIFAR-10比ImageNet小得多上跑一个简化版AlexNet大约30到40分钟能跑完60个epoch。在ImageNet上做完整训练即使有现代GPU加速和优化库也需要几天时间。因此如果是学习用途强烈建议先用CIFAR-10或猫狗分类这种小数据集练手把网络结构和训练流程跑通再去挑战ImageNet级别。6. 复现AlexNet时我踩过的坑一份实战排查记录6.1 训练Loss震荡直到NaN八成是学习率太大我第一次用PyTorch复现AlexNet时没有用它原始的SGDmomentum配置而是直接上了Adam学习率默认的0.001结果前几十个step倒还正常后面突然就开始震荡然后loss变成NaN。排查了很久发现是几个因素叠加造成的学习率对Adam来说还是偏大、ReLU死了不少神经元、权重初始化不规范。解决办法是三步走先把学习率调到0.0001然后换成Kaiming初始化最后加上梯度裁剪torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm5)。这样处理之后训练稳定多了。6.2 验证准确率上不去检查数据增强有没有做过头数据增强是AlexNet的核心技巧之一但“增强过头”也会反噬。我在做一个小数据集实验时把随机裁剪、随机旋转、颜色抖动全部拉满结果训练集loss降不下去验证集准确率也一直卡在低位。原因是随机旋转对某些类别比如数字识别里的6和9产生了语义混淆模型学不到稳定特征。我的经验是增强得跟着任务走分类任务里水平翻转一般安全垂直翻转要谨慎随机旋转尽量控制在小角度范围内。颜色抖动幅度也要适可而止AlexNet的PCA抖动幅度本身就设置得很温和。6.3 训练速度慢检查GPU利用率和DataLoader瓶颈如果你发现GPU利用率只有60%左右CPU却在满负荷跑大概率是DataLoader的num_workers设置太小。PyTorch的DataLoader默认num_workers0意味着数据加载在主进程里不能并行遇到图片解码比较慢时GPU只能干等。我个人的配置经验是num_workers设为CPU核心数的一半到三分之二同时把pin_memoryTrue打开在GPU训练时这能把数据从CPU内存搬到GPU显存的过程变得更快。另外如果磁盘IO是瓶颈可以考虑把数据先打包成LMDB或TFRecord格式减少大量小文件读取的开销。6.4 不同框架对LRN实现有差异复现结果对不上如果你拿PyTorch复现出来的结果跟Caffe原版对不上不要奇怪LRN的实现细节在各框架之间有细微差别。现代PyTorch的LocalResponseNorm默认参数是size5, alpha0.0001, beta0.75, k2基本上和论文一致但如果你用老版本TensorFlow的LRN可能需要额外设置bias参数对应公式里的k。如果追求极致复现我建议干脆脱离LRN只保留那些核心组件ReLU、Dropout、重叠池化做出来的准确率其实大同小异。6.5 推理阶段的“永恒疑问”要不要再做一次随机裁剪很多人训练时做了随机裁剪测试时却直接把图像resize到224x224就送入模型准确率比训练时还低于是怀疑模型没有收敛。其实不是模型问题而是训练和测试的分布不一致。AlexNet的解决方案是测试时也做多次裁剪取平均。你的模型在训练时见过各种随机裁剪的图像但测试时只给了完整的resize图这对卷积网络来说也是一个有效的输入但测试时增强多裁剪是稳定提升精度的标准手段。如果你不想写复杂的测试增强代码用torchvision.transforms.Compose组合Resize、CenterCrop等基础变换就能实现中心裁剪。稍复杂一点的FiveCrop和TenCrop也足够满足绝大多数需求。7. AlexNet之后那些技术点的生命轨迹AlexNet不只带来了一个冠军模型更重要的是它验证了一套方法论的可行性——深度 ReLU Dropout 大数据 GPU加速可以组合出远超传统方法的效果。这个“配方”在后续几年里被反复验证和优化VGG把大卷积核替换成连续的小卷积核3x3证明深度比宽度更重要。GoogLeNet引入Inception模块在相同计算量下做更宽更深的特征提取。ResNet用残差连接彻底解决了超深网络的训练问题让上百层的网络成为现实。BatchNorm在激活之前做归一化大幅度缓解了内部协变量偏移问题让训练更稳定也慢慢替代了LRN。但一些AlexNet的核心思想至今仍然活跃。ReLU和它的变体Leaky ReLU、Swish、GELU依然是主流模型的激活函数Dropout在Transformer里也有了新的形态如Dropout在Attention层的应用甚至还有研究尝试用Dynamic Dropout根据神经元的重要性动态调整丢弃概率让正则化更智能。对我个人而言AlexNet的价值不在于那些具体的超参数而在于它展示了一种拆解问题的方式过拟合怎么办——加正则化、加数据增强训练不稳定怎么办——换激活函数、调初始化算力不够怎么办——模型并行、跨卡通信。每一个问题都有对应的工程解法而这些解法组合在一起才成就了深度学习的“寒武纪爆发”。如果你现在还在学习阶段我的建议是把AlexNet代码从头到尾手写一遍不要直接抄完跑个结果就完事。你要搞清楚每一层输出的shape变化亲手调一次超参数亲眼看一看loss曲线的形态变化然后在CIFAR-10这种小数据集上把它调到能work的状态。这个过程比你看十遍论文都管用。等你做完这一遍再去理解ResNet、Transformer这些更复杂的模型时你会发现自己对“为什么这样设计”有了真正的体感而不只是停留在背公式的层面。
返回列表