教程链接: 【[2025][PyTorch]《RethinkFun深度学习》教程,零基础一站直达大模型DeepSeek-哔哩哔哩】
电子书网站: RethinkFun 深度学习电子书
第一章:初识深度学习
1.1 人工智能、机器学习与深度学习
三者是逐层包含的关系:
人工智能(AI)
└── 机器学习(Machine Learning)
└── 深度学习(Deep Learning)
- 人工智能 关注如何让机器表现出感知、推理、决策和生成等智能行为。
- 机器学习 不再为每一种情况手写规则,而是让算法从数据中寻找规律。
- 深度学习 是机器学习的一类方法,主要依靠多层神经网络自动学习数据中的层级特征。
传统程序通常是“规则 + 数据 → 结果”;机器学习更像是“数据 + 答案 → 学到规则”。深度学习进一步减少了人工设计特征的工作:模型会在训练过程中逐层形成适合任务的表示。
例如图像分类中,浅层可能先识别边缘和纹理,中间层逐渐组合出局部结构,深层再形成与类别相关的高级特征。大语言模型也是同样的思想,只是输入变成了 Token 序列,模型通过大量参数学习语言中的关系。
1.2 如何学习深度学习
深度学习确实依赖线性代数、微积分和概率统计,但不必等到完整学完所有数学课程才开始实践。更有效的路径是:
- 先掌握当前算法真正需要的数学概念;
- 尽快进入模型和代码,建立直觉;
- 遇到不理解的公式或算法时,再回到数学查漏补缺;
- 让“数学概念—模型结构—代码实现”反复对应。
这一阶段需要先建立三个意识:
- 形状意识:任何张量运算前,先确认每一维代表什么。
- 函数意识:神经网络本质上是由许多函数复合而成的可学习函数。
- 优化意识:训练就是寻找一组参数,让损失函数尽可能小。
PyTorch 的作用是把这些数学对象落实成可计算的张量,并通过自动微分帮助我们计算梯度。但框架只能代替计算,不能代替对“为什么这样计算”的理解。
第二章:深度学习里的线性代数
2.1 向量:把一个对象表示成一组有序数
标量(Scalar) 是单一数值,例如年龄 20、体重 54 kg。向量(Vector) 是由若干标量组成的有序数列。
一个学生可以表示为:
x = [年龄, 身高, 体重] = [12, 175, 60]
这里每个分量都有确定含义,因此顺序不能随意交换。在机器学习中,一个样本常用一个向量表示;多个样本放在一起,就形成一个矩阵。
向量的常见运算包括:
- 加法:对应分量相加;
- 数乘:标量乘以每个分量,相当于缩放向量;
- 减法:可理解为加上一个经过
-1缩放的向量; - 模长:衡量向量的长度,
||v|| = sqrt(v₁² + v₂² + ... + vₙ²)。
用 PyTorch 表示向量与批量数据:
import torch
x = torch.tensor([12.0, 175.0, 60.0])
batch = torch.tensor([
[12.0, 175.0, 60.0],
[13.0, 145.0, 50.0],
])
print(x.shape) # torch.Size([3])
print(batch.shape) # torch.Size([2, 3]):2 个样本,每个样本 3 个特征
print(batch.mean(dim=0)) # 按特征求均值
2.2 基、张成空间与线性相关
向量中的数字不只可以理解成坐标,也可以理解成对基向量的缩放系数。
二维空间的标准基为:
i = [1, 0]
j = [0, 1]
[3, 2] = 3i + 2j
张成空间 是指通过一组向量的所有线性组合能够到达的空间。
- 两个不共线的二维向量可以张成整个二维平面;
- 两个共线向量只能张成一条直线;
- 三维空间中的三个向量可能张成三维空间、一个平面、一条直线或一个点。
如果一组向量中至少有一个可以由其他向量线性组合得到,这组向量就是 线性相关 的。一个向量空间的基必须同时满足:
- 能够张成整个空间;
- 基向量之间线性无关。
这解释了为什么“维度”不只是数字个数,还意味着有多少个彼此独立的方向。
2.3 线性变换与矩阵
线性变换可以理解为一个“输入向量、输出向量”的函数,并满足:
T(u + v) = T(u) + T(v)
T(cv) = cT(v)
它保留向量之间的线性关系,具有两个直观性质:直线在变换后仍是直线,原点在变换后仍位于原点。
矩阵就是线性变换的数字表示。只要记录标准基经过变换后落在哪里,就能确定整个变换。矩阵的每一列可以看作对应标准基变换后的结果。
以二维向量沿 y 轴镜像为例:
A = [-1 0]
[ 0 1]
b = [2, 1]ᵀ
Ab = [-2, 1]ᵀ
单位矩阵 由标准基组成,对向量进行变换后仍得到原向量。非方阵则可以改变向量维度:一个 m × n 矩阵可以把 n 维向量映射到 m 维空间。
矩阵乘法可以理解为连续执行线性变换。若 A 的形状为 m × n,B 的形状为 n × p,则 AB 的形状为 m × p。中间维度必须相等。
在深度学习中,矩阵主要承担两种角色:
- 存储数据:每一行通常是一个样本,每一列是一个特征;
- 存储参数:作为线性变换,把输入特征映射到新的表示空间。
因此全连接层可以写为:
Y = XW + b
X: [batch_size, in_features]
W: [in_features, out_features]
b: [out_features]
Y: [batch_size, out_features]
对应的 PyTorch 写法:
import torch
from torch import nn
x = torch.randn(32, 10) # 32 个样本,每个样本 10 个特征
layer = nn.Linear(10, 4)
y = layer(x)
print(y.shape) # torch.Size([32, 4])
复习重点:遇到矩阵乘法错误时,不要先改代码,先把每个张量的形状和每一维含义写出来。
2.4 点乘与余弦相似度
两个等维向量的点乘结果是一个标量:
a · b = Σ aᵢbᵢ = ||a|| ||b|| cosθ
因此余弦相似度为:
cosθ = (a · b) / (||a|| ||b||)
- 接近
1:方向相近; - 接近
0:接近正交,方向关系弱; - 接近
-1:方向相反。
余弦相似度关注方向而非绝对长度,适合比较不同尺度的特征向量。在人脸识别、文本向量检索和 Embedding 相似度计算中都很常见。
import torch
import torch.nn.functional as F
a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([2.0, 4.0, 6.0])
similarity = F.cosine_similarity(a, b, dim=0)
print(similarity) # 接近 1
2.5 叉乘
叉乘主要针对三维向量,结果仍是一个向量:
||a × b|| = ||a|| ||b|| sinθ
结果方向同时垂直于 a 和 b,可以用右手定则判断。叉乘不满足交换律,交换顺序会让结果方向相反:a × b = -(b × a)。
叉乘在普通神经网络训练中不如点乘常见,但在三维视觉、计算机图形学、法向量计算和空间几何中很重要。
第三章:深度学习里的微积分
3.1 极限与无穷小
极限描述“自变量不断接近某个值时,函数值趋近哪里”。导数和积分都建立在极限之上。
无穷小 不是等于 0,而是在某个变化过程中趋近于 0 的量。如果两个无穷小之比的极限:
- 为非零常数:二者是同阶无穷小;
- 为 0:分子是分母的高阶无穷小。
例如当 x → 0 时,x² / x = x → 0,所以 x² 是比 x 更高阶的无穷小,也就是 x² 更快趋近于 0。
3.2 导数:某一点的瞬时变化率
导数统一描述了瞬时速度、曲线切线斜率以及函数在某一点的变化率:
f'(x₀) = lim(Δx→0) [f(x₀ + Δx) - f(x₀)] / Δx
几何上,可以先用曲线上两点组成割线,再让第二个点无限接近第一个点;割线的极限位置就是切线。
导数与连续的关系:
- 可导一定连续;
- 连续不一定可导,例如
f(x)=|x|在x=0处连续,但左右导数不同,因此不可导。
若某点可导且取得局部极值,该点导数通常为 0。但“导数为 0”只是寻找极值的候选条件,不代表一定取得极值。
3.3 常用求导公式
| 原函数 | 导函数 |
|---|---|
C |
0 |
xⁿ |
nxⁿ⁻¹ |
eˣ |
eˣ |
aˣ |
aˣ ln a |
ln x |
1/x |
logₐx |
1/(x ln a) |
sin x |
cos x |
cos x |
-sin x |
3.4 导数运算法则与链式法则
(u + v)' = u' + v'
(uv)' = u'v + uv'
(u/v)' = (u'v - uv') / v²
复合函数 y = f(g(x)) 使用链式法则:
dy/dx = (dy/du) · (du/dx),其中 u = g(x)
链式法则是理解神经网络 反向传播 的核心。神经网络由多层函数复合而成,反向传播就是从损失函数开始,沿计算图从后向前不断应用链式法则,把梯度传回每一层参数。
3.5 微分:用线性部分近似局部变化
若函数在 x₀ 附近的增量满足:
Δy = AΔx + o(Δx)
则函数在该点可微,并记作:
dy = A dx
其中 A = f'(x₀)。微分的核心思想是 以直代曲:在足够小的局部范围内,用切线近似曲线,把非线性问题局部线性化。
一元函数中,可微与可导等价。导数强调变化率,微分强调由自变量微小变化引起的因变量线性变化。
3.6 偏导数
模型的损失函数通常依赖大量参数,因此需要从一元函数走向多元函数。
对 z=f(x,y):
- 求
∂z/∂x时固定y,只观察x对z的影响; - 求
∂z/∂y时固定x,只观察y对z的影响。
偏导数告诉我们:其他变量暂时不变时,某一个变量的微小变化会怎样影响函数值。
3.7 全微分
对二元函数 z=f(x,y),若在某点可微,其局部变化可以近似为:
dz = (∂f/∂x) dx + (∂f/∂y) dy
几何上,一元函数用切线近似曲线,多元函数则用切平面近似曲面。推广到 n 个变量:
df = Σ (∂f/∂xᵢ) dxᵢ
这意味着函数总变化可以近似分解为每个变量变化所产生影响的总和。
3.8 方向导数与梯度
偏导数只研究沿坐标轴方向的变化,方向导数则研究沿任意单位方向向量 u 的变化率:
Dᵤf = ∇f · u
梯度由函数对所有自变量的偏导数组成:
∇f = [∂f/∂x₁, ∂f/∂x₂, ..., ∂f/∂xₙ]
梯度包含两个重要信息:
- 方向:指向函数值增长最快的方向;
- 模长:反映函数沿该方向变化的最大速率。
在等高线图上,梯度垂直于经过该点的等高线,并指向更高的函数值。训练模型时希望减小损失,因此参数沿 负梯度方向 更新:
θ ← θ - η∇L(θ)
其中 θ 是参数,L 是损失函数,η 是学习率。学习率决定每次沿负梯度方向走多远:太大可能越过最低点甚至发散,太小则收敛缓慢。
PyTorch 会记录张量运算形成的计算图,并自动完成反向传播:
import torch
x = torch.tensor([1.0, 2.0], requires_grad=True)
loss = (x ** 2).sum()
loss.backward()
print(x.grad) # tensor([2., 4.])
这里 loss = x₁² + x₂²,所以梯度为 [2x₁, 2x₂]。需要注意,PyTorch 默认会 累积梯度;正式训练时通常要在下一轮反向传播前调用 optimizer.zero_grad()。
3.9 定积分
定积分可以理解为将区间切成许多小段,用无数个小矩形面积之和逼近曲线下的面积:
∫[a,b] f(x)dx = lim Σ f(ξᵢ)Δxᵢ
牛顿—莱布尼茨公式把积分和导数连接起来:若 F'(x)=f(x),则:
∫[a,b] f(x)dx = F(b) - F(a)
积分在概率密度归一化、连续随机变量的期望以及模型理论分析中都会出现。可以把导数理解为研究“局部变化率”,把积分理解为研究“连续累积量”。
