一、激活函数(Sigmoid、ReLU、Softmax)梯度计算

(一)核心知识点

激活函数是神经网络非线性来源,梯度用于梯度下降反向传播,是考试重点。


1. Sigmoid 函数

公式

σ(x)=11+e−x\sigma(x) = \frac{1}{1+e^{-x}}σ(x)=1+ex1

题目

求 Sigmoid 函数的导数(梯度),并化简。

答案 & 解析

求导过程

在这里插入图片描述

最终梯度
σ′(x)=σ(x)(1−σ(x))\boldsymbol{\sigma'(x) = \sigma(x)\big(1-\sigma(x)\big)}σ(x)=σ(x)(1σ(x))

解析

  1. 化简形式计算高效,反向传播直接复用函数值;

  2. 值域 (0,0.25](0,0.25](0,0.25],自变量绝对值越大,梯度越趋近于 0,易出现梯度消失


2. ReLU 函数

公式

在这里插入图片描述

题目

求 ReLU 函数的梯度。

答案 & 解析

梯度结果在这里插入图片描述

x=0x=0x=0 处导数不唯一,工程上通常直接取 000111

解析

  1. x>0x>0x>0 时梯度恒为 1,有效缓解梯度消失;

  2. x<0x<0x<0 时梯度为 0,神经元死亡(不再更新)是其主要缺陷;

  3. 计算简单、运算速度快,是卷积网络主流激活函数。


3. Softmax 函数

多用于分类任务输出层,设输入向量 z=[z1,z2,…,zn]\boldsymbol{z}=[z_1,z_2,\dots,z_n]z=[z1,z2,,zn]

公式

在这里插入图片描述

题目

推导 Softmax 对输入 zjz_jzj 的偏导数(梯度)。

答案 & 解析

分两种情况:i=ji=ji=ji≠ji\neq ji=j
S=∑k=1nezkS = \sum\limits_{k=1}^n e^{z_k}S=k=1nezk,则 pi=eziSp_i = \dfrac{e^{z_i}}{S}pi=Sezi

  1. i=j\boldsymbol{i = j}i=j

  2. 在这里插入图片描述

  3. i≠j\boldsymbol{i \neq j}i=j

  4. 在这里插入图片描述

汇总梯度
在这里插入图片描述

解析

  1. Softmax 将输入转为概率分布,所有输出和为 1;

  2. 常与交叉熵损失搭配使用,组合后梯度形式会大幅简化,是分类网络标准搭配。


二、交叉熵计算 题目 + 答案 + 解析

核心公式

在这里插入图片描述

离散分布交叉熵:对于真实分布 PPP、预测分布 QQQ

说明:题目中维度统一按 4 维计算,对数默认以自然对数 / 2 为底均可,考试统一按公式计算即可。

题目

已知:
P=[0.1, 0, 0, 0]P = [0.1,\ 0,\ 0,\ 0]P=[0.1, 0, 0, 0]
Q1=[0.4, 0.2, 0.3, 0.1]Q_1 = [0.4,\ 0.2,\ 0.3,\ 0.1]Q1=[0.4, 0.2, 0.3, 0.1]
Q2=[0.7, 0, 0.2, 0.1]Q_2 = [0.7,\ 0,\ 0.2,\ 0.1]Q2=[0.7, 0, 0.2, 0.1]

  1. 分别计算 H(P,Q1)H(P,Q_1)H(P,Q1)H(P,Q2)H(P,Q_2)H(P,Q2)

  2. 对比结果,说明交叉熵的意义。


解答过程

1. 计算 H(P,Q1)H(P,Q_1)H(P,Q1)

代入数值计算:

在这里插入图片描述

H(P,Q1)≈0.0916H(P,Q_1) \approx \boldsymbol{0.0916}H(P,Q1)0.0916

2. 计算 H(P,Q2)H(P,Q_2)H(P,Q2)

代入数值计算:

在这里插入图片描述

H(P,Q2)≈0.0357H(P,Q_2) \approx \boldsymbol{0.0357}H(P,Q2)0.0357

3. 结果对比

H(P,Q1)≈0.0916 > H(P,Q2)≈0.0357H(P,Q_1) \approx 0.0916 \ > \ H(P,Q_2) \approx 0.0357H(P,Q1)0.0916 > H(P,Q2)0.0357


解析 & 交叉熵意义

  1. 数值解读
    真实分布 PPP 在第一个位置概率为 0.10.10.1,其余为 0;
    Q2Q_2Q2 在对应位置概率 0.70.70.7,比 Q1Q_1Q10.40.40.4 更接近真实分布 PPP,因此交叉熵值更小

  2. 交叉熵核心意义

  • 交叉熵用来衡量两个概率分布之间的差异程度

  • 交叉熵越小,代表预测分布 QQQ 与真实分布 PPP 越接近,模型预测效果越好;

  • 在深度学习中,交叉熵常作为损失函数,训练目标就是不断最小化交叉熵,让网络预测逼近真实标签。

  1. 补充说明
    P(i)=0P(i)=0P(i)=0 时,该项 P(i)log⁡Q(i)=0P(i)\log Q(i)=0P(i)logQ(i)=0,计算时可直接忽略,简化运算。

卷积与池化计算详解

卷积计算

已知输入矩阵、卷积核,步长 stride=1,padding=0(无补零):

输入矩阵 AAA
在这里插入图片描述

卷积核 KKK
在这里插入图片描述

卷积输出尺寸公式:
在这里插入图片描述

代入参数:输入尺寸3×33\times33×3,卷积核尺寸2×22\times22×2,padding=0,stride=1,得输出尺寸为 2×22\times22×2

逐位置计算(卷积核与对应区域点积):

  • 位置 (1,1)(1,1)(1,1)1×1+0×0+0×(−1)+2×1=1+0+0+2=31\times1 + 0\times0 + 0\times(-1) + 2\times1 = 1 + 0 + 0 + 2 = 31×1+0×0+0×(1)+2×1=1+0+0+2=3

  • 位置 (1,2)(1,2)(1,2)0×1+(−1)×0+2×(−1)+1×1=0+0−2+1=−10\times1 + (-1)\times0 + 2\times(-1) + 1\times1 = 0 + 0 - 2 + 1 = -10×1+(1)×0+2×(1)+1×1=0+02+1=1

  • 位置 (2,1)(2,1)(2,1)0×1+2×0+(−2)×(−1)+0×1=0+0+2+0=20\times1 + 2\times0 + (-2)\times(-1) + 0\times1 = 0 + 0 + 2 + 0 = 20×1+2×0+(2)×(1)+0×1=0+0+2+0=2

  • 位置 (2,2)(2,2)(2,2)2×1+1×0+0×(−1)+1×1=2+0+0+1=32\times1 + 1\times0 + 0\times(-1) + 1\times1 = 2 + 0 + 0 + 1 = 32×1+1×0+0×(1)+1×1=2+0+0+1=3

卷积结果:
在这里插入图片描述


池化计算

输入矩阵与卷积题相同,步长 stride=1,池化核为2×22\times22×2的平均池化:

输入矩阵 AAA
在这里插入图片描述

平均池化输出尺寸与卷积计算一致,为 2×22\times22×2,逐位置计算区域平均值:

  • 位置 (1,1)(1,1)(1,1)1+0+0+24=34=0.75\frac{1+0+0+2}{4} = \frac{3}{4} = 0.7541+0+0+2=43=0.75

  • 位置 (1,2)(1,2)(1,2)0+(−1)+2+14=24=0.5\frac{0+(-1)+2+1}{4} = \frac{2}{4} = 0.540+(1)+2+1=42=0.5

  • 位置 (2,1)(2,1)(2,1)0+2+(−2)+04=04=0\frac{0+2+(-2)+0}{4} = \frac{0}{4} = 040+2+(2)+0=40=0

  • 位置 (2,2)(2,2)(2,2)2+1+0+14=44=1\frac{2+1+0+1}{4} = \frac{4}{4} = 142+1+0+1=44=1

池化结果:
在这里插入图片描述


梯度下降算法题

一、题目信息

目标函数:f(x,y)=ln⁡a⋅x2+(sin⁡b)⋅y+c2f(x,y) = \ln a \cdot x^2 + (\sin b) \cdot y + c^2f(x,y)=lnax2+(sinb)y+c2,求关于参数 a,b,ca,b,ca,b,c 的梯度下降算法,需包含目标函数、梯度、迭代公式,并说明算法原理。


二、解题步骤

1. 目标函数

f(x,y)=ln⁡a⋅x2+(sin⁡b)⋅y+c2f(x,y) = \ln a \cdot x^2 + (\sin b) \cdot y + c^2f(x,y)=lnax2+(sinb)y+c2
(其中 x,yx,yx,y 为常数,a,b,ca,b,ca,b,c 为待优化参数)

2. 各参数的梯度(偏导数)

对参数 a,b,ca,b,ca,b,c 分别求偏导:

  • aaa 求偏导:
    ∂f∂a=1a⋅x2\frac{\partial f}{\partial a} = \frac{1}{a} \cdot x^2af=a1x2

  • bbb 求偏导:
    ∂f∂b=(cos⁡b)⋅y\frac{\partial f}{\partial b} = (\cos b) \cdot ybf=(cosb)y

  • ccc 求偏导:
    ∂f∂c=2c\frac{\partial f}{\partial c} = 2ccf=2c

3. 梯度下降迭代公式

设学习率为 α\alphaα,参数更新规则为:

在这里插入图片描述


三、梯度下降算法的基本思路与原理

  1. 核心思路:梯度是函数上升最快的方向,梯度下降通过沿着梯度的反方向更新参数,使目标函数值不断减小,最终逼近最小值点。

  2. 关键原理

    • 每次迭代计算目标函数对参数的梯度;

    • 按 “参数 = 参数 - 学习率 × 梯度” 的公式更新参数;

    • 重复迭代直到函数值收敛(变化量小于阈值),得到近似最优解。

  3. 补充说明

    • 学习率 α\alphaα 控制每次更新的步长,过大会导致震荡不收敛,过小则收敛过慢;

    • 该算法是深度学习模型训练的核心优化方法,反向传播就是利用梯度下降更新网络权重。


四、补充解析

  1. 参数更新趋势

    • ccc 的更新:若初始 c>0c>0c>0,梯度为正,每次迭代会让 ccc 减小,最终收敛到 c=0c=0c=0(此时 c2c^2c2 项取最小值 0);

    • aaa 的更新:梯度与 aaa 成反比,若 x≠0x\neq0x=0aaa 会不断调整,使 ln⁡a\ln alna 趋近于负无穷,对应 a→0+a\to0^+a0+

    • bbb 的更新:梯度为 ycos⁡by\cos bycosb,最终会收敛到使 sin⁡b\sin bsinb 取最小值的点(若 y>0y>0y>0,则 sin⁡b=−1\sin b=-1sinb=1,即 b=−π2+2kπb=-\frac{\pi}{2}+2k\pib=2π+2kπ)。

  2. 最小值分析
    a→0+a\to0^+a0+b=−π2+2kπb=-\frac{\pi}{2}+2k\pib=2π+2kπc=0c=0c=0 时,函数 f(x,y)f(x,y)f(x,y) 趋近于负无穷,因此该函数无有限最小值;梯度下降只能找到局部收敛点,无法收敛到全局极小值。


PyTorch 广播机制(Tensor 自动扩展)题目解析


在这里插入图片描述

(1)题目填空与结果

  1. x 的数据意义:表示一个包含 10 张图片的批次,每张图片有 1 个通道,分辨率为 32×3232 \times 3232×32。张量维度含义为 (batch_size, channels, height, width)

  2. print((x+y).shape) 结果torch.Size([10, 1, 32, 32])


(2)广播机制等价实现

x 的 shape 为 (10, 1, 32, 32)y 的 shape 为 (32, 32),二者可以通过广播机制相加。

等价实现(使用 unsqueezeexpand):

# 步骤1:给y增加维度,使其与x的维度数匹配
y_ = y.unsqueeze(0).unsqueeze(0)  # shape变为(1, 1, 32, 32)

# 步骤2:扩展y的维度,使其与x的shape完全一致
y_ = y_.expand(10, 1, 32, 32)    # shape变为(10, 1, 32, 32)

# 此时x + y_ 和原代码x + y 效果完全一致
result = x + y_

(3)广播机制的意义与优点

  1. 意义:广播机制允许不同 shape 的张量在满足一定条件下进行运算,PyTorch 会自动在缺失的维度上 “扩展” 张量,无需手动复制数据。

  2. 优点

    • 节省内存:不需要显式复制数据来匹配 shape,避免创建额外的大张量;

    • 简化代码:无需手动编写 unsqueezeexpand 等扩展操作,代码更简洁;

    • 提高效率:底层实现优化,比手动扩展张量更高效。


在这里插入图片描述

LeNet-5 神经网络结构解析

该网络是经典的手写数字识别卷积神经网络,结构清晰,由输入层、卷积层、池化层、全连接层和输出层组成。


1. 输入层(INPUT)

  • 输入尺寸32×3232 \times 3232×32 单通道灰度图像

  • 功能:接收原始图像数据,作为网络的输入


2. C1 卷积层(Convolution)

  • 功能:使用卷积核提取图像的低级特征(边缘、纹理)

  • 参数

    • 卷积核:5×55 \times 55×5,共 6 个

    • 步长:1,无填充(padding=0)

  • 输出特征图6@28×286@28 \times 286@28×28(计算:32−5+1=2832-5+1=28325+1=28

  • 可训练参数5×5×6+6=1565 \times 5 \times 6 + 6 = 1565×5×6+6=156(含偏置)


3. S2 池化层(Subsampling / 池化)

  • 功能:下采样,降低特征图尺寸,保留关键信息,减少计算量

  • 参数

    • 池化核:2×22 \times 22×2,步长 2

    • 采用平均池化(或最大池化)

  • 输出特征图6@14×146@14 \times 146@14×14(计算:28/2=1428/2=1428/2=14

  • 可训练参数2×6=122 \times 6 = 122×6=12(含偏置,若使用带参数池化)


4. C3 卷积层(Convolution)

  • 功能:提取中级组合特征(边缘组合、局部形状)

  • 参数

    • 卷积核:5×55 \times 55×5,共 16 个

    • 步长:1,无填充

    • 采用稀疏连接:每个卷积核仅与 S2 的部分特征图相连

  • 输出特征图16@10×1016@10 \times 1016@10×10(计算:14−5+1=1014-5+1=10145+1=10

  • 可训练参数(5×5×6×3)+16=1516(5 \times 5 \times 6 \times 3) + 16 = 1516(5×5×6×3)+16=1516(按稀疏连接方式计算)


5. S4 池化层(Subsampling / 池化)

  • 功能:再次下采样,进一步压缩特征图尺寸

  • 参数

    • 池化核:2×22 \times 22×2,步长 2
  • 输出特征图16@5×516@5 \times 516@5×5(计算:10/2=510/2=510/2=5

  • 可训练参数2×16=322 \times 16 = 322×16=32(含偏置)


6. C5 卷积层(Convolution)

  • 功能:提取高级特征,此时特征图尺寸已足够小,该层等价于全连接层

  • 参数

    • 卷积核:5×55 \times 55×5,共 120 个

    • 步长:1,无填充

  • 输出特征图120@1×1120@1 \times 1120@1×1(计算:5−5+1=15-5+1=155+1=1

  • 可训练参数(5×5×16)×120+120=48120(5 \times 5 \times 16) \times 120 + 120 = 48120(5×5×16)×120+120=48120


7. F6 全连接层(Full Connection)

  • 功能:将特征映射到更高维空间,完成特征向类别向量的过渡

  • 输入:C5 层输出的 120 个神经元

  • 输出:84 个神经元

  • 可训练参数120×84+84=10164120 \times 84 + 84 = 10164120×84+84=10164


8. 输出层(OUTPUT)

  • 功能:输出分类结果(手写数字 0-9)

  • 参数:采用径向基函数(RBF)或 Softmax 激活

  • 输出:10 个神经元,对应 10 个类别

  • 可训练参数84×10=84084 \times 10 = 84084×10=840


整体结构总结

类型 输出尺寸 主要功能
INPUT 输入层 32×3232 \times 3232×32 接收图像数据
C1 卷积层 6@28×286@28 \times 286@28×28 提取低级边缘特征
S2 池化层 6@14×146@14 \times 146@14×14 下采样,降低维度
C3 卷积层 16@10×1016@10 \times 1016@10×10 提取中级组合特征
S4 池化层 16@5×516@5 \times 516@5×5 进一步压缩特征
C5 卷积层 120@1×1120@1 \times 1120@1×1 提取高级特征
F6 全连接层 84 特征映射到类别空间
OUTPUT 输出层 10 输出分类结果

在这里插入图片描述
在这里插入图片描述

程序题考点整理与代码示例


一、LeNet-5 与 ResNet 网络构建(PyTorch)

1. LeNet-5 完整代码示例

import torch
import torch.nn as nn
import torch.optim as optim

# 1. 定义网络类
class LeNet5(nn.Module):
    def __init__(self):
        super(LeNet5, self).__init__()
        # C1 卷积层: 输入1通道,输出6通道,5x5卷积核
        self.c1 = nn.Conv2d(1, 6, kernel_size=5, padding=0)
        # S2 池化层: 2x2平均池化
        self.s2 = nn.AvgPool2d(kernel_size=2, stride=2)
        # C3 卷积层: 输入6通道,输出16通道,5x5卷积核
        self.c3 = nn.Conv2d(6, 16, kernel_size=5, padding=0)
        # S4 池化层
        self.s4 = nn.AvgPool2d(kernel_size=2, stride=2)
        # C5 卷积层/全连接层: 输入16通道,输出120通道,5x5卷积核
        self.c5 = nn.Conv2d(16, 120, kernel_size=5, padding=0)
        # F6 全连接层
        self.f6 = nn.Linear(120, 84)
        # 输出层
        self.out = nn.Linear(84, 10)

    def forward(self, x):
        # 前向传播
        x = torch.sigmoid(self.c1(x))
        x = self.s2(x)
        x = torch.sigmoid(self.c3(x))
        x = self.s4(x)
        x = torch.sigmoid(self.c5(x))
        x = x.view(-1, 120)  # 展平
        x = torch.sigmoid(self.f6(x))
        x = self.out(x)
        return x

# 2. GPU部署
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = LeNet5().to(device)

# 3. 损失函数与优化器定义
criterion = nn.CrossEntropyLoss()  # 交叉熵损失
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

# 4. 梯度计算三要素(训练循环核心)
def train_step(inputs, labels):
    # 1) 梯度清零
    optimizer.zero_grad()
    # 2) 前向传播+计算损失
    outputs = model(inputs)
    loss = criterion(outputs, labels)
    # 3) 反向传播+参数更新
    loss.backward()
    optimizer.step()
    return loss.item()

2. ResNet 残差块与基础结构代码示例

import torch
import torch.nn as nn

# 残差块定义(核心)
class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1, downsample=None):
        super(ResidualBlock, self).__init__()
        # 卷积层1
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, 
                               stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)
        # 卷积层2
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, 
                               stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_channels)
        # 下采样层(匹配维度)
        self.downsample = downsample

    def forward(self, x):
        residual = x
        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)
        out = self.conv2(out)
        out = self.bn2(out)
        if self.downsample:
            residual = self.downsample(x)
        # 残差连接
        out += residual
        out = self.relu(out)
        return out

# 简化版ResNet定义
class ResNet(nn.Module):
    def __init__(self, block, layers, num_classes=10):
        super(ResNet, self).__init__()
        self.in_channels = 64
        # 初始卷积层
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        # 残差层
        self.layer1 = self._make_layer(block, 64, layers[0])
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
        # 分类头
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(512, num_classes)

    def _make_layer(self, block, out_channels, blocks, stride=1):
        downsample = None
        if stride != 1 or self.in_channels != out_channels:
            downsample = nn.Sequential(
                nn.Conv2d(self.in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(out_channels)
            )
        layers = []
        layers.append(block(self.in_channels, out_channels, stride, downsample))
        self.in_channels = out_channels
        for _ in range(1, blocks):
            layers.append(block(out_channels, out_channels))
        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

# 实例化ResNet-18
def resnet18():
    return ResNet(ResidualBlock, [2, 2, 2, 2])

# GPU部署示例
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = resnet18().to(device)

二、2D 函数优化案例(梯度下降完整流程)

import torch
import torch.optim as optim
import matplotlib.pyplot as plt

# 1. 定义目标函数(2D)
def f(x, y):
    return (x ** 2 + y - 11) ** 2 + (x + y ** 2 - 7) ** 2  # Himmelblau函数,有4个局部最小值

# 2. 设定初始值(需要优化的变量,设置requires_grad=True)
x = torch.tensor(0.0, requires_grad=True)
y = torch.tensor(0.0, requires_grad=True)

# 3. 优化器选择与参数设置
optimizer = optim.SGD([x, y], lr=0.01, momentum=0.9)
# 也可使用Adam: optimizer = optim.Adam([x, y], lr=0.01)

# 4. 梯度下降迭代优化
history = []
epochs = 100
for epoch in range(epochs):
    # 梯度计算三要素:
    # 1) 梯度清零
    optimizer.zero_grad()
    # 2) 前向传播+计算损失(函数值)
    loss = f(x, y)
    # 3) 反向传播+参数更新
    loss.backward()
    optimizer.step()
    
    history.append((x.item(), y.item(), loss.item()))
    if (epoch + 1) % 10 == 0:
        print(f"Epoch {epoch+1:3d}: x={x.item():.4f}, y={y.item():.4f}, loss={loss.item():.4f}")

# 5. 可视化优化过程
xs = [h[0] for h in history]
ys = [h[1] for h in history]
plt.plot(xs, ys, 'r-o', markersize=4)
plt.title("Optimization Path of 2D Function")
plt.xlabel("x")
plt.ylabel("y")
plt.show()

核心考点说明

  1. 梯度计算三要素(所有训练 / 优化代码必背)

    • optimizer.zero_grad():梯度清零,防止累积

    • loss.backward():反向传播,计算梯度

    • optimizer.step():根据梯度更新参数

  2. GPU 部署关键代码

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = model.to(device)
    inputs, labels = inputs.to(device), labels.to(device)
    
  3. 残差块核心逻辑

    • 输入经过两层卷积后,与原输入(或下采样后的输入)相加,再激活

    • 解决深层网络的梯度消失问题,使深层模型更容易训练


(注:文档部分内容可能由 AI 生成),如有错误或不足请在评论区指正,我会进行完善修正

Logo

立足具身智能前沿赛道,致力于搭建全球化、开源化、全栈式技术交流与实践共创平台。

更多推荐