norm(v) 欧氏长度、norm(A) 矩阵 2 范数、p 参数全解
从向量长度到算子范数——一条贯穿数值线性代数、信号处理与深度学习的主线
摘要
在MATLAB的数值计算工具箱中,norm是一个看似简单、实则承载了整个范数理论体系的函数。它既能计算向量的欧氏长度,也能返回矩阵的诱导2范数,还能通过p参数在1范数、2范数、无穷范数、Frobenius范数之间自由切换。然而,多数使用者只停留在"求长度"的直觉层面,对其背后的奇异值分解、算子范数定义、数值稳定性与大规模计算策略缺乏系统认知。
本文以"范数即度量"为分析主线,从向量范数的公理化定义出发,逐层推进到矩阵诱导范数、Schatten范数族与数值算法实现,并结合信号处理、机器学习正则化、模型鲁棒性评估等工程场景,给出可复现的操作路径。全文兼顾理论推导与MATLAB实操,力求让读者读完不仅能正确调用norm,更能理解每一次调用背后发生了什么。
目录
一、为什么范数是数值计算的"度量衡"
任何涉及误差、距离、相似度的计算,最终都要回答一个问题:两个对象之间"差多少"。在标量世界里,绝对值就够了;一旦进入向量和矩阵的世界,就需要一个把"大小"从多维压缩成单个实数的函数——这就是范数。
范数(norm)的数学定义并不复杂:给定向量空间 V,函数 ‖·‖: V → ℝ 若满足非负性、齐次性与三角不等式三条公理,即为范数。但真正让工程师头疼的,是同一空间上可以定义无穷多种范数,而不同范数诱导出的"距离"完全不同。一个在2范数下接近的向量,在无穷范数下可能相差甚远。
本文评述:范数的选择本质上是一种"价值判断"——你关心的是整体能量(2范数)、最坏分量(无穷范数)还是稀疏结构(1范数)。MATLAB的norm函数把这套判断封装成参数,但参数背后的语义需要使用者自己承担。
在MATLAB中,norm的调用形式高度统一,但返回值语义随输入类型(向量/矩阵)和参数(p)剧烈变化。这种"一个函数、多重语义"的设计,既是MATLAB的便利,也是误用的高发区。本文后续章节将逐层拆解。
二、向量范数:从欧氏长度到p范数族
2.1 欧氏范数:最熟悉的陌生人
对于向量 v = [v₁, v₂, …, vₙ],2范数定义为各分量平方和的平方根:
‖v‖₂ = sqrt( v₁² + v₂² + … + vₙ² )
这就是中学几何里的"长度"概念在高维空间的自然推广。MATLAB中norm(v)默认返回的正是它。
v = [3; 4]; n2 = norm(v) % 返回 5 n2b = norm(v, 2) % 显式指定2范数,同样返回 5
值得注意的是,MATLAB在计算2范数时并非简单地逐项平方求和。对于大规模向量,直接平方可能导致上溢或下溢。MathWorks官方文档指出,norm内部采用了缩放策略(scaling)来规避极端数值问题[1]。这一点在后续数值稳定性章节会展开。
2.2 p范数族:一个公式统一四种度量
向量p范数的一般定义为:
‖v‖_p = ( Σᵢ |vᵢ|^p )^(1/p), p ≥ 1
当p取不同值时,得到不同的度量:
MATLAB对norm(v, p)的支持覆盖了p为任意正实数、Inf和-Inf的情形。但有一个常被忽略的约束:p必须≥1,否则三角不等式不成立,函数不再构成范数。当p<1时,MATLAB会报错。
v = [1 -2 3 -4]; norm(v, 1) % 10 norm(v, 2) % 5.4772 norm(v, Inf) % 4 norm(v, -Inf) % 1 norm(v, 0.5) % 报错:'p' must be a real number >= 1
本文评述:p<1的"拟范数"在压缩感知和稀疏优化中极其重要(如L0.5范数),但MATLAB的norm函数刻意不支持。笔者认为这是合理的工程取舍——拟范数不满足凸性,优化算法完全不同,混入通用接口反而危险。需要时应在优化工具箱或自定义函数中处理。
三、norm(v) 的MATLAB实操与边界情形
3.1 基本调用与维度处理
MATLAB的norm对行向量和列向量一视同仁,返回值都是标量。但如果你传入一个矩阵而只想要"按列求范数",直接调用norm(A)会得到矩阵范数而非列范数向量。正确做法是使用vecnorm:
A = [1 2; 3 4; 5 6]; norm(A) % 9.5255 —— 矩阵2范数(最大奇异值) vecnorm(A) % [5.9161 7.4833] —— 每列的2范数 vecnorm(A, 1) % [9 12] —— 每列的1范数 vecnorm(A, Inf, 2) % [2; 4; 6] —— 每行的无穷范数
vecnorm是R2017b引入的函数,专门解决"沿指定维度求范数"的需求[2]。在它出现之前,工程师只能用sqrt(sum(A.^2))这类手动写法,既冗长又容易在维度上出错。
3.2 空向量、零向量与NaN
边界情形往往是bug的温床。MATLAB对以下输入的处理值得牢记:
norm([])返回0,不报错。norm([0 0 0])返回0。- 含
NaN的向量返回NaN(除非使用'omitnan'选项,但norm本身不直接支持,需先清洗)。 - 含
Inf的向量返回Inf。
笔者认为:norm([])==0这一约定在数学上是有争议的(空和的平方根通常定义为0,但空集的最大值无定义)。工程上它避免了大量空数据分支判断,是务实的妥协。但在涉及无穷范数时,norm([], Inf)同样返回0,这一点需要特别留意。
3.3 复数向量的范数
对于复数向量,范数定义中的|vᵢ|取模(模长),而非实部或虚部。MATLAB自动处理:
z = [3+4i, 0]; norm(z) % 5 —— 因为 |3+4i| = 5 norm(z, 1) % 5
这一点在信号处理中至关重要。FFT输出的频谱是复数,计算其能量时必须用复数范数,若误用abs(real(z))会丢失虚部能量。
四、矩阵范数:诱导范数与Frobenius范数
4.1 诱导范数的定义逻辑
矩阵范数不是向量范数的简单推广。最常用的一类矩阵范数由向量范数"诱导"而来,其定义带有明显的算子色彩:
‖A‖_p = max_{x≠0} ‖Ax‖_p / ‖x‖_p
这个定义的物理含义是:矩阵A对向量x的最大"放大倍数"。它衡量的是A作为线性算子的最坏情况增益。这正是控制论、数值分析中反复出现的"算子范数"。
诱导范数有一个极其重要的性质——次乘性(submultiplicativity):
‖AB‖ ≤ ‖A‖ · ‖B‖
这条性质保证了误差在矩阵乘法中不会爆炸式增长,是数值稳定性分析的基石。
4.2 Frobenius范数:不是诱导范数
Frobenius范数定义为所有元素平方和的平方根:
‖A‖_F = sqrt( Σᵢ Σⱼ |aᵢⱼ|² )
它等价于把矩阵拉直成向量后的2范数,但它不是任何向量范数诱导出的矩阵范数。原因在于:诱导范数满足‖I‖=1(单位矩阵),而‖I‖_F = sqrt(n),随维度增长。
本文评述:Frobenius范数虽然不满足诱导范数的"归一性",但它计算廉价(无需SVD)、对正交变换不变(‖QA‖_F = ‖A‖_F),在矩阵分解、低秩逼近中应用极广。Eckart-Young定理指出,Frobenius范数下的最优低秩逼近由截断SVD给出[3]。这是推荐系统、图像压缩的理论基础。
五、norm(A) 为什么等于最大奇异值
5.1 从SVD到2范数
对任意矩阵A,其奇异值分解为 A = UΣVᵀ(实矩阵情形)。其中Σ是对角矩阵,对角线元素σ₁ ≥ σ₂ ≥ … ≥ σᵣ ≥ 0称为奇异值。矩阵2范数的核心结论是:
‖A‖₂ = σ₁ = σ_max(A)
证明思路并不复杂:由于U、V是正交矩阵,它们不改变2范数。于是‖Ax‖₂ = ‖ΣVᵀx‖₂。令y = Vᵀx,则‖y‖₂ = ‖x‖₂。问题转化为求‖Σy‖₂ / ‖y‖₂的最大值,而Σ是对角矩阵,其最大放大倍数显然是对角线上的最大元素σ₁。
MATLAB中norm(A)正是通过计算最大奇异值实现的。可以用svd验证:
A = [1 2; 3 4]; n = norm(A) % 5.4650 s = svd(A); % [5.4650; 0.3660] max(s) % 5.4650 —— 与norm(A)一致
5.2 计算代价与替代方案
计算最大奇异值的标准方法是SVD,其计算复杂度为O(min(m,n)²·max(m,n))。对于大型矩阵,这可能成为瓶颈。MATLAB提供了normest函数,用幂迭代法估计2范数,适合稀疏矩阵或只需要近似值的场景[4]。
A = gallery('randsvd', 1000, -3); % 1000x1000病态矩阵
tic; n1 = norm(A); toc % 精确SVD,较慢
tic; n2 = normest(A, 1e-6); toc % 幂迭代估计,快得多
abs(n1 - n2) / n1 % 相对误差通常 < 1e-6
根据MathWorks文档,normest默认容差为1e-6,最多迭代100次[4]。在笔者的测试中(模拟数据,基于MATLAB R2023b,Intel i7-12700),1000×1000随机矩阵上norm耗时约0.18秒,normest约0.02秒,加速约9倍。
六、p参数全解:norm(A,p) 的完整语义表
当输入是矩阵时,p参数的语义与向量情形有本质区别。下表是MATLAB官方文档给出的完整对照[1],笔者补充了计算复杂度与适用场景:
需要特别强调:矩阵的1范数和无穷范数不是向量1范数/无穷范数的简单推广。矩阵1范数是"列和的最大值",无穷范数是"行和的最大值",这与诱导范数的定义一致,但直觉上容易记反。
A = [1 -2; 3 -4]; norm(A, 1) % max(|1|+|3|, |-2|+|-4|) = max(4, 6) = 6 norm(A, Inf) % max(|1|+|-2|, |3|+|-4|) = max(3, 7) = 7 norm(A, 'fro') % sqrt(1+4+9+16) = sqrt(30) = 5.4772 norm(A, 'nuc') % 奇异值之和
笔者认为:核范数(nuclear norm)是近年来最值得关注的矩阵范数。它是秩函数在单位球上的凸包络,因此成为矩阵补全、鲁棒PCA等低秩优化问题的核心工具[5]。MATLAB从R2021a起支持'nuc'选项,但计算代价与2范数相当,大规模问题需谨慎。
七、数值稳定性、条件数与范数的关系
7.1 条件数的范数定义
矩阵条件数定义为:
cond(A) = ‖A‖ · ‖A⁻¹‖
MATLAB的cond(A)默认使用2范数,即σ_max/σ_min。条件数衡量的是线性方程组Ax=b对扰动的敏感度:条件数越大,解越不稳定。
A = hilb(10); % 10阶Hilbert矩阵,著名病态矩阵 c2 = cond(A) % 约1.6e13 c1 = cond(A, 1) % 1范数条件数 cInf = cond(A, Inf) % 无穷范数条件数
Hilbert矩阵的条件数随阶数指数增长。10阶时2范数条件数已达10¹³量级,意味着双精度下求解Ax=b会损失约13位有效数字[6]。
7.2 范数计算的数值陷阱
直接按定义计算2范数可能遇到上溢/下溢。例如v = [1e200, 1e200],各分量平方后为1e400,超出双精度上限(约1.8e308),得到Inf。MATLAB内部通过缩放规避了这个问题:
v = [1e200, 1e200]; norm(v) % 1.4142e200 —— 正确 sqrt(sum(v.^2)) % Inf —— 手动计算溢出
MathWorks在norm实现中采用了Blue的缩放算法(参考LAPACK的dnrm2)[7]。该算法先找出最大绝对值,将所有元素除以它,计算后再乘回。这一细节在嵌入式代码生成时尤其重要——MATLAB Coder生成的代码会保留这一保护。
本文评述:很多人以为norm只是sqrt(sum(x.^2))的语法糖,这是一个危险的误解。在科学计算中,数值稳定性往往比算法本身更重要。笔者建议:任何涉及极端量级数据的范数计算,都应优先使用内置norm而非手写公式。
八、大规模矩阵与GPU上的范数计算
8.1 稀疏矩阵的范数
对于稀疏矩阵,norm(A,1)和norm(A,Inf)可以直接在稀疏结构上高效计算,复杂度与非零元素数成正比。但norm(A)(2范数)需要SVD,稀疏SVD通常会产生大量填充(fill-in),代价高昂。
A = sprand(10000, 10000, 0.001); % 0.1%稀疏度 tic; n1 = norm(A, 1); toc % 很快 tic; nf = norm(A, 'fro'); toc % 很快 tic; n2 = normest(A, 1e-4); toc % 幂迭代,可接受 % norm(A) 对如此大的稀疏矩阵可能耗时数分钟,不推荐
8.2 GPU加速
如果安装了Parallel Computing Toolbox,gpuArray上的norm会自动调用cuBLAS/cuSOLVER。对于大型稠密矩阵,GPU版本通常有数倍到数十倍加速:
A = rand(5000, 5000); tic; n_cpu = norm(A); toc Ag = gpuArray(A); tic; n_gpu = norm(Ag); toc gather(n_gpu)
根据笔者在NVIDIA RTX 3060上的测试(模拟数据),5000×5000随机矩阵的2范数计算,CPU耗时约4.2秒,GPU约0.6秒,加速约7倍。但需要注意数据传输开销:如果矩阵本身在CPU内存中,gpuArray的拷贝时间可能抵消计算收益。
8.3 分块计算策略
当矩阵大到无法一次性载入内存时,Frobenius范数可以分块累加:
function nf = frobBlocked(filename, blockSize)
% 分块读取矩阵文件,累加平方和
total = 0;
fid = fopen(filename, 'r');
while ~feof(fid)
block = fread(fid, [blockSize, blockSize], 'double');
total = total + sum(block(:).^2);
end
fclose(fid);
nf = sqrt(total);
end
这种策略在深度学习训练中很常见——梯度矩阵的范数用于梯度裁剪(gradient clipping),而梯度可能分布在多张GPU上,需要先做all-reduce再求范数[8]。
九、工程实践:正则化、信号处理与鲁棒性评估
9.1 机器学习中的范数正则化
L1和L2正则化是范数在机器学习中最直接的应用。L2正则化(权重衰减)对应2范数平方,L1正则化对应1范数:
% 假设w是模型权重向量 L2_penalty = 0.5 * norm(w)^2; % 等价于 0.5 * sum(w.^2) L1_penalty = norm(w, 1); % sum(abs(w))
L1正则化产生稀疏解(部分权重精确为零),L2正则化产生平滑解(权重整体缩小)。这一差异的几何解释是:L1球在坐标轴上有"尖角",损失函数的等高线更容易与尖角相切,从而产生零分量[9]。
本文评述:虽然norm(w,1)写法简洁,但在深度学习框架中通常直接用sum(abs(w)),因为需要自动微分。MATLAB的Deep Learning Toolbox中,正则化通过trainingOptions的L2Regularization参数设置,底层实现并非直接调用norm。
9.2 信号处理:能量与总变差
在信号处理中,2范数平方对应信号能量(Parseval定理保证时域和频域能量相等),1范数对应总变差(Total Variation)的离散形式:
t = 0:0.001:1; x = sin(2*pi*50*t) + 0.5*randn(size(t)); E_time = norm(x)^2 / length(x); % 时域平均能量 X = fft(x); E_freq = norm(X)^2 / length(X); % 频域平均能量,与E_time一致 TV = norm(diff(x), 1); % 总变差
总变差正则化在图像去噪中极为常用。Rudin-Osher-Fatemi模型的核心就是在最小化‖u-f‖² + λ·TV(u)[10]。MATLAB的Image Processing Toolbox提供了imdiffusefilt等函数实现类似效果。
9.3 鲁棒性评估:谱范数与对抗攻击
在神经网络鲁棒性研究中,权重矩阵的谱范数(即2范数)是Lipschitz常数的上界。对于多层网络,整体Lipschitz常数不超过各层谱范数之积:
% 假设W1, W2, W3是三层权重矩阵 L = norm(W1) * norm(W2) * norm(W3); % Lipschitz常数上界 % 对抗扰动的最大放大倍数不超过L
这一性质被用于设计"谱归一化"(Spectral Normalization)技术,通过将每层权重除以谱范数,强制网络满足1-Lipschitz约束[11]。这在生成对抗网络(GAN)训练中显著提升了稳定性。
十、前沿预判:算子范数在深度学习中的角色
范数理论正在从数值线性代数向机器学习基础设施渗透。以下是笔者认为值得关注的三个方向:
10.1 谱范数正则化与泛化界
Bartlett等(2017)证明,神经网络的泛化误差可以用权重矩阵的谱范数(而非Frobenius范数)给出更紧的界[12]。这一发现推动了"谱归一化"和"正交初始化"等技术的普及。MATLAB的Deep Learning Toolbox从R2022b起支持在自定义层中访问权重矩阵并计算谱范数。
10.2 矩阵范数在联邦学习中的应用
联邦学习中,客户端上传的梯度更新需要经过范数裁剪以保护隐私(差分隐私)。裁剪阈值的选择直接影响模型精度与隐私预算的权衡。近期研究表明,基于2范数的自适应裁剪策略优于固定阈值[13]。
10.3 量子计算中的范数度量
在量子信息中,密度矩阵的迹范数(核范数)用于衡量量子态的可区分性。量子纠缠的度量(如 negativity)也基于部分转置矩阵的迹范数[14]。虽然MATLAB并非量子计算的主流平台,但其norm(A,'nuc')可以直接用于小规模量子态的数值实验。
本文评述:范数不再只是"求长度"的工具,它正在成为连接数值计算与机器学习的桥梁。笔者认为,未来五年内,算子范数的快速估计(如随机化SVD、Lanczos方法)将成为科学计算库的标配功能,因为深度学习模型规模的增长使得精确SVD越来越不现实。
十一、避坑清单与性能对照表
11.1 常见错误与修正
11.2 性能对照(模拟数据)
以下数据基于MATLAB R2023b,Intel i7-12700,32GB RAM,测试矩阵为1000×1000随机矩阵(模拟数据,非真实基准测试):
这张表传递的核心信息是:2范数比1范数/无穷范数贵两个数量级。在循环中反复调用norm(A)是常见的性能杀手。如果只需要近似值,normest是更好的选择。
11.3 拓展学习资源
- MathWorks官方文档:norm函数参考页(含完整参数说明与示例)
- MathWorks官方文档:vecnorm函数参考页
- MIT线性代数公开课(Gilbert Strang):Lecture 29: Singular Value Decomposition
- YouTube教程:Matrix Norms Explained(可视化讲解各类矩阵范数)
- LAPACK官方文档:dnrm2例程源码(2范数缩放算法实现)
十二、结语
从norm(v)的一行调用,到矩阵2范数背后的奇异值分解,再到深度学习中的谱归一化与联邦学习的梯度裁剪,范数这条线索贯穿了数值计算与机器学习的核心地带。MATLAB的norm函数用极简的接口封装了这套复杂的语义体系,但真正理解它,需要使用者主动穿透接口,看到背后的数学结构与工程权衡。
笔者认为,范数计算的未来不在于更快的SVD,而在于更智能的近似策略与更贴合应用场景的范数选择。当矩阵规模突破内存限制、当计算从CPU迁移到异构硬件、当范数从误差度量变成正则化工具,"选哪个范数"将和"怎么算范数"同等重要。
文章声明
本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。文中性能数据为模拟测试环境下的相对参考值,实际结果因硬件、MATLAB版本与矩阵特性而异。
主要参考文献
- MathWorks. "norm - Vector and matrix norms." MATLAB Documentation, R2023b. https://www.mathworks.com/help/matlab/ref/norm.html
- MathWorks. "vecnorm - Vector-wise norm." MATLAB Documentation, R2023b. https://www.mathworks.com/help/matlab/ref/vecnorm.html
- Eckart, C., & Young, G. (1936). "The approximation of one matrix by another of lower rank." Psychometrika, 1(3), 211–218.
- MathWorks. "normest - 2-norm estimate." MATLAB Documentation, R2023b.
- Candès, E. J., & Recht, B. (2009). "Exact matrix completion via convex optimization." Foundations of Computational Mathematics, 9(6), 717–772.
- Higham, N. J. (2002). Accuracy and Stability of Numerical Algorithms (2nd ed.). SIAM.
- Blue, J. L. (1978). "A portable Fortran program to find the Euclidean norm of a vector." ACM TOMS, 4(1), 15–23.
- Pascanu, R., Mikolov, T., & Bengio, Y. (2013). "On the difficulty of training recurrent neural networks." ICML.
- Tibshirani, R. (1996). "Regression shrinkage and selection via
微信扫一扫分享
打开微信「扫一扫」,扫描二维码后在微信中分享给好友或朋友圈。
💬 评论 (0)
评论功能已关闭

