当前位置: 首页 > article >正文

动手学深度学习 -- 3.6 数学推演

代码逻辑

在《动手学深度学习》3.6节 Softmax 回归的从零开始实现 中,代码的执行顺序决定了整个模型的搭建和训练过程。下面我们按照 代码执行顺序 逐步拆解每一部分的作用。


1. 导入依赖库

首先,导入所需的 Python 库:

import torch
from torch import nn
from d2l import torch as d2l
  • torch:深度学习框架 PyTorch 的核心库
  • torch.nn:神经网络模块,定义模型结构和损失函数
  • d2l.torchd2l 库封装了一些辅助函数,比如数据加载、可视化等

2. 读取 Fashion-MNIST 数据集

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
  • batch_size = 256:设置 每次训练的批量大小 为 256
  • d2l.load_data_fashion_mnist(batch_size):使用 d2l 提供的函数下载并加载 Fashion-MNIST 数据集,返回 训练集和测试集迭代器(DataLoader)
  • train_iter, test_iter:分别是 训练数据迭代器测试数据迭代器,每次调用时会返回一个 小批量数据

3. 初始化模型参数

num_inputs = 784  # 28 × 28
num_outputs = 10  # 10个类别
W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)
  • num_inputs = 784:每张图片是 28×28 像素,输入层需要 784 个神经元
  • num_outputs = 10Fashion-MNIST 共有 10 个类别
  • W:初始化权重矩阵,形状为 (784, 10),服从 均值为 0,标准差为 0.01 的正态分布
  • b:初始化偏置向量,形状为 (10,),初始值全为 0
  • requires_grad=True开启自动求导,让 PyTorch 计算梯度,以便进行梯度下降优化

4. 定义 Softmax 函数

def softmax(X):
    X_exp = torch.exp(X)  # 计算指数
    partition = X_exp.sum(dim=1, keepdim=True)  # 按行求和,确保概率归一化
    return X_exp / partition  # 计算 softmax
  • torch.exp(X):对 X 逐元素求指数
  • sum(dim=1, keepdim=True):按 求和,确保结果仍然是 列向量,用于概率归一化
  • X_exp / partition:计算 Softmax,即每个类别的概率分布

示例:

X = torch.tensor([[1.0, 2.0, 3.0], [0.5, 1.5, 2.5]])
softmax(X)

输出:

tensor([[0.0900, 0.2447, 0.6652],
        [0.1165, 0.3160, 0.5675]])

说明:

  • 每一行的和都为 1,表示概率分布

5. 定义模型

def net(X):
    return softmax(torch.matmul(X.reshape((-1, num_inputs)), W) + b)
  • X.reshape((-1, num_inputs)):将 输入图像(batch_size, 1, 28, 28) 变为 (batch_size, 784)
  • torch.matmul(..., W) + b:执行 线性变换,计算 O = XW + b
  • softmax(...):使用 Softmax 归一化,将 O 变为 概率分布

6. 定义交叉熵损失函数

def cross_entropy(y_hat, y):
    return -torch.log(y_hat[range(len(y_hat)), y]).mean()
  • y_hat[range(len(y_hat)), y]:获取 y_hat真实标签对应的概率值
  • torch.log(y_hat[...]):对这些概率取 对数
  • mean():计算所有样本的平均损失

示例:

y_hat = torch.tensor([[0.1, 0.2, 0.7], [0.3, 0.4, 0.3]])
y = torch.tensor([2, 1])
loss = cross_entropy(y_hat, y)
  • y_hat[range(len(y_hat)), y] = [0.7, 0.4]
  • -log([0.7, 0.4])
  • 计算均值作为最终损失

7. 计算分类准确率

def accuracy(y_hat, y):
    if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
        y_hat = y_hat.argmax(axis=1)  # 获取最大概率的索引
    cmp = y_hat.type(y.dtype) == y  # 比较预测类别和真实标签
    return float(cmp.type(y.dtype).sum())  # 计算正确数量
  • y_hat.argmax(axis=1):找到最大概率的索引,即预测类别
  • cmp = y_hat == y:比较预测值和真实标签,返回 布尔值数组
  • sum():计算 预测正确的样本数

8. 训练模型

num_epochs, lr = 10, 0.1
updater = lambda batch_size: d2l.sgd([W, b], lr, batch_size)
d2l.train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
  • num_epochs = 10:训练 10 轮
  • lr = 0.1:学习率设为 0.1
  • updater = lambda batch_size: d2l.sgd([W, b], lr, batch_size):定义参数更新函数,使用 随机梯度下降(SGD)
  • d2l.train_ch3(...)
    • 输入
      • net:定义的 Softmax 预测函数
      • train_iter, test_iter:训练和测试数据集
      • cross_entropy:损失函数
      • num_epochs:训练轮数
      • updater:参数更新策略
    • 执行流程
      1. 取出一个小批量 X, y
      2. 计算预测值 y_hat = net(X)
      3. 计算损失 loss = cross_entropy(y_hat, y)
      4. 计算梯度 loss.backward()
      5. 使用 SGD 更新参数 W, b
      6. 评估模型的准确率
      7. 重复 num_epochs

数学推演

数学推导:Softmax 回归

Softmax 回归的数学逻辑主要包括 线性变换Softmax 归一化交叉熵损失计算梯度下降优化 四个核心部分。我们按照模型的执行顺序,一步步列出数学公式。


1. 线性变换(Linear Transformation)

输入

假设输入数据为:
X ∈ R m × n \mathbf{X} \in \mathbb{R}^{m \times n} XRm×n
其中:
- m m m批量大小(batch size)
- n n n特征数(输入维度),对于 Fashion-MNIST n = 784 n = 784 n=784(28×28)

模型的权重矩阵(Weight)和偏置(Bias):
W ∈ R n × c , b ∈ R c \mathbf{W} \in \mathbb{R}^{n \times c}, \quad \mathbf{b} \in \mathbb{R}^{c} WRn×c,bRc
其中:
- c c c类别数(Fashion-MNIST 中 c = 10 c=10 c=10

计算

神经网络的前向传播计算公式:
O = X W + b \mathbf{O} = \mathbf{X} \mathbf{W} + \mathbf{b} O=XW+b
其中:
- O ∈ R m × c \mathbf{O} \in \mathbb{R}^{m \times c} ORm×c未归一化的类别分数(logits)


2. Softmax 函数(Softmax Function)

Softmax 函数用于将未归一化的 logits 转换成 概率分布,公式如下:
y ^ j = e O j ∑ k = 1 c e O k , j = 1 , 2 , . . . , c \hat{y}_j = \frac{e^{O_j}}{\sum_{k=1}^{c} e^{O_k}}, \quad j = 1, 2, ..., c y^j=k=1ceOkeOj,j=1,2,...,c
其中:
- O j O_j Oj j j j个类别的 logits
- y ^ j \hat{y}_j y^j属于类别 j j j的预测概率

  • Softmax 保证了所有类别的概率和为 1
    ∑ j = 1 c y ^ j = 1 \sum_{j=1}^{c} \hat{y}_j = 1 j=1cy^j=1

3. 交叉熵损失(Cross-Entropy Loss)

在分类任务中,我们使用 交叉熵(Cross-Entropy) 作为损失函数:
L = − 1 m ∑ i = 1 m ∑ j = 1 c y i , j log ⁡ ( y ^ i , j ) L = - \frac{1}{m} \sum_{i=1}^{m} \sum_{j=1}^{c} y_{i,j} \log(\hat{y}_{i,j}) L=m1i=1mj=1cyi,jlog(y^i,j)
其中:
- y i , j y_{i,j} yi,j是真实标签(如果样本 i i i属于类别 j j j,则 y i , j = 1 y_{i,j} = 1 yi,j=1,否则 y i , j = 0 y_{i,j} = 0 yi,j=0
- y ^ i , j \hat{y}_{i,j} y^i,j是模型对类别 j j j预测的概率
- m m m是 batch size(小批量样本数)

由于真实标签 y y yone-hot 编码,只有正确类别的概率才会被计算,公式可以简化为:
L = − 1 m ∑ i = 1 m log ⁡ ( y ^ i , y i ) L = - \frac{1}{m} \sum_{i=1}^{m} \log(\hat{y}_{i, y_i}) L=m1i=1mlog(y^i,yi)
其中:
- y i y_i yi样本 i i i的真实类别索引
- y ^ i , y i \hat{y}_{i, y_i} y^i,yi模型预测的正确类别概率


4. 计算梯度(Gradient Computation)

为了使用 梯度下降 进行参数优化,我们需要计算损失函数对 权重 W \mathbf{W} W和偏置 b \mathbf{b} b的梯度

权重梯度 ∂ L ∂ W \frac{\partial L}{\partial W} WL

损失函数 关于 权重矩阵 求导:
∂ L ∂ W = 1 m ∑ i = 1 m X i T ( y ^ i − y i ) \frac{\partial L}{\partial W} = \frac{1}{m} \sum_{i=1}^{m} \mathbf{X}_i^T (\hat{\mathbf{y}}_i - \mathbf{y}_i) WL=m1i=1mXiT(y^iyi)
其中:
- X i \mathbf{X}_i Xi输入数据
- y ^ i − y i \hat{\mathbf{y}}_i - \mathbf{y}_i y^iyi预测值与真实值的误差

偏置梯度 ∂ L ∂ b \frac{\partial L}{\partial b} bL

损失函数 关于 偏置向量 求导:
∂ L ∂ b = 1 m ∑ i = 1 m ( y ^ i − y i ) \frac{\partial L}{\partial b} = \frac{1}{m} \sum_{i=1}^{m} (\hat{\mathbf{y}}_i - \mathbf{y}_i) bL=m1i=1m(y^iyi)

  • 这个梯度是 所有样本误差的平均值

5. 梯度下降(Gradient Descent)

使用 随机梯度下降(SGD) 更新参数:
W : = W − η ∂ L ∂ W W := W - \eta \frac{\partial L}{\partial W} W:=WηWL
b : = b − η ∂ L ∂ b b := b - \eta \frac{\partial L}{\partial b} b:=bηbL
其中:
- η \eta η学习率(Learning Rate),控制更新幅度

  • 更新方向: 沿着梯度的反方向调整参数,使损失函数逐步减小

6. 训练过程总结

整个 Softmax 回归训练过程 可以用以下数学逻辑总结:

  1. 输入数据:从 Fashion-MNIST 读取批量数据 X \mathbf{X} X和真实标签 y y y
  2. 前向传播
    O = X W + b O = XW + b O=XW+b
    y ^ = softmax ( O ) \hat{y} = \text{softmax}(O) y^=softmax(O)
  3. 计算损失
    L = − 1 m ∑ i = 1 m log ⁡ ( y ^ i , y i ) L = - \frac{1}{m} \sum_{i=1}^{m} \log(\hat{y}_{i, y_i}) L=m1i=1mlog(y^i,yi)
  4. 计算梯度
    ∂ L ∂ W = 1 m ∑ i = 1 m X i T ( y ^ i − y i ) \frac{\partial L}{\partial W} = \frac{1}{m} \sum_{i=1}^{m} X_i^T (\hat{y}_i - y_i) WL=m1i=1mXiT(y^iyi)
    ∂ L ∂ b = 1 m ∑ i = 1 m ( y ^ i − y i ) \frac{\partial L}{\partial b} = \frac{1}{m} \sum_{i=1}^{m} (\hat{y}_i - y_i) bL=m1i=1m(y^iyi)
  5. 参数更新(SGD)
    W : = W − η ∂ L ∂ W W := W - \eta \frac{\partial L}{\partial W} W:=WηWL
    b : = b − η ∂ L ∂ b b := b - \eta \frac{\partial L}{\partial b} b:=bηbL
  6. 重复以上步骤,直到损失收敛或训练完成

结论

  • Softmax 回归本质上是一个线性分类器,通过 Softmax 归一化将 logits 转换成概率分布
  • 交叉熵损失 评估模型的预测概率与真实标签的匹配程度
  • 梯度下降优化 更新参数,使得模型能够更准确地分类
  • 训练过程不断 迭代前向传播、计算损失、计算梯度、更新参数,直到收敛

这样,Softmax 回归模型就能对 Fashion-MNIST 数据集进行分类!🔥

问题 QA

交叉熵损失的梯度与权重 𝑊 梯度的关系

交叉熵损失的梯度与权重 W W W梯度的关系

交叉熵损失函数的梯度在 Softmax 训练中起着核心作用,它直接影响权重 W W W的梯度计算。我们详细推导两者的关系。


1. 交叉熵损失函数

对于一个样本 i i i,假设:

  • 输入特征向量 X i X_i Xi(维度 1 × n 1 \times n 1×n
  • 权重矩阵 W W W(维度 n × c n \times c n×c
  • 未归一化得分(logits)
    z i = X i W ( 1 × c ) z_i = X_i W \quad (1 \times c) zi=XiW(1×c)
  • Softmax 计算出的类别概率
    y ^ i = softmax ( z i ) = e z i ∑ j e z i j \hat{y}_i = \text{softmax}(z_i) = \frac{e^{z_i}}{\sum_j e^{z_{ij}}} y^i=softmax(zi)=jezijezi
  • 真实标签的 One-hot 编码 y i y_i yi(维度 1 × c 1 \times c 1×c
  • 交叉熵损失
    L i = − ∑ j y i j log ⁡ y ^ i j L_i = - \sum_{j} y_{ij} \log \hat{y}_{ij} Li=jyijlogy^ij

对于 整个批量(batch) 样本(大小 m m m),总损失是:
L = − 1 m ∑ i = 1 m ∑ j = 1 c y i j log ⁡ y ^ i j L = - \frac{1}{m} \sum_{i=1}^{m} \sum_{j=1}^{c} y_{ij} \log \hat{y}_{ij} L=m1i=1mj=1cyijlogy^ij


2. 交叉熵损失对 Softmax 输出的梯度

损失函数对 Softmax 预测值 y ^ i \hat{y}_i y^i求导:
∂ L ∂ y ^ i = − y i y ^ i \frac{\partial L}{\partial \hat{y}_i} = -\frac{y_i}{\hat{y}_i} y^iL=y^iyi

使用链式法则结合 Softmax 导数,可得:
∂ L ∂ z i = y ^ i − y i \frac{\partial L}{\partial z_i} = \hat{y}_i - y_i ziL=y^iyi

这说明:

  • 交叉熵损失对 logits(未归一化的得分)求导后,刚好等于 Softmax 预测值与真实标签的误差。
  • 这是梯度计算的核心步骤。

3. 计算权重 W W W的梯度

根据链式法则:
∂ L ∂ W = ∂ L ∂ z ⋅ ∂ z ∂ W \frac{\partial L}{\partial W} = \frac{\partial L}{\partial z} \cdot \frac{\partial z}{\partial W} WL=zLWz

已知:
∂ L ∂ z = Y ^ − Y \frac{\partial L}{\partial z} = \hat{Y} - Y zL=Y^Y
z = X W ⇒ ∂ z ∂ W = X T z = X W \quad \Rightarrow \quad \frac{\partial z}{\partial W} = X^T z=XWWz=XT

因此:
∂ L ∂ W = X T ( Y ^ − Y ) \frac{\partial L}{\partial W} = X^T (\hat{Y} - Y) WL=XT(Y^Y)

如果有 m m m个样本(batch 形式),则梯度取均值:
∂ L ∂ W = 1 m ∑ i = 1 m X i T ( y ^ i − y i ) \frac{\partial L}{\partial W} = \frac{1}{m} \sum_{i=1}^{m} X_i^T (\hat{y}_i - y_i) WL=m1i=1mXiT(y^iyi)


4. 关系总结

  • 交叉熵损失对 Softmax 的梯度
    ∂ L ∂ z = y ^ − y \frac{\partial L}{\partial z} = \hat{y} - y zL=y^y
  • 权重矩阵 W W W的梯度
    ∂ L ∂ W = X T ( y ^ − y ) \frac{\partial L}{\partial W} = X^T (\hat{y} - y) WL=XT(y^y)

也就是说:

  1. 交叉熵损失对 logits 的梯度( y ^ − y \hat{y} - y y^y)决定了整个参数的梯度传播
  2. 权重梯度 ∂ L ∂ W \frac{\partial L}{\partial W} WL是误差项 ( y ^ − y ) (\hat{y} - y) (y^y)与输入特征 X X X计算得到的

这解释了为什么 Softmax 交叉熵的梯度计算可以直接通过误差项 ( y ^ − y ) (\hat{y} - y) (y^y)计算,而不需要显式计算 Softmax 的导数。


http://www.kler.cn/a/539574.html

相关文章:

  • 01单片机上电后没有正常运行怎么办
  • npm与包
  • 物联网的三层架构:感知层、网络层与应用层
  • 嵌入式工程师面试准备(客观题准备)
  • Windows安装cwgo,一直安装的是linux平台的
  • F - Building Roads S
  • 【C++学习篇】C++11第二期学习
  • Palatir和它的AIP
  • Redis 事务和 “锁机制”——> 并发秒杀处理的详细说明
  • 2025新鲜出炉--前端面试题(一)
  • Transformer基础 多头自注意力机制
  • SQL自学,mysql从入门到精通 --- 第 6 天,sql中的子句使用
  • 开源+降本浅析及Deepseek模型在countdown游戏上的初探
  • 蓝桥杯C语言组:图论问题
  • 大数据项目4:基于spark的智慧交通项目设计与实现
  • 传统营销架构在当下如何进行优化转型?
  • 程序猿成长之路之数据挖掘篇——决策树分类算法(2)——构建决策树
  • transformers学习笔记——初级篇
  • Spring Boot 对接深度求索接口实现知识问答功能
  • 第433场周赛:变长子数组求和、最多 K 个元素的子序列的最值之和、粉刷房子 Ⅳ、最多 K 个元素的子数组的最值之和
  • elasticsearch实战应用从入门到高效使用java集成es快速上手
  • 【漫话机器学习系列】085.自助采样法(Bootstrap Sampling)
  • selenium4.0 入门案例
  • Web开发概念解析
  • 云开发 AI 实战—基于腾讯云开发 Copilot快速开发陕西家乡小程序实战
  • Linux proc虚拟文件系统