- 人工智能
- 深度学习
- 机器学习
- 教程
【免费下载链接】d2l-zh
《动手学深度学习》:面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。
《动手学深度学习》(d2l-zh)的“线性神经网络”一章是整个教程承上启下的核心起点:在正式接触深度神经网络之前,它以经典统计学习中的线性回归与softmax 回归为载体,完整呈现了一次神经网络训练所需的全部要素——定义网络架构、处理数据、指定损失函数与驱动模型训练。读完本章,你将掌握“从零实现”与“框架高级 API 简洁实现”两套并行的建模路径,理解损失函数、小批量随机梯度下降、矢量化加速与交叉熵等概念,为后续卷积神经网络、循环神经网络乃至 Transformer 等复杂模型打下坚实基础。
章节定位:为什么用“线性”模型开启深度学习的旅程
本章开篇即点明了它的教学目标(见 chapter_linear-networks/index.md):
在介绍深度神经网络之前,我们需要了解神经网络训练的基础知识。本章将介绍神经网络的整个训练过程,包括:定义简单的神经网络架构、数据处理、指定损失函数和如何训练模型。
这一表述定义了本章的四大主线:
- 定义简单的神经网络架构——线性回归与 softmax 回归都可以被描述为“单层神经网络”;
- 数据处理——从人工合成数据集到 Fashion-MNIST 真实图像数据集,掌握小批量读取与打乱;
- 指定损失函数——平方损失(回归)与交叉熵损失(分类);
- 如何训练模型——以小批量随机梯度下降为核心的参数更新循环。
之所以选择线性模型作为起点,是因为经典统计学习技术中的线性回归和 softmax 回归可以视为线性神经网络。它们足够简单:线性回归存在解析解、损失平面只有一个极小值,便于读者把注意力集中在“训练流程本身”而不是复杂的优化问题上;同时它们又足够通用:softmax 回归已经具备完整的分类建模要素(概率输出、独热编码、交叉熵),能为后续更复杂的技术奠定基础。
章节内容地图:七节内容一次看清
本章共包含 7 个小节,构成了“理论 → 从零实现 → 简洁实现”的完整闭环:
| 小节 | 主题 | 核心要点 |
|---|---|---|
| 线性回归 | 理论篇 | 线性模型、损失函数、解析解、小批量随机梯度下降、矢量化、正态分布与平方损失、单层神经网络视角 |
| 线性回归的从零开始实现 | 实践篇 A | 仅用张量与自动微分,从数据生成、小批量迭代器到 SGD 训练循环全部手写 |
| 线性回归的简洁实现 | 实践篇 B | 用Sequential、全连接层、框架损失函数与优化器实现同样任务 |
| softmax 回归 | 理论篇 | 分类问题、独热编码、softmax 运算、交叉熵损失、信息论基础 |
| 图像分类数据集 | 数据篇 | Fashion-MNIST 数据集的读取、类别与形状 |
| softmax 回归的从零开始实现 | 实践篇 C | 手写 softmax 前向、交叉熵与训练评估 |
| softmax 回归的简洁实现 | 实践篇 D | 使用框架高级 API 快速搭建分类模型 |
线性回归:回归问题的经典起点
线性模型与仿射变换
线性回归回答的是“预测多少”的问题(房价、住院天数、零售销量等)。其核心假设是目标 $y$ 可以表示为特征 $\mathbf{x}$ 的加权和加上偏置:
$$\hat{y} = \mathbf{w}^\top \mathbf{x} + b$$
其中 $\mathbf{w}$ 称为权重(weight),决定每个特征对预测的影响;$b$ 称为偏置(bias)/偏移量/截距。即使现实中不存在“面积为 0 的房子”,模型仍然需要偏置项——没有它,模型的表达能力会受到限制。严格来说,上式是输入特征的一个仿射变换(affine transformation):先通过加权和做线性变换,再通过偏置做平移。将 $n$ 个样本堆叠为矩阵 $\mathbf{X} \in \mathbb{R}^{n \times d}$ 后,整个数据集的预测可写为 $\hat{\mathbf{y}} = \mathbf{X}\mathbf{w} + b$,求和过程依赖广播机制。
损失函数:平方误差
要拟合数据,首先需要量化“预测与真实之间的差距”。本章采用回归问题最常用的平方误差函数:
$$l^{(i)}(\mathbf{w}, b) = \frac{1}{2}\left(\hat{y}^{(i)} - y^{(i)}\right)^2$$
常数 $\frac{1}{2}$ 没有本质差别,但求导后系数为 1,形式更简洁。由于平方项的放大作用,较大的预测偏差会带来显著更大的损失。整个训练集上的总损失为各样本损失的均值:
$$L(\mathbf{w}, b) = \frac{1}{n}\sum_{i=1}^n l^{(i)}(\mathbf{w}, b)$$
训练目标即寻找使 $L$ 最小的参数 $(\mathbf{w}^, b^)$。
解析解与随机梯度下降
线性回归是极少数存在解析解的模型:把偏置并入 $\mathbf{w}$ 后,令损失对参数的导数为 0,可得
$$\mathbf{w}^* = (\mathbf{X}^\top \mathbf{X})^{-1}\mathbf{X}^\top \mathbf{y}$$
但解析解对问题限制严格,无法推广到深度学习。因此本章正式引入小批量随机梯度下降(minibatch stochastic gradient descent):每步随机抽取固定数量样本构成小批量 $\mathcal{B}$,计算该批量平均损失关于参数的梯度,再沿负梯度方向以学习率 $\eta$ 更新参数:
$$(\mathbf{w}, b) \leftarrow (\mathbf{w}, b) - \frac{\eta}{|\mathcal{B}|}\sum_{i \in \mathcal{B}} \partial_{(\mathbf{w},b)} l^{(i)}(\mathbf{w}, b)$$
这里 $|\mathcal{B}|$ 是批量大小(batch size),$\eta$ 是学习率(learning rate)。二者不随训练更新,属于超参数(hyperparameter),通常依据独立验证数据集上的评估结果反复调整(调参)。算法流程可概括为两步:初始化参数(如随机初始化)→ 反复抽取小批量并按负梯度更新。
值得注意的是,即使函数是线性且无噪声,有限步数的梯度下降也无法让损失精确达到最小值;而对深度神经网络这类复杂模型,损失平面往往存在多个极小值,实践者追求的并非训练损失最小,而是对未见数据的泛化能力。给定训练好的模型 $\hat{\mathbf{w}}^\top \mathbf{x} + \hat{b}$,用特征估计新目标的过程称为预测(prediction)或推断(inference)。
矢量化加速:为什么不用 for 循环
训练时我们希望同时处理整个小批量,为此必须对计算矢量化,利用线性代数库而非 Python 中开销高昂的 for 循环。本章用“两个全 1 的 10000 维向量相加”做了对比实验:一种方法是逐元素 for 循环,另一种是直接调用重载的+运算符,后者通常带来数量级的加速(linear-regression.md 中的Timer类专门用于这类运行时间基准测试)。
正态分布与平方损失:从极大似然看损失函数
平方损失并非拍脑袋选择的:若假设观测噪声服从正态分布 $y = \mathbf{w}^\top \mathbf{x} + b + \epsilon$,$\epsilon \sim \mathcal{N}(0, \sigma^2)$,则写出数据的似然后,最大化似然等价于最小化负对数似然。忽略与参数无关的常数项后,负对数似然恰好退化为均方误差的形式。因此,在高斯噪声假设下,最小化均方误差等价于对线性模型的极大似然估计——这是“损失函数从哪来”的重要理论依据。
从线性回归到深度网络:单层神经网络视角
线性回归还可以用神经网络的语言描述:输入层包含 $d$ 个输入(特征维度),输出层有 1 个输出,由于计算层数不计输入层,线性回归是一个层数为 1的单层神经网络(img/singleneuron.svg)。每个输入都与每个输出相连,这种结构称为全连接层(fully-connected layer)或稠密层(dense layer),下一章将详细讨论由这些层组成的多层网络。本章还从生物神经元(树突接收加权输入、细胞核汇聚求和、轴突输出)的历史视角解释了为何线性模型是人工神经元的起点,并提醒读者:当代深度学习的灵感更多来自数学、统计学与计算机科学,而非神经科学本身。
线性回归的从零实现:亲手搭建训练流水线
linear-regression-scratch.md 用仅张量与自动微分的方式实现完整方法(数据流水线、模型、损失函数、优化器),确保读者真正理解每一步在做什么。这套代码中的关键函数均以#@save注解保存进本书的d2l工具包,例如 d2l/torch.py 中的synthetic_data与load_array,后续章节可直接复用。
- 生成数据集:用真实参数 $\mathbf{w} = [2, -3.4]^\top$、$b = 4.2$ 加标准差 0.01 的正态噪声,生成 1000 个样本的合成数据 $\mathbf{y} = \mathbf{X}\mathbf{w} + b + \epsilon$,任务就是用这些有限样本“恢复”原参数;
- 读取数据集:手写
data_iter函数——先random.shuffle打乱索引,再按batch_size切片并用生成器逐批产出特征与标签;批量大小设为 10。书中明确指出该实现教学友好但效率低,实际项目应使用框架内置的数据迭代器(可处理文件与数据流); - 初始化模型参数:权重从均值 0、标准差 0.01 的正态分布采样,偏置初始化为 0(PyTorch 中设置
requires_grad=True以开启梯度跟踪); - 定义模型:
linreg(X, w, b)即一次矩阵-向量乘法加偏置,标量 $b$ 依靠广播机制加到向量每个分量; - 定义损失函数:
squared_loss实现平方损失,其中reshape保证预测与真实标签形状一致; - 定义优化算法:
sgd(params, lr, batch_size)在每个参数上执行param -= lr * param.grad / batch_size,除以批量大小是为了使步长不依赖批量大小的选择; - 训练循环:超参数设为
lr = 0.03、num_epochs = 3。每个迭代周期(epoch)用data_iter完整遍历一次数据集,对每个小批量执行:前向计算损失 →backward()反向传播存储梯度 →sgd更新参数,随后打印该周期全量损失。
训练结束后,将学习到的参数与真实参数做差(true_w - w),可以直观验证收敛效果。书中特别提醒:机器学习的重点通常不是恢复真实参数,而是实现对未见数据的高精度预测。
线性回归的简洁实现:框架高级 API 的威力
linear-regression-concise.md 展示了现代深度学习框架如何自动化训练中的重复性工作——数据迭代器、损失函数、优化器和神经网络层都是现成组件。
- 读取数据集:
load_array把(features, labels)包装为框架的数据集与数据迭代器,is_train=True表示每个 epoch 内打乱数据(PyTorch 对应TensorDataset+DataLoader); - 定义模型:
net = nn.Sequential(nn.Linear(2, 1))。Sequential将多个层串联,数据依次流过每一层;全连接层在 PyTorch/PaddlePaddle 中叫Linear、在 MXNet/Keras 中叫Dense。两个参数分别指定输入特征数(2)与输出特征数(1); - 初始化参数:
net[0].weight.data.normal_(0, 0.01)、net[0].bias.data.fill_(0)直接改写参数值(MXNet/Keras 支持init.Normal(sigma=0.01)等初始化器,且初始化是推迟执行的——直到第一次传入数据才真正完成,因此初始化前不可访问参数); - 损失函数:
nn.MSELoss()(PyTorch/Paddle)、gluon.loss.L2Loss()(MXNet)、tf.keras.losses.MeanSquaredError()(TensorFlow),默认返回所有样本损失的平均值; - 优化器:
torch.optim.SGD(net.parameters(), lr=0.03)(其他框架对应Trainer/optimizers.SGD),只需指定学习率; - 训练循环:与从零实现几乎相同,只是每步调用
trainer.zero_grad()(清梯度)→l.backward()→trainer.step()。最后同样通过net[0].weight.data读取参数并与真实参数比较。
这组对比实验的结论贯穿全书:“从零实现”帮助理解原理,“简洁实现”提升开发效率——当模型变得更复杂时,高级 API 的优势将急剧放大。
softmax 回归:从回归走向分类
分类问题与独热编码
回归回答“多少”,分类回答“哪一个”:邮件是否垃圾、图像是猫是狗还是鸡、用户是否注册。分类问题的标签不适合用整数 $y \in {1,2,3}$ 直接表示(整数暗示了不存在的类别顺序),因此采用统计学中的独热编码(one-hot encoding):标签是一个与类别数等长的向量,对应类别分量为 1、其余为 0,如 $(1,0,0)$ 代表“猫”、$(0,1,0)$ 代表“鸡”、$(0,0,1)$ 代表“狗”。
网络架构与全连接层的参数开销
与线性回归类似,softmax 回归需要与输出类别等量的仿射函数。以 4 特征 3 类别为例,需要 12 个权重标量与 3 个偏置标量,每个输入产生三个未规范化的预测(logit)$o_1, o_2, o_3$,向量形式为 $\mathbf{o} = \mathbf{W}\mathbf{x} + \mathbf{b}$。它同样是一个单层神经网络(img/softmaxreg.svg),输出层因每个输出都依赖全部输入而成为全连接层。
本节还提前点出全连接层的代价:对 $d$ 输入、$q$ 输出的全连接层,参数开销为 $\mathcal{O}(dq)$,在实践中可能高得令人望而却步——这是后续章节引入卷积等结构化设计的动机之一。
softmax 运算
线性层的输出不能直接当概率:它们可能为负、总和也不为 1。softmax 函数通过对每个 logit 求幂确保非负,再除以总和实现归一化:
$$\hat{y}_j = \frac{\exp(o_j)}{\sum_k \exp(o_k)}$$
由此 $\hat{\mathbf{y}}$ 成为合法的概率分布,且不改变 logit 之间的相对大小次序($\operatorname*{argmax}_j \hat{y}_j = \operatorname*{argmax}_j o_j$),因此预测时仍可按最大 logit 选取类别。尽管 softmax 是非线性函数,softmax 回归的输出仍由输入的仿射变换决定,所以它依然是线性模型。对小批量样本 $\mathbf{X} \in \mathbb{R}^{n \times d}$,softmax 按行执行:$\mathbf{O} = \mathbf{X}\mathbf{W} + \mathbf{b}$ 后逐行归一化,从而充分利用 GPU 的矩阵运算能力。
交叉熵损失与信息论基础
分类的损失函数依然从极大似然估计出发。对独热标签 $\mathbf{y}$ 与预测 $\hat{\mathbf{y}}$,负对数似然给出:
$$l(\mathbf{y}, \hat{\mathbf{y}}) = -\sum_{j=1}^q y_j \log \hat{y}_j$$
这就是交叉熵损失(cross-entropy loss)。把 softmax 定义代入后求导,可得一个极其简洁的结果:损失关于 logit $o_j$ 的导数等于softmax 分配的概率减去独热标签分量——即“预测与实际的差异”,与回归中“观测值减估计值”的梯度形式如出一辙,这并非巧合,而是指数族分布模型的共性,使梯度计算在实践中非常容易。
本节还用信息论解释了交叉熵的深层含义:分布的熵$H[P] = \sum_j -P(j)\log P(j)$ 量化了对该分布数据编码所需的最少“纳特”数(1 纳特 ≈ 1.44 比特);事件概率越低、信息量$-\log P(j)$ 越大(越“惊异”)。交叉熵 $H(P,Q)$ 可理解为“持有主观概率 $Q$ 的观察者看到按 $P$ 生成数据时的预期惊异”,当 $P=Q$ 时达到最小值。因此交叉熵分类目标可以同时被理解为:最大化观测数据的似然、最小化传达标签所需的惊异。
模型预测与评估
训练完成后,对任意样本给出每个类别的概率,取概率最高者作为预测类别,并与真实标签比较。本章用精度(accuracy,正确预测数 / 预测总数)作为评估指标。
图像分类数据集:Fashion-MNIST
image-classification-dataset.md 选择Fashion-MNIST作为分类实验数据集——MNIST 过于简单,不适合作为基准。该数据集包含10 个类别(t-shirt、trouser、pullover、dress、coat、sandal、shirt、sneaker、bag、ankle boot),每类训练集 6000 张、测试集 1000 张,即训练集 60000 张、测试集 10000 张;每张为 28×28 像素、单通道的灰度图,展开后恰为 784 维特征,适合线性模型处理。测试集不参与训练,仅用于评估模型性能。
各框架均提供内置加载方式:PyTorch 用torchvision.datasets.FashionMNIST配合transforms.ToTensor()(把 PIL 图像转为 32 位浮点并除以 255 归一化到 0~1),TensorFlow 用tf.keras.datasets.fashion_mnist.load_data(),Paddle 用paddle.vision.datasets.FashionMNIST。本节还定义了get_fashion_mnist_labels函数,在数字标签索引与文本名称间转换,便于可视化。
softmax 回归的两套实现:从零手写到高级 API
- 从零实现(softmax-regression-scratch.md):沿用 Fashion-MNIST,批量大小设为256。要点包括:展平图像(
reshape为二维矩阵)、softmax 运算的矢量化实现、交叉熵损失的手写、训练循环与精度评估。与线性回归从零实现呼应,帮助读者理解 softmax 前向与反向的每个细节; - 简洁实现(softmax-regression-concise.md):直接用
nn.Sequential(nn.Linear(784, 10))定义 784→10 的线性层,配合框架的CrossEntropyLoss与SGD优化器,代码量大幅缩减,训练流程与线性回归简洁实现高度相似——这正体现了“训练循环”这一模式在深度学习中的通用性。
学习路线与后续衔接
本章是全书训练范式的最小完备示例。阅读时可对照以下仓库资源深化理解:
- 四个框架后端各有一套
d2l工具包,synthetic_data、load_array、sgd等#@save函数均可在 d2l/torch.py、d2l/mxnet.py、d2l/tensorflow.py、d2l/paddle.py 中查到对应实现,文档代码块内的#@tab pytorch、#@tab mxnet等标记表明同一段代码的多框架版本; - 本章依赖的前置知识包括张量与广播机制(chapter_preliminaries/ndarray.md)、自动微分(chapter_preliminaries/autograd.md)、数据预处理(chapter_preliminaries/pandas.md);
- 后续章节将基于本章的训练循环,引入多层感知机(chapter_multilayer-perceptrons/index.md)、更精细的优化算法(chapter_optimization/index.md)以及卷积等结构化网络。
本章的核心结论可概括为四句话:机器学习模型的四大要素是训练数据、损失函数、优化算法与模型本身;矢量化既让数学表达简洁也让运行更快;最小化目标函数与极大似然估计等价;线性回归与 softmax 回归都是单层神经网络。吃透本章的“理论 → 从零实现 → 简洁实现”节奏,后续所有章节的代码都将在此范式上演进。
- 人工智能
- 深度学习
- 机器学习
- 教程
【免费下载链接】d2l-zh
《动手学深度学习》:面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。
相关推荐
Mesop 应用性能优化实战:定位瓶颈、压缩 State 负载与横向扩容
Mesop 应用性能优化实战:定位瓶颈、压缩 State 负载与横向扩容 本文基于 Mesop 官方性能指南,讲解如何诊断并解决 Mesop 应用常见的性能问题
人工智能深度学习机器学习教程动手学深度学习(d2l-zh)实战:softmax回归从零开始实现
动手学深度学习(d2l zh)实战:softmax回归从零开始实现 本文基于《动手学深度学习》中文版开源仓库(d2l zh)的 softmax 回归从零实现章节
人工智能深度学习机器学习教程终极Gorgonia神经网络构建指南:从线性回归到深度学习的完整教程
终极Gorgonia神经网络构建指南:从线性回归到深度学习的完整教程 Gorgonia是一个强大的Go语言机器学习库,专门用于构建和训练神经网络模型。这个完整的
机器学习深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考