Python实战:5分钟搞懂NumPy中的向量范数与矩阵范数计算
如果你在数据科学或机器学习领域摸爬滚打了一段时间,大概率会碰到“范数”这个词。它听起来有点数学,有点抽象,但当你真正在代码里用起来,比如用NumPy的np.linalg.norm函数时,可能会觉得它就是个计算“长度”或“大小”的工具。这种直觉没错,但范数的世界远比“长度”要丰富得多。不同的范数,就像不同的尺子,衡量向量和矩阵的方式截然不同,这直接影响了从数据预处理到模型正则化、再到算法稳定性的方方面面。
今天,我们不打算复刻那些厚重的数值分析教材。相反,我会带你直接跳进Python和NumPy的实践环境,通过具体的代码和可视化的对比,在几分钟内建立起对L1、L2、无穷范数等核心概念的直观感受。你会发现,理解它们不仅是为了应付数学考试,更是为了在构建更鲁棒、更高效的模型时,手里能多几把趁手的“量尺”。
1. 从直觉开始:向量范数到底是什么?
抛开严谨的数学定义,我们可以把向量范数想象成给向量“打分”或“测量”的一套规则。给定一个向量,比如 x = [1, -2, 3],不同的范数会给出不同的“大小”数值。这个数值必须满足几个基本公理(非负性、齐次性、三角不等式),但对我们使用者来说,更重要的是理解每种范数背后的“关注点”。
在NumPy中,计算向量范数的核心函数是 numpy.linalg.norm。它的基本调用方式很简单:
import numpy as np
x = np.array([1, -2, 3])
norm_value = np.linalg.norm(x, ord=None) # 默认是L2范数
这里的 ord 参数就是指定范数类型的钥匙。让我们看看最常见的几种:
-
L1范数 (
ord=1): 也称为曼哈顿距离或出租车距离。它把所有元素的绝对值加起来。对于向量x,L1 = |1| + |-2| + |3| = 6。你可以想象在曼哈顿街区,从A点到B点只能沿网格走,走过的总街区数就是L1距离。它在机器学习中的一个著名应用是Lasso回归的正则化项,因为它倾向于产生稀疏解(即把一些特征的系数压到0)。 -
L2范数 (
ord=2): 这就是我们最熟悉的欧几里得距离。计算所有元素平方和的平方根。对于x,L2 = sqrt(1^2 + (-2)^2 + 3^2) = sqrt(14) ≈ 3.742。它是衡量向量“几何长度”最自然的方式,也是岭回归(Ridge Regression)和神经网络中权重衰减(Weight Decay)最常用的正则化项。 -
无穷范数 (
ord=np.inf): 它只关心向量中绝对值最大的那个元素。对于x,L_inf = max(|1|, |-2|, |3|) = 3。这个范数衡量的是向量分量的“最大偏差”,在控制误差上界时特别有用。
为了让你更直观地感受不同范数如何“看待”空间,我们可以画个图。假设我们考虑所有满足 ||x||_p = 1 的二维向量 x = [x1, x2],随着 p 值的变化,这个“单位圆”的形状会剧烈变化。
import matplotlib.pyplot as plt
import numpy as np
theta = np.linspace(0, 2*np.pi, 200)
p_values = [0.5, 1, 2, 5, np.inf]
colors = ['r', 'g', 'b', 'orange', 'purple']
labels = ['p=0.5', 'p=1 (L1)', 'p=2 (L2)', 'p=5', 'p=∞']
plt.figure(figsize=(8, 8))
for p, color, label in zip(p_values, colors, labels):
# 计算对应p范数下的单位“圆”坐标
# 对于p范数,|x1|^p + |x2|^p = 1
# 参数化表示: x1 = (cosθ)^(2/p), x2 = (sinθ)^(2/p) * sign(sinθ) (简化处理,仅示意)
# 这里我们用更通用的数值方法生成点
if p == np.inf:
# 无穷范数单位“圆”是一个正方形
x = np.array([-1, 1, 1, -1, -1])
y = np.array([-1, -1, 1, 1, -1])
else:
# 生成角度,计算对应坐标
# 使用参数方程: x1 = cos(θ) / (|cos(θ)|^p + |sin(θ)|^p)^(1/p), x2同理
cos_t = np.cos(theta)
sin_t = np.sin(theta)
denom = (np.abs(cos_t)**p + np.abs(sin_t)**p) ** (1/p)
x = cos_t / denom
y = sin_t / denom
plt.plot(x, y, color=color, label=label, linewidth=2)
plt.axhline(y=0, color='k', linestyle=':', alpha=0.3)
plt.axvline(x=0, color='k', linestyle=':', alpha=0.3)
plt.axis('equa

467

被折叠的 条评论
为什么被折叠?



