卷积:一种共享参数的“不全连接”
为什么要用卷积不使用卷积神经网络在传统全连接神经网络中若传入一张224*224*3的彩色图像直接连接到一个1000维的输出层参数量为224*224*3*10001000150528000巨大的参数量容易导致过拟合、大量消耗计算资源。卷积的优势1、 局部连接Local Connectivity每个输出只与输入的一个局部区域感受野相连2、参数共享Weight Sharing同一个卷积核在整个输入上滑动使用同一组参数3、平移不变性Translation Invariance无论目标出现在图像何处卷积都能检测到。使用11×11×3的卷积核64个通道则参数量仅为11×11×3×646423296远小于全连接。降采样降采样的目的是减少特征图的空间尺寸从而降低计算量、增大感受野、提取更抽象的高层特征。感受野感受野是指输出特征图上的某一个点在原始输入图像中所“看到”的区域大小。换句话说这个神经元的响应是由输入图像中多大一块区域决定的比如第一层卷积如 3×3 卷积核每个输出点的感受野是 3×3 像素第二层再用 3×3 卷积此时每个输出点的感受野变成 5×5 因为第二层的一个点依赖第一层的 3×3 区域而第一层每个点又对应输入的 3×3 随着网络加深感受野越来越大高层神经元能“看到”整张图像的更大范围。深度神经网络是分层特征提取器不同层学到不同层次的信息。以人脸识别为例第1层检测各种方向的边缘第2层组合边缘 → 检测眼角、鼻梁轮廓第5层组合五官 → 检测“人脸”区域最后分类层判断是“张三”还是“李四”。将高层特征“抽象”出来高级抽象特征如“有四条腿尾巴耳朵”才与“这是一只猫”直接相关低级特征如像素值对任务无直接意义抽象特征具有不变性无论猫在图像左边还是右边、大一点还是小一点高层特征都能稳定表示“猫”。降采样方法1、扩大步长O(I-K2P)/S1OOutput输出特征图边长IInput输入特征图边长K卷积核边长PpaddingSstride步长。如输入3*224*224卷积核11padding2Stride4卷积核数量为64则输出的卷积核边长为224-112*2/4155即输出为65*55*55。缺点步长过大容易丢失信息引入计算。2、池化Pooling1最大池化Max2平均池化Avg3适应性最大/平均池化AdaptiveMax/AvgPooling梯度消失、梯度爆炸在深层网络中反向传播时梯度通过链式法则连乘若权重普遍 1 → 梯度指数级衰减消失若权重普遍 1 → 梯度指数级增长爆炸。数据增广通过对训练数据进行合理变换增加多样性提升泛化能力。常见方法几何变换随机裁剪、旋转、翻转、缩放颜色扰动亮度、对比度、饱和度调整噪声注入高斯噪声、椒盐噪声AlexNet创新点使用ReLU激活替代sigmoid/tanh加速收敛缓解梯度消失Dropout训练时随机丢弃部分神经元如50%防止过拟合池化归一化首次大规模使用 GPU 加速。激活函数“饱和区”当输入很大正或负时函数的导数趋近于 0导致反向传播时梯度几乎为零参数无法有效更新。常用的激活函数合集详细版_常用激活函数-CSDN博客https://blog.csdn.net/caip12999203000/article/details/127067360sigmoid函数的导数在趋向 ∞ 或 -∞ 时导数为零出现正饱和/负饱和在饱和区无论输入怎么变输出几乎不变梯度≈0 → 梯度消失参数几乎无法更新。ReLU函数导数在x0时为1其余为0只要 x0梯度恒为 1反向传播畅通无阻 → 缓解梯度消失且运算比指数运算快得多。为什么说“避免负值饱和”Sigmoid/Tanh 在负值区域也会饱和梯度→0ReLU 在负值区域虽然梯度为 0但不是因为函数平缓而是人为截断且正区完全不饱和所以 ReLU 只在一半区域有梯度问题且是硬性的而 sigmoid/tanh 在大部分区域都有软性饱和问题。打个比方Sigmoid 像一辆油门踩到底也跑不动的老车饱和ReLU 像一辆开关控制的电动车关了就停x≤0开了就全力跑x0梯度1。那么如果ReLU负值区梯度为 0那是不是意味着模型“永久放弃”了一半的神经元并不是“永久放弃”而是在训练动态中大部分神经元仍有机会被激活并参与学习。ReLU 并不会“舍弃所有负值参数”——关键在“输入分布”ReLU 的输出是否为 0取决于它的输入即前一层的加权和 偏置而不是固定不变的。每个 ReLU 神经元的输入是zwxb如果 z0z0 → 激活梯度回传如果 z≤0z≤0 → 输出 0本次无梯度。但注意x 是变化的不同样本 w,b 也在训练中不断更新。在训练初期通过权重初始化让多数神经元处于“可激活”状态避免了“开局挂一半”。另外批量训练也能够天然地提供多样性。例如在一次参数更新中我们使用一个 batch比如 16 张图对于某个 ReLU 神经元图片 A 可能让它输出 0关闭图片 B 可能让它输出 5.2激活。反向传播时梯度是 batch 内所有样本的平均只要至少有一个样本激活了它它就能获得非零梯度那么既然负区有问题为什么不用 Leaky ReLU 等替代实际上Leaky ReLU / PReLU / ELU 确实在某些任务上表现更好如 GANs、小数据集但在大规模图像分类如 ImageNet中标准 ReLU 通常足够好且更简单、更快多数 SOTA 模型ResNet、EfficientNet、ViT 的 MLP 块仍默认使用 ReLU 或其变体如 GELU。所以“只用 ReLU” 是效率与性能的平衡选择而非忽视问题其用“简单粗暴”的非线性换来了训练深层网络的可能性。以下是一段在训练或推理过程中监控每一层 ReLU 的激活率的代码可以看到激活率为61%import torch import torch.nn as nn import torchvision.models as models # 1. 定义一个钩子hook函数用于记录激活率 def make_relu_hook(name): def hook(module, input, output): # output 是 ReLU 的输出shape: (B, C, H, W) 或 (B, D) total output.numel() # 总元素数 active (output 0).sum().item() # 激活的元素数0 ratio active / total print(f{name}: 激活率 {ratio:.4f} ({active}/{total})) return hook # 2. 加载一个预训练模型例如 ResNet18 model models.resnet18(pretrainedTrue) model.eval() # 推理模式 # 3. 遍历所有 ReLU 层注册前向钩子 hooks [] for name, module in model.named_modules(): if isinstance(module, nn.ReLU): # 为每个 ReLU 注册钩子 hook module.register_forward_hook(make_relu_hook(name)) hooks.append(hook) # 4. 准备一个示例输入ImageNet 标准尺寸 x torch.randn(1, 3, 224, 224) # batch_size1 # 5. 前向传播会自动触发钩子打印激活率 with torch.no_grad(): _ model(x) # 6. 可选移除钩子避免内存泄漏 for h in hooks: h.remove()
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2430177.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!