超全面讲透一个算法模型,AlexNet !!

哈喽,大家好~

这个小节,咱们一起来看下 AlexNet ~

首先,神经网络是一种模仿人类大脑“神经元连接方式”的计算模型。

它的基本思想是:

  • 把输入(比如一张图片)通过一层一层的计算“传递”下去。
  • 每一层都会对输入做一些处理,比如找出边缘、颜色、形状。
  • 最后一层会给出一个结果,比如“这是猫”或者“这是狗”。

可以理解成:神经网络就是一套复杂的数学“公式+连接”,它自己不会写规则,而是通过大量样本学习出规则。

举个简单例子:

  • 如果我们给神经网络看成千上万张“猫”和“狗”的照片,它就会自己学会分辨猫和狗。
  • 我们不用告诉它“猫有胡须,狗的耳朵比较大”,它会自动总结出这些特征。

AlexNet 是什么?

AlexNet 是 2012 年由 Alex Krizhevsky 提出的一个神经网络模型。它之所以有名,是因为在当年的图像识别比赛(ImageNet 大赛)上,它的表现远远超过其他方法。

简单来说,AlexNet 就像是神经网络历史上的一个“转折点”:

  • 以前大家觉得深度神经网络很难训练,也跑不动。
  • AlexNet 用了更深的结构、更大的数据集和更强的计算能力(主要是 GPU),一举证明了深度学习的威力。

AlexNet 的核心特点

  1. 层数更深:用了 8 层(5 层卷积层 + 3 层全连接层)。
  2. 用 GPU 加速:当时的突破点之一,大大缩短了训练时间。
  3. 激活函数 ReLU:相比传统函数,更快收敛,不容易卡住。
  4. 数据增强和 Dropout:减少过拟合,让模型更能适应新数据。

就是说可以把 AlexNet 想象成一个“超级放大版的猫狗识别器”,它不是靠人写规则,而是靠自己学出来的。

它之所以重要,是因为它向世界证明:只要有足够的数据和算力,神经网络真的可以在复杂任务上超过传统方法

原理详解

全局概览:AlexNet 是什么(用数学对象表述)

任务:多分类(ImageNet 1000 类)。输入图像 ,输出类别概率 )。

模型:一个由卷积层(Conv)→ 非线性(ReLU)→ 归一化(LRN)→ 池化(Pool)→ 全连接(FC)→ Softmax组成的复合函数

参数  包含所有卷积核、全连接权重与偏置。

常用的 AlexNet 张量尺寸(单卡视角、不考虑原论文的双 GPU 分组计算细节):输入 

1. 各模块的数学定义与尺寸计算

1.1 卷积层(Conv)

前向: 给定第  层输入特征图 ,卷积核 ,偏置 ,步幅 ,填充 

输出尺寸:

AlexNet 关键设置:

  • Conv1:, , ,输入  → 输出 
  • Conv2:, ,   (在池化后续尺寸基础上)。
  • Conv3/4/5:, , 

1.2 非线性激活(ReLU)

  • 前向: (逐元素)。
  • 性质: 避免梯度消失、收敛快;导数简单(见反向传播部分)。

1.3 局部响应归一化(LRN, Local Response Normalization)

  • 用于模拟“侧抑制”,对同一空间位置在通道维度做归一化。对通道  的激活 

    AlexNet 常用超参:

1.4 池化(Max Pooling)

  • 前向(最大池化): 在每个通道上以窗口 ,步幅 

  • AlexNet 使用  窗口、步幅 

1.5 全连接(Fully-Connected, FC)

  • 将上一层张量展平为向量 

1.6 Dropout

  • 训练时以概率  将神经元置零(保留率 ),保留的神经元按  缩放,期望不变:

  • 推理时不使用掩码与缩放(或采用“训练时不缩放、推理时乘 ”的等价实现)。

1.7 Softmax 与交叉熵

  • Softmax: 给定分类打分(logits)

  • 损失(单样本 one-hot 标签 ):

  • 带权重衰减( 正则): 总损失

2. AlexNet 的逐层尺寸与结构(典型实现)

2.1 尺寸流(单图推理)

  • 输入:
  • Conv1(, , , )→  ReLU → LRN → MaxPool(, )→ 
  • Conv2(, , , )→  ReLU → LRN → MaxPool(, )→ 
  • Conv3(, , , )→  → ReLU
  • Conv4(, , , )→  → ReLU
  • Conv5(, , , )→  ReLU → MaxPool(, )→ 
  • 展平 →  FC6: → ReLU → Dropout FC7: → ReLU → Dropout FC8: → Softmax

3. 训练目标与优化算法(含动量与权重衰减)

3.1 小批量 SGD(带动量)

  • 梯度(对参数 ):  由反向传播得到。

  • 动量更新:

    其中  为动量系数(如 ), 学习率, 权重衰减; 通常只对权重项(不含偏置、归一化偏置等)施加。

3.2 数据预处理与增强(影响分布与梯度方差)

  • 均值消除: 像素减去训练集 RGB 通道均值。

  • 随机裁剪/镜像: 训练时随机裁 (或近似)与水平翻转。

  • PCA 颜色扰动: 令 RGB 像素数据的协方差矩阵的主成分为  与特征值 ,采样 (如 ),对每个像素做

4. 反向传播的核心推导(逐模块)

记号说明:对任一中间变量 ,其损失梯度记为 。链式法则用  表示逐元素乘。

4.1 Softmax + 交叉熵的梯度(关键结论与推导)

  • logits:,概率 ,损失 

  • 关键梯度:

    推导要点:

    整理即得 

  • 进一步: 对 FC8

4.2 全连接层(一般形式)

  • 前向:,后向给定 

4.3 ReLU 的梯度

  • 前向:;后向:

4.4 Dropout 的梯度

  • 训练时:。后向:

    推理时无梯度分支(不使用掩码)。

4.5 最大池化(MaxPool)梯度

  • 前向保存每个池化窗口的argmax 位置 。后向把梯度路由回该位置:

    窗口内其他位置梯度为 0。

4.6 卷积层的梯度(重点)

  • 前向:。设后向来自上一层的梯度为 (尺寸 )。

  • 对偏置: 每个输出通道 c 的梯度是该通道所有位置梯度之和:

  • 对卷积核  是输入与  的“相关”(cross-correlation):

  • 对输入  相当于把每个输出通道的  翻转后的卷积核在通道维上做卷积并累加(考虑步幅/填充的反向映射):

    其中仅当  为整数且落在  内时取值。实现中常用“上采样 + 全卷积/转置卷积”的等价计算或 im2col 矩阵化。

4.7 LRN 的梯度(含分子与分母两路)

  • 回忆:

    设损失对  的梯度为 ,则对 

    第一项来自分子 ;第二项来自分母  对所有受影响通道的“反向侧抑制”。

5. 损失函数的批量形式与正则化项梯度

5.1 批量交叉熵

  • 批大小 ,样本 

5.2 权重衰减()梯度

  • 对任意权重矩阵 

  • 实际更新时常与动量/学习率一道合并到优化步骤中(见 3.1)。

6. AlexNet 的端到端训练/推理流程(无代码版“可执行思路”)

6.1 初始化

  1. 设定层级结构与超参(卷积核大小、步幅、填充、通道数、池化窗口、Dropout 概率等)。
  2. 权重初始化:高斯/均匀分布的小方差随机数(可按 He/Xavier 原理:保证前向/反向方差稳定)。
  3. 偏置初始化为零或小常数。

6.2 数据通道

  1. 读入图像,缩放到固定尺度(如最短边 256)。
  2. 随机裁剪 、随机水平翻转。
  3. 减去训练集均值;可加 PCA 颜色扰动。

6.3 前向传播(单批次)

  1. Conv1 → ReLU → LRN → MaxPool,记录池化 argmax、LRN 的中间量 
  2. Conv2 → ReLU → LRN → MaxPool,同上记录必要中间量。
  3. Conv3 → ReLU → Conv4 → ReLU → Conv5 → ReLU → MaxPool
  4. 展平 → FC6 → ReLU → Dropout → FC7 → ReLU → Dropout → FC8
  5. Softmax 得到 ;计算交叉熵损失(可加  正则)。

6.4 反向传播(单批次)

  1.  Softmax+CE 得到 

  2. 依次对 FC8、Dropout、ReLU、FC7、Dropout、ReLU、FC6 回传:

  • 每层按 4.2/4.3/4.4 给出 
  • 将梯度 reshape 成卷积张量形状,依次对 Conv5→Conv4→Conv3→Conv2→Conv1 回传:

    • ReLU:门控梯度(4.3);
    • 池化:按 argmax 路由(4.5);
    • LRN:用 4.7 的公式回传;
    • 卷积:用 4.6 计算对  的梯度。
  • 在每层权重梯度上加上   (若在优化器中未合并)。

  • 6.5 参数更新

    • 按 3.1 用 SGD+动量+权重衰减 更新全部可训练参数;必要时调整学习率(阶梯式或多项式衰减等)。

    6.6 推理(测试)

    • 关闭 Dropout 与数据增强(仅做中心裁剪/尺度归一化);前向一次得到概率向量 ,取 

    7. 关键细节的进一步理解与数学联系

    7.1 为什么 ReLU 有利于优化

    Sigmoid 在  大时 ,梯度消失;ReLU 的导数是 ,在激活区间内保持常数,梯度路径更“直”。

    7.2 大卷积核 + 大步幅的感受野与下采样

    Conv1 的  等价于早期强下采样,快速扩大感受野,降低后续计算量。尺寸公式确保输出为整数()。

    7.3 LRN 的“侧抑制”数学效应

    同一位置上通道间的二次项  在分母中抑制幅度较大的响应,使网络更关注“相对显著”的通道响应;反向中体现为通道间的耦合梯度(见 4.7 第二项)。

    7.4 Dropout 的期望保持与集成效果

    训练相当于对指数多的“子网络”做参数共享;按  缩放保证 ,推理等价于对大量子网络的近似平均。

    完整案例

    案例部分,咱们使用Pytroch实现一个简易的AlexNet实现过程,包含训练、可视化和分析,帮助大家对于原理的理解~

    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torch.utils.data import DataLoader
    from torchvision import datasets, transforms
    import matplotlib.pyplot as plt

    torch.manual_seed(42)

    # 1. 数据准备
    transform = transforms.Compose([
        transforms.Resize((224224)),                # 调整尺寸适配 AlexNet
        transforms.Grayscale(num_output_channels=3), # 转为 3 通道
        transforms.ToTensor()
    ])

    # root 指向 MNIST 数据所在父目录 /MNIST
    train_dataset = datasets.MNIST(root='./MNIST'
                                   train=True, transform=transform, download=True)
    test_dataset  = datasets.MNIST(root='./MNIST'
                                   train=False, transform=transform, download=True)

    train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
    test_loader  = DataLoader(test_dataset, batch_size=64, shuffle=False)

    # 2. 定义简化 AlexNet
    class SimpleAlexNet(nn.Module):
        def __init__(self, num_classes=10):
            super(SimpleAlexNet, self).__init__()
            self.features = nn.Sequential(
                nn.Conv2d(364, kernel_size=11, stride=4, padding=2),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),

                nn.Conv2d(64192, kernel_size=5, padding=2),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),

                nn.Conv2d(192384, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.Conv2d(384256, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.Conv2d(256256, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),
            )
            self.classifier = nn.Sequential(
                nn.Dropout(),
                nn.Linear(256*6*64096),
                nn.ReLU(inplace=True),
                nn.Dropout(),
                nn.Linear(40964096),
                nn.ReLU(inplace=True),
                nn.Linear(4096, num_classes),
            )

        def forward(self, x):
            x = self.features(x)
            x = torch.flatten(x, 1)
            x = self.classifier(x)
            return x

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = SimpleAlexNet().to(device)

    # 3. 损失函数 & 优化器
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001)

    # 4. 训练与测试
    num_epochs = 3
    train_losses, test_accuracies = [], []

    for epoch in range(num_epochs):
        model.train()
        running_loss = 0.0
        for images, labels in train_loader:
            images, labels = images.to(device), labels.to(device)
            optimizer.zero_grad()
            outputs = model(images)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
        train_losses.append(running_loss / len(train_loader))

        model.eval()
        correct, total = 00
        with torch.no_grad():
            for images, labels in test_loader:
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)
                _, predicted = torch.max(outputs.data, 1)
                total += labels.size(0)
                correct += (predicted == labels).sum().item()
        test_accuracy = 100 * correct / total
        test_accuracies.append(test_accuracy)
        print(f'Epoch [{epoch+1}/{num_epochs}] | Loss: {train_losses[-1]:.4f} | Test Accuracy: {test_accuracy:.2f}%')

    # 5. 可视化训练曲线
    plt.figure(figsize=(10,5))
    plt.plot(range(1,num_epochs+1), train_losses, marker='o', color='orange', label='Train Loss')
    plt.plot(range(1,num_epochs+1), test_accuracies, marker='s', color='green', label='Test Accuracy')
    plt.title('Training Loss & Test Accuracy', fontsize=14)
    plt.xlabel('Epoch', fontsize=12)
    plt.ylabel('Value', fontsize=12)
    plt.legend()
    plt.grid(True)
    plt.show()

    # 6. 可视化预测结果
    classes = [str(i) for i in range(10)]
    model.eval()
    dataiter = iter(test_loader)
    images, labels = next(dataiter)
    images, labels = images.to(device), labels.to(device)
    outputs = model(images)
    _, preds = torch.max(outputs, 1)

    plt.figure(figsize=(12,6))
    for idx in range(8):
        plt.subplot(2,4,idx+1)
        img = images[idx].cpu().permute(1,2,0)
        plt.imshow(img)
        plt.title(f"GT: {classes[labels[idx]]}\nPred: {classes[preds[idx]]}", color='purple')
        plt.axis('off')
    plt.tight_layout()
    plt.show()

    咱们这里,使用 PyTorch 实现了一个简化版的 AlexNet,用于对 MNIST 手写数字数据集进行分类。

    1. 数据准备
    • 将 MNIST 原始的 28×28 灰度图调整为 224×224 的 3 通道图像,以适配 AlexNet 输入。
    • 使用 DataLoader 按批加载训练集和测试集。
  • 模型构建
    • 卷积特征提取层:多层卷积 + ReLU + 最大池化
    • 全连接分类器:线性层 + Dropout,用于将提取的特征映射到 10 类输出
    • 定义 SimpleAlexNet 类,包含:
    • 支持前向传播。
  • 训练设置
    • 损失函数:交叉熵损失 (CrossEntropyLoss)
    • 优化器:Adam
  • 训练与测试
    • 训练过程中记录每个 epoch 的训练损失
    • 测试集上计算分类准确率
    • 可视化训练损失与测试准确率的变化趋势

    结果可视化

    • 训练曲线(损失下降、准确率上升)
    • 随机展示部分测试图像的预测结果,与真实标签对比

    资讯配图

    总结来说,使用 AlexNet 的主要价值在于 学习卷积网络基础结构、训练流程和可视化特征,在 MNIST 这样的简单数据集上可以工作,但如果追求效率或最新性能,可以考虑轻量级网络或深层残差网络。

    最后

    最近准备了16大块的内容,124个算法问题的总结,完整的机器学习小册,免费领取~
    资讯配图
    领取:备注「算法小册」即可~
    资讯配图

    声明:内容取材于网络,仅代表作者观点,如有内容违规问题,请联系处理。 
    Copyright © 2025 成都区角科技有限公司
    蜀ICP备2025143415号-1
      
    川公网安备51015602001305号