昇腾AI自学Day2-- 深度学习基础工具与数学
深度学习实践基础篇
用 PyTorch 学线性代数:概念、Python 常用运算与 torch.linalg 加速
一、前言:为什么深度学习离不开线性代数?
深度学习的计算基本都可以还原为向量与矩阵运算:
-
前向传播就是一连串线性变换(矩阵乘法)+ 非线性;
-
反向传播用到了大量的矩阵微积分;
-
训练稳定性与效率取决于**范数、条件数、正定性、分解(SVD/Cholesky/QR)**等基础概念。
本文从“能马上用”的视角出发:先用几何直觉理解线性代数,再用 Python/NumPy 打下语法基础,最后用 PyTorch/torch.linalg 把同样的运算迁移到GPU + 自动求导与高性能场景
二、主要内容一览
-
线性代数速览(几何直觉):向量/矩阵/张量、线性映射、内积、范数、秩、正交与投影、特征分解与 SVD、正定与 Cholesky。
-
Python 常用代数运算(NumPy):矩阵乘法、求解线性方程、伪逆/最小二乘、特征值分解、SVD、QR、Cholesky、范数与行列式。
-
PyTorch 里的高效与可微代数:torch.matmul/@、torch.einsum、torch.linalg.* 家族、批量线性代数、autograd、数值稳定与性能建议。
-
小例子:用最小二乘做线性回归(NumPy 与 PyTorch 各一版,展示“别再手算逆矩阵”)。
三、分节详解
1) 线性代数速览(用直觉串起关键概念)
标量
标量由只有一个元素的张量表示。 下面的代码将实例化两个标量,并执行一些熟悉的算术运算,即加法、乘法、除法和指数。
import torchx = torch.tensor(3.0) y = torch.tensor(2.0)x + y, x * y, x / y, x**y
向量
向量可以被视为标量值组成的列表。 这些标量值被称为向量的元素(element)或分量(component)。 当向量表示数据集中的样本时,它们的值具有一定的现实意义。 例如,如果我们正在训练一个模型来预测贷款违约风险,可能会将每个申请人与一个向量相关联, 其分量与其收入、工作年限、过往违约次数和其他因素相对应。 如果我们正在研究医院患者可能面临的心脏病发作风险,可能会用一个向量来表示每个患者, 其分量为最近的生命体征、胆固醇水平、每天运动时间等。 在数学表示法中,向量通常记为粗体、小写的符号 (例如,x、y和z)。
x = torch.arange(4) x
我们可以使用下标来引用向量的任一元素,例如可以通过$x_i$来引用第个元素。
注意,元素是一个标量,所以我们在引用它时不会加粗。
大量文献认为列向量是向量的默认方向,在本课程中也是如此。
在数学中,向量可以写为:
其中是向量的元素。在代码中,我们**通过向量的索引来访问任一元素**。
向量长度、维度和形状
向量只是一个数字数组,就像每个数组都有一个长度一样,每个向量也是如此。 在数学表示法中,如果我们想说一个向量由个实值标量组成, 可以将其表示为。 向量的长度通常称为向量的维度(dimension)。
与普通的Python数组一样,我们可以通过调用Python的内置len()
函数来访问向量的长度。
x[3] len(x) x.shape
我们也可以通过
.shape
属性访问向量的长度。 形状(shape)是一个元素组,列出了向量沿每个轴的长度(维数)。 对于只有一个轴的向量,形状只有一个元素。
矩阵
正如向量将标量从零阶推广到一阶,矩阵将向量从一阶推广到二阶。
矩阵,我们通常用粗体、大写字母来表示
(例如,、$
$和
),
在代码中表示为具有两个轴的张量。
数学表示法使用
来表示矩阵,其由$m$行和$n$列的实值标量组成。
我们可以将任意矩阵视为一个表格,
其中每个元素属于第
行第
列:
对于任意,
的形状是
或
。
当矩阵具有相同数量的行和列时,其形状将变为正方形;
因此,它被称为*方阵*(square matrix)。
当调用函数来实例化张量时,
我们可以通过指定两个分量和
来创建一个形状为
的矩阵。
A = torch.arange(20).reshape(5, 4) A
张量的基本概念
-
定义
张量(Tensor)是一个多维数组,可以看作是标量(0维)、向量(1维)、矩阵(2维)向高维推广的数学概念。
-
与 NumPy 的区别
PyTorch 的张量与 NumPy 数组相似,但最大的不同是张量可以在 GPU 上进行计算,极大提升了深度学习模型的训练速度。
-
张量的属性
-
shape(形状)
-
dtype(数据类型)
-
device(设备位置:CPU 或 GPU)
-
参考链接:PyTorch 基本操作:张量(Tensor)基础与操作
-
-
当我们开始处理图像时,张量将变得更加重要,图像以
维数组形式出现,其中3个轴对应于高度、宽度,以及一个*通道*(channel)轴,用于表示颜色通道(红色、绿色和蓝色)。现在先将高阶张量暂放一边,而是专注学习其基础知识
-
标量/向量/矩阵/张量:0/1/2/≥3 维数据容器。深度学习中常用张量形状如 N×C×H×W(批×通道×高×宽)。
-
线性映射与矩阵乘法:矩阵 A 作用在向量 x 上,相当于对空间做“拉伸、旋转、投影”的组合:
。
-
内积(点积):
,几何意义是
,和相似度、余弦距离直接相关。
-
范数(长度/大小):
-
向量
;
-
矩阵 Frobenius 范数
。范数与正则化、梯度爆炸/消失有关。
-
-
秩(rank):线性独立方向的数量。低秩 ⇒ 冗余大、可压缩(SVD/PCA)。
-
特征分解/对称矩阵:对称矩阵可正交对角化
;在优化中常出现 Hessian(近似二次型)。
-
SVD:
。
的奇异值衡量方向拉伸强度。用于低秩近似、PCA、稳健求逆(伪逆)。
-
正定矩阵与 Cholesky:对称正定
。广泛用于高效求解二次问题/高斯模型。
-
条件数与数值稳定:条件数越大,问题越“病态”,误差易被放大。训练中要避免显式求逆,优先用 solve/lstsq。
2) Python 常用代数运算(NumPy 版)
目的:建立“概念 ↔ 代码”最短路径,随后无缝迁移到 PyTorch。
import numpy as np# 基本创建与形状 A = np.random.randn(3, 4) B = np.random.randn(4, 5) x = np.random.randn(4)# 矩阵乘法(推荐 @ 或 np.matmul) Y = A @ B # (3,4)@(4,5)->(3,5) y = A @ x # (3,)# 内积/范数/迹/行列式 dot_xy = x @ x # 向量点积 norm_x = np.linalg.norm(x, ord=2) trace_A = np.trace(A @ A.T) det_square = np.linalg.det(np.random.randn(4,4))# 线性方程组 Ax=b(优先 solve,别用 inv@b) A2 = np.random.randn(5,5) b2 = np.random.randn(5) x2 = np.linalg.solve(A2, b2)# 伪逆/最小二乘 X = np.random.randn(100, 3) t = X @ np.array([1.5, -2.0, 0.7]) + 0.1*np.random.randn(100) theta_ls, residuals, rank, s = np.linalg.lstsq(X, t, rcond=None) # 最小二乘 pinv_X = np.linalg.pinv(X) # 伪逆# 分解:特征、SVD、QR、Cholesky(正定矩阵) C = np.random.randn(6,6) C = C.T @ C + 1e-3*np.eye(6) # 保证正定 L = np.linalg.cholesky(C) # C = L L^TE_vals, E_vecs = np.linalg.eigh(C) # 对称矩阵特征分解 U, S, Vt = np.linalg.svd(X, full_matrices=False) # SVD Q, R = np.linalg.qr(X, mode='reduced') # QR
要点
-
永远优先 solve/lstsq 而不是 inv;
-
eigh 专门用于对称/厄米矩阵,更快更稳;
-
用 svd/pinv 处理病态问题;
-
正定矩阵优先 cholesky(速度/稳定性最佳)。
3) PyTorch 的高效与可微代数(GPU + Autograd + 批量)
PyTorch 将上述运算搬到 GPU,并支持 自动求导。核心在 torch 与 torch.linalg 模块。
3.1 基础与设备
import torchdevice = torch.device("cuda" if torch.cuda.is_available() else "cpu") A = torch.randn(3, 4, device=device, dtype=torch.float32, requires_grad=False) B = torch.randn(4, 5, device=device) x = torch.randn(4, device=device, requires_grad=True) # 需要梯度
3.2 乘法/内积/爱因斯坦求和
Y = A @ B # torch.matmul y = A @ x # (3,) dot_x = torch.dot(x, x) # 向量点积 y2 = torch.einsum('ij,j->i', A, x) # 灵活的多维相乘
3.3 torch.linalg 速查(面向深度学习的稳定实现)
# 线性方程组(推荐)与最小二乘 A2 = torch.randn(5,5, device=device) b2 = torch.randn(5, device=device) x2 = torch.linalg.solve(A2, b2) # 优先用 solve theta_ls = torch.linalg.lstsq(A, B).solution # 最小二乘# 伪逆/逆(仅在必要时) pinvA = torch.linalg.pinv(A2) invA = torch.linalg.inv(A2) # 一般不建议直接用# 范数/迹/行列式/对数行列式/条件数 nA = torch.linalg.norm(A2) # Fro / 指定 ord trA = torch.trace(A2) detA = torch.linalg.det(A2) sgn, logabsdet = torch.linalg.slogdet(A2) # 计算 log|det| 更稳 condA = torch.linalg.cond(A2)# 分解:Cholesky / eigh / svd / qr C = torch.randn(6,6, device=device); C = C.T @ C + 1e-3*torch.eye(6, device=device) L = torch.linalg.cholesky(C)evals, evecs = torch.linalg.eigh(C) # 对称阵的特征分解 U, S, Vh = torch.linalg.svd(A, full_matrices=False) Q, R = torch.linalg.qr(A)
3.4 批量(batched)线性代数(超实用)
绝大多数 torch.linalg.* 都支持批量维度:
形状 (..., m, n) 表示前面是批量维度。
# 批量矩阵乘法
X = torch.randn(32, 10, 10, device=device) # 32 个 10×10
B = torch.randn(32, 10, 1, device=device)
sol = torch.linalg.solve(X, B) # 一次解 32 个线性系统# 或 bmm: (B, m, n) @ (B, n, p) -> (B, m, p)
A_b = torch.randn(64, 20, 30, device=device)
B_b = torch.randn(64, 30, 40, device=device)
C_b = torch.bmm(A_b, B_b)
3.5 Autograd 与数值稳定建议
-
给需要梯度的张量 requires_grad=True,计算图会追踪线性代数运算,之后 loss.backward() 自动求梯度。
-
避免不必要的 inv:用 solve/lstsq 可微且更稳。
-
对称正定 + Cholesky:速度快、稳定;常见于高斯模型/二次优化。
-
加抖动(jitter):A_pd = A + eps*I,缓解病态或保证正定。
-
双精度:需要高精度时用 dtype=torch.float64(代价是更慢)。
-
混合精度训练:torch.autocast 与 GradScaler 提速但要注意数值范围。
-
广播与维度:熟练使用 broadcasting、permute/transpose、reshape/view。(B, C, H, W) 与 @ 的约束要清楚。
4) 小例子:最小二乘线性回归(NumPy → PyTorch)
目标:拟合,展示“不要用
,直接 lstsq/solve”。
NumPy 版:
import numpy as npnp.random.seed(0)
N, D = 200, 5
X = np.random.randn(N, D)
true_theta = np.array([1.5, -2.0, 0.7, 0.0, 3.0])
y = X @ true_theta + 0.1*np.random.randn(N)theta_ls, *_ = np.linalg.lstsq(X, y, rcond=None)
print("NumPy θ̂:", theta_ls)
PyTorch 版(GPU + 可微):
import torch
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")N, D = 200, 5
X = torch.randn(N, D, device=device)
true_theta = torch.tensor([1.5, -2.0, 0.7, 0.0, 3.0], device=device)
y = X @ true_theta + 0.1*torch.randn(N, device=device)theta_hat = torch.linalg.lstsq(X, y).solution
print("Torch θ̂:", theta_hat)
梯度下降(展示 autograd):
theta = torch.zeros(D, device=device, requires_grad=True)
opt = torch.optim.SGD([theta], lr=1e-2)for _ in range(1000):y_pred = X @ thetaloss = torch.mean((y_pred - y)**2)opt.zero_grad()loss.backward()opt.step()print("GD θ̂:", theta.detach())
四、总结与写作建议
-
核心记忆点
-
深度学习 = 线性代数 + 非线性。矩阵乘法/范数/分解决定了训练的稳定性与效率。
-
编程层面:NumPy 练语法 → PyTorch 迁移;熟悉 torch.linalg 的解方程/分解/范数。
-
工程建议:别用 inv;优先 solve/lstsq/Cholesky;必要时加 jitter、用 双精度,或改写到 log 域(slogdet)。
-
-
可扩展方向
-
用 torch.linalg.svd 实现 PCA/低秩近似;
-
用 eigh/Cholesky 构建 高斯似然/二次目标;
-
批量线性代数加速多任务/多样本并行;
-
结合 torch.autocast 做 混合精度训练。
附:常用 API 速查(对照表)
-
-
-
乘法:A @ B / torch.matmul / torch.bmm(批量) / torch.einsum
-
解方程:np.linalg.solve ↔ torch.linalg.solve
-
最小二乘:np.linalg.lstsq ↔ torch.linalg.lstsq
-
伪逆:np.linalg.pinv ↔ torch.linalg.pinv
-
SVD:np.linalg.svd ↔ torch.linalg.svd
-
对称特征:np.linalg.eigh ↔ torch.linalg.eigh
-
QR:np.linalg.qr ↔ torch.linalg.qr
-
Cholesky:np.linalg.cholesky ↔ torch.linalg.cholesky
-
范数:np.linalg.norm ↔ torch.linalg.norm/vector_norm/matrix_norm
-
行列式/对数行列式:np.linalg.det ↔ torch.linalg.det/slogdet
-
条件数:np.linalg.cond ↔ torch.linalg.cond
-