特征值、SVD 与低秩:直通 LoRA
用最小数字看清特征分解与 SVD,理解低秩近似为何成立,并亲手算出 LoRA 到底省了多少参数
- 说清特征值/特征向量的几何含义与特征分解的适用边界
- 能写出 SVD 的分解式,讲清楚 U、Σ、V 各自的角色,还要知道奇异值是非负的。
- 理解秩-1 外积与低秩近似的原理和误差来源
- 能手算 LoRA 相对全参数微调的参数量与压缩比例,说清低秩为何有效
SVD 给任意矩阵做「主轴解剖」,LoRA 把低秩思想变成了工业级微调
这节是线性代数这条线的收尾。先找特征向量——就是变换里「方向不变、只被拉伸」的特殊轴;再讲对任意矩阵都成立的奇异值分解(SVD);最后落到一个大模型时代很关键的结论:权重更新可以用很低的秩近似,所以才有了只训练 0.4% 参数的 LoRA。你要的全部前置知识,就是前三节讲的向量、矩阵乘、秩与投影。
4.1 特征值与特征向量:变换中「方向不变」的轴
对方阵 A,若存在非零向量 v 和数 λ 使 A·v = λ·v,就称 v 是特征向量、λ 是对应的特征值。几何含义:绝大多数向量被 A 作用后又转又变,但特征向量是少数「方向纹丝不动、只沿原方向被缩放 λ 倍」的特殊方向,它们是这台变换机器的主轴。最小手算:对角阵 A=[[2,0],[0,3]]。取 e₁=[1,0],A·e₁=[2,0]=2·e₁,所以 λ₁=2;取 e₂=[0,1],A·e₂=[0,3]=3·e₂,λ₂=3。对角阵的特征向量就是坐标轴,特征值就是对角线上的缩放倍数。
两个有用的整体量:迹 trace(A) 是对角线元素之和,恰好等于全部特征值之和;行列式 det(A) 恰好等于全部特征值之积。所以「某个特征值为 0」等价于 det=0、矩阵秩亏不可逆,和 l3 的判据对应上了。特征值为负表示沿该主轴方向翻转,特征值模长大于 1 表示该方向被放大——动力系统里判断迭代是否发散,看的就是特征值模长是否超过 1。
特征分解还让「矩阵的幂」变得可算:若 A=QΛQ⁻¹,则 Aⁿ=QΛⁿQ⁻¹,而对角阵的 n 次方只需把每个对角元分别取 n 次方。这解释了两件你以后会遇到的事:一是反复施加同一线性变换(如深层网络的同类映射、马尔可夫链多步转移)时,最大特征值主导长期行为;二是若某特征值模长大于 1,沿该主轴的分量会被层层放大直至数值爆炸,小于 1 则逐层衰减消失——梯度在深度网络里为何消失或爆炸,数学根子就在这里。
Av=λv 中特征向量 v 的几何含义是?
4.2 特征分解的边界:不是每个矩阵都能被干净分解
把方阵写成 A=QΛQ⁻¹(Q 的列是特征向量、Λ 对角线上是特征值)叫特征对角化。它有前提:必须是方阵,且要凑齐足够多线性独立的特征向量。遇到非对称矩阵、特征值出现复数、或「亏损矩阵」(独立特征向量不够)时,特征分解要么很别扭要么不存在。
特征值允许为负(方向翻转)甚至为复数(含旋转),且只对方阵定义;后面对任意矩阵定义的奇异值是 AᵀA 特征值的平方根,因此永远 ≥0 并按从大到小排列。两者不是一回事,别混用。
4.3 SVD:任意矩阵都能拆成「旋转—拉伸—旋转」
奇异值分解(SVD)不挑矩阵,任意 A(甚至长方形)都能写成 A = UΣVᵀ:V 的列是「输入空间的主轴」(右奇异向量,正交);U 的列是「输出空间的主轴」(左奇异向量,正交);Σ 是对角矩阵,对角元 σ₁≥σ₂≥…≥0 叫奇异值,只负责沿各主轴拉伸。任何线性变换都能拆成三步:先用 Vᵀ 旋转对齐主轴,再用 Σ 沿主轴分别缩放,最后用 U 旋转到输出方向。
再拿一个非对角对称的小例子,感受下「主轴被旋转」是什么意思:A=[[3,1],[1,3]]。方向 [1,1] 上,A·[1,1]=[4,4]=4·[1,1],特征值 4;方向 [1,-1] 上,A·[1,-1]=[2,-2]=2·[1,-1],特征值 2。它的主轴不再是横平竖直的坐标轴,而是被旋转了 45° 的 [1,1]、[1,-1];对称正定阵的奇异值就等于特征值 {4,2}。这说明 SVD 做的事,是先把坐标系转到「最自然的主轴」上,缩放规律才变得简单。
奇异值从哪来:用 AᵀA 手算(对称例)
奇异值是矩阵 AᵀA(半正定对称阵)特征值的算术平方根,即 σᵢ=√λᵢ(AᵀA),这保证了 σᵢ≥0。拿对称正定的对角阵 A=[[2,0],[0,3]] 举例,AᵀA=[[4,0],[0,9]],特征值是 4、9,开方得到奇异值 σ={2,3}(按降序写成 {3,2}),这时候主轴刚好是坐标轴,U、V 都是正交单位阵。一般矩阵的计算量不小,都交给程序跑。但你得记牢:奇异值衡量矩阵在各主轴方向上的影响力大小。
4.4 低秩近似:只保留最有分量的几根主轴
SVD 还能把矩阵拆成若干秩-1 外积相加:A = Σᵢ σᵢ·uᵢ·vᵢᵀ。每一项都是「列向量 uᵢ 乘行向量 vᵢᵀ」得到的薄矩阵,权重就是奇异值 σᵢ。σ 是按降序排的,前几项通常占了绝大部分「能量」。把后面数值很小的 σ 丢掉,就能得到低秩近似 A≈Σi≤r σᵢuᵢvᵢᵀ,计算和存储成本都更低。
手算一个秩-1 外积:取单位向量 u=[0.6,0.8](即 [3,4]/5)、σ=5、v=[1,0],则 σ·u·vᵀ = 5×[0.6,0.8]ᵀ×[1,0] = [[3,0],[4,0]]——一列被拉伸、另一列为 0,这是秩严格为 1 的矩阵。
低秩这思路在工程里用得特别多:推荐系统里那个超大的「用户×物品」评分矩阵,靠低秩分解补全缺失的评分;图像或者大矩阵压缩,只存前若干组奇异向量就行;PCA 给中心化后的数据矩阵做 SVD,主成分就是最大奇异值对应的主轴,用来降维去噪。这些应用本质上都认同一个理:真实的高维数据,有效自由度往往比它表面的维度低得多。
从这儿引出两个定量工具。第一个是「有效秩」:名义秩可能很高,但如果奇异值衰减得快、后面小到可以忽略,矩阵的实际自由度由前几个大奇异值决定——这就是权重更新能被低秩逼近的经验依据。第二个是范数和奇异值的关系:谱范数(矩阵作用后最多把向量拉长几倍)等于最大奇异值 σ₁;Frobenius 范数(所有元素平方和开根)等于 √Σσᵢ²。前面算能量占比用的平方和,就是 Frobenius 范数的口径,截断误差就是被丢弃奇异值的平方和。
某矩阵奇异值为 [10, 3, 1],只保留最大的 σ=10 做秩-1 近似,被保留的「能量占比」约为多少(用平方和占比,10²+3²+1²=110)?A=QΛQ⁻¹,仅方阵且需足够独立特征向量;特征值可负可复;沿自身特征轴分解。
主成分分析 PCA,本质就是求数据协方差阵的特征方向。实现的时候直接对中心化后的数据矩阵做 SVD 就行,右奇异向量就是主成分,奇异值的平方和各方向的方差成正比。把 SVD 搞懂了,PCA 自然就通了,不用单独再啃一套逻辑。
4.5 直通 LoRA:用低秩增量给大模型做「微创手术」
全参数微调要更新权重矩阵 W 的每一个元素。LoRA(Low-Rank Adaptation)的思路不一样:它假设权重的变化量 ΔW 本身近似低秩,不直接学 ΔW,而是把它拆成两个小矩阵相乘:ΔW = B·A。训练时冻住原 W,只训练 A、B 这两个小矩阵。 形状设计:W 是 [d,d],让 A 形状是 [r,d](瘦高)、B 形状是 [d,r](矮胖),r≪d,这个 r 就叫秩。前向计算是 y = Wx + B(Ax),先把 d 维输入压到 r 维,再升回 d 维,注入的正是一个秩不超过 r 的更新。
参数量手算(d=4096,r=8):全参数:d×d = 4096² = 16,777,216(约 1677 万)。LoRA:A 有 r×d=8×4096 个、B 有 d×r=4096×8 个,合计 2dr = 65,536。比例:65,536 / 16,777,216 ≈ 0.00391 ≈ 0.39%,等价公式 2r/d = 16/4096。只训约千分之四的参数,这就是 LoRA 能在单张消费级显卡上微调大模型的直接原因。
记两个工程细节。训练时 ΔW=BA 走旁路、原 W 冻结,部署时可把 BA 算出来加回 W 得到 W'=W+BA 合并成一个矩阵,推理时与原模型计算量完全相同、零额外延迟,需要切换风格时再换回 W 并挂另一组 BA,因此能热插拔多个适配器。实现里常带缩放系数 α/r 来控制低秩更新的强弱,并把 B 初始化为 0,保证训练开始瞬间 ΔW=0、模型行为与底座完全一致,再逐步学出增量。
注意别把 LoRA 和「直接对 ΔW 做 SVD 截断」混为一谈:SVD 截断是先有完整矩阵再事后压缩,而微调前你根本不知道 ΔW 是什么;LoRA 是直接把优化变量约束在「所有可写成 BA 的低秩矩阵」这个集合里,让梯度下降自己去找最优的低秩增量。两者殊途同归地押注「有效更新低秩」,但一个是事后压缩、一个是事前约束,LoRA 的聪明之处在于用极小代价把低秩假设直接写进了训练过程。
# LoRA 线性层结构(PyTorch 伪代码,不在浏览器运行)
import torch, torch.nn as nn
class LoRALinear(nn.Module):
def __init__(self, base, d, r):
super().__init__()
self.base = base # 冻结的原线性层 W
for p in self.base.parameters(): p.requires_grad_(False)
self.A = nn.Linear(d, r, bias=False) # [d -> r] 降维
self.B = nn.Linear(r, d, bias=False) # [r -> d] 升维
def forward(self, x):
return self.base(x) + self.B(self.A(x)) # Wx + BAxr 越小越省显存,但表达力越弱。常见取值 4/8/16/32。简单风格任务 r=4~8 就够,复杂推理任务一般加大 r,或者用多组适配器。QLoRA 在 LoRA 基础上,把冻结的底座量化到 4bit,进一步省显存。多个 LoRA 适配器支持热插拔切换。面试要能当场推出参数量 2dr 和比例 2r/d,还要能解释「为什么低秩够用」——任务对参数的改变集中在少数方向上,和 SVD 能量集中是同一个直觉。
LoRA 调到 r=64 还欠拟合,或者把多个差异极大的任务硬塞进同一组适配器,就说明权重变化根本不在同一个低维子空间里。这种时候直接增大 r、给不同任务各开一个适配器,要么退回全参微调,别盲目堆训练轮数。
LoRA 之所以能用极少参数微调,最根本的假设是?
本节小结
串成一条线说:特征向量是变换里方向不变的轴,对应公式 Av=λv。矩阵的迹等于所有特征值相加,行列式等于所有特征值相乘,但特征分解不是所有矩阵都能用。SVD 对任意矩阵都成立,公式是 A=UΣVᵀ=Σσᵢuᵢvᵢᵀ,奇异值都是非负的、按降序排,用来衡量每个主轴分量的大小。只保留前 r 项就是最优低秩近似,PCA、压缩、推荐系统本质都是这个思路。LoRA 假设权重的增量是低秩的,用 ΔW=BA 实现,维度变化是 d→r→d,训练时冻结底座模型,只训这两个小矩阵。当 d=4096、r=8 时,只需要训练约 0.39% 的参数,训练完还能把增量合并回原权重 W,推理时零额外延迟。到这,线性代数的四块基石——向量张量、矩阵乘、秩与投影、特征分解与低秩——就全和大模型工程的实际场景对上了。
资深工程师加餐
底层原理 · 大厂视角 · 工程经验,点卡片展开
信息熵度量一个分布的不确定程度,越随机熵越大。交叉熵衡量「用模型预测的分布去编码真实分布」所需的平均代价:模型预测越接近真实标签,交叉熵越小。因此多分类任务用交叉熵做损失不是拍脑袋,而是有严格信息论依据的最大似然等价形式。