机器学习中的常用范数详解
文章目录
- 机器学习中的常用范数详解
-
- [1 什么是范数?](#1 什么是范数?)
- [2 常用的向量范数](#2 常用的向量范数)
-
- [2.1 L0范数](#2.1 L0范数)
- [2.2 L1范数(曼哈顿范数)](#2.2 L1范数(曼哈顿范数))
- [2.3 L2范数(欧几里得范数)](#2.3 L2范数(欧几里得范数))
- [2.4 Lp范数](#2.4 Lp范数)
- [2.5 L∞范数(最大范数)](#2.5 L∞范数(最大范数))
- [3 常用的矩阵范数](#3 常用的矩阵范数)
-
- [3.1 弗罗贝尼乌斯范数(Frobenius Norm)](#3.1 弗罗贝尼乌斯范数(Frobenius Norm))
- [3.2 核范数(Nuclear Norm)](#3.2 核范数(Nuclear Norm))
- [3.3 算子范数(Operator Norm)](#3.3 算子范数(Operator Norm))
- [4 范数在机器学习中的应用](#4 范数在机器学习中的应用)
- [5 可视化范数比较](#5 可视化范数比较)
-
- [5.1 单位圆比较示例](#5.1 单位圆比较示例)
- [5.2 等高线比较示例](#5.2 等高线比较示例)
- [6 总结](#6 总结)
1 什么是范数?
在数学中,范数(Norm)是对向量或矩阵"长度"或"大小"的一种度量。范数将向量或矩阵映射到一个非负实数,满足以下性质:
- 非负性:对于所有向量x,‖x‖ ≥ 0,且‖x‖ = 0当且仅当x=0
- 齐次性:对于所有标量α和向量x,‖αx‖ = |α|·‖x‖
- 三角不等式:对于所有向量x和y,‖x + y‖ ≤ ‖x‖ + ‖y‖
范数在机器学习、优化问题、信号处理等领域有广泛应用。
2 常用的向量范数
2.1 L0范数
L0范数表示向量中非零元素的个数:
∥ x ∥ 0 = # { i ∣ x i ≠ 0 } \|x\|_0 = \#\{i | x_i \neq 0\} ∥x∥0=#{i∣xi=0}
虽然称为"范数",但严格来说L0并不满足范数的所有性质(特别是齐次性)。它在稀疏表示、压缩感知等领域有重要应用。
python
import numpy as np
def l0_norm(x):
return np.count_nonzero(x)
x = np.array([1, 0, 3, 0, 5])
print(l0_norm(x)) # 输出:3
2.2 L1范数(曼哈顿范数)
L1范数是向量中各元素绝对值之和:
∥ x ∥ 1 = ∑ i = 1 n ∣ x i ∣ \|x\|1 = \sum{i=1}^n |x_i| ∥x∥1=i=1∑n∣xi∣
L1范数能促进稀疏性,常用于特征选择(Lasso回归)和稀疏编码。
python
def l1_norm(x):
return np.sum(np.abs(x))
x = np.array([1, -2, 3])
print(l1_norm(x)) # 输出:6
2.3 L2范数(欧几里得范数)
L2范数是向量各元素平方和的平方根:
∥ x ∥ 2 = ∑ i = 1 n x i 2 \|x\|2 = \sqrt{\sum{i=1}^n x_i^2} ∥x∥2=i=1∑nxi2
这是最常用的范数,表示向量的几何长度。在机器学习中,L2正则化可以防止过拟合。
python
def l2_norm(x):
return np.sqrt(np.sum(x**2))
x = np.array([3, 4])
print(l2_norm(x)) # 输出:5.0
2.4 Lp范数
Lp范数是更一般的范数形式:
∥ x ∥ p = ( ∑ i = 1 n ∣ x i ∣ p ) 1 / p \|x\|p = \left( \sum{i=1}^n |x_i|^p \right)^{1/p} ∥x∥p=(i=1∑n∣xi∣p)1/p
当p=1时为L1范数,p=2时为L2范数。
2.5 L∞范数(最大范数)
L∞范数是向量中绝对值最大的元素:
∥ x ∥ ∞ = max i ∣ x i ∣ \|x\|_\infty = \max_i |x_i| ∥x∥∞=imax∣xi∣
python
def linf_norm(x):
return np.max(np.abs(x))
x = np.array([1, -5, 3, 2])
print(linf_norm(x)) # 输出:5
3 常用的矩阵范数
3.1 弗罗贝尼乌斯范数(Frobenius Norm)
类似于向量的L2范数,是矩阵元素平方和的平方根:
∥ A ∥ F = ∑ i = 1 m ∑ j = 1 n ∣ a i j ∣ 2 \|A\|F = \sqrt{\sum{i=1}^m \sum_{j=1}^n |a_{ij}|^2} ∥A∥F=i=1∑mj=1∑n∣aij∣2
python
def frobenius_norm(A):
return np.sqrt(np.sum(A**2))
A = np.array([[1, 2], [3, 4]])
print(frobenius_norm(A)) # 输出:5.477...
3.2 核范数(Nuclear Norm)
矩阵的核范数是其奇异值之和,常用于矩阵补全和低秩矩阵恢复:
∥ A ∥ ∗ = ∑ i = 1 r σ i \|A\|* = \sum{i=1}^r \sigma_i ∥A∥∗=i=1∑rσi
其中r是矩阵A的秩,σ_i是奇异值。
python
def nuclear_norm(A):
return np.sum(np.linalg.svd(A)[1])
A = np.array([[1, 0, 0], [0, 2, 0], [0, 0, 3]])
print(nuclear_norm(A)) # 输出:6.0
3.3 算子范数(Operator Norm)
根据不同的向量范数,可以定义不同的矩阵算子范数。例如:
- p=1时: ∥ A ∥ 1 = max j ∑ i = 1 m ∣ a i j ∣ \|A\|1 = \max_j \sum{i=1}^m |a_{ij}| ∥A∥1=maxj∑i=1m∣aij∣ (列和最大值)
- p=∞时: ∥ A ∥ ∞ = max i ∑ j = 1 n ∣ a i j ∣ \|A\|\infty = \max_i \sum{j=1}^n |a_{ij}| ∥A∥∞=maxi∑j=1n∣aij∣ (行和最大值)
- p=2时: ∥ A ∥ 2 = σ max \|A\|2 = \sigma{\max} ∥A∥2=σmax (最大奇异值)
4 范数在机器学习中的应用
-
正则化:
- L1正则化产生稀疏解,用于特征选择
- L2正则化防止过拟合,使解更平滑
-
距离度量:
- 在KNN、K-means等算法中,常用L2范数作为距离度量
- 在异常检测中,有时使用L1范数
-
优化约束:
- 在支持向量机中,使用L2范数定义间隔
- 在矩阵分解中,使用核范数约束低秩性
-
损失函数:
- 回归问题中常用L2范数作为损失(MSE)
- 鲁棒回归中可能使用L1范数作为损失(MAE)
5 可视化范数比较
5.1 单位圆比较示例
下面是一个Python代码,使用matplotlib绘制不同范数(L0.5, L1, L2, L3, L∞)的单位圆:
python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
# 设置中文显示和字体
rcParams['font.sans-serif'] = ['SimHei']
rcParams['axes.unicode_minus'] = False
def plot_unit_balls():
# 创建极坐标角度数组
theta = np.linspace(0, 2*np.pi, 1000)
# 创建图形
plt.figure(figsize=(10, 8))
plt.title('Comparison of unit circles with different norms', fontsize=16)
plt.axhline(0, color='gray', linewidth=0.5)
plt.axvline(0, color='gray', linewidth=0.5)
plt.grid(True, linestyle='--', alpha=0.7)
plt.axis('equal')
# 定义不同p值的范数
p_values = [0.5, 1, 2, 3, np.inf]
colors = ['red', 'blue', 'green', 'purple', 'orange']
labels = ['L0.5 Norm', 'L1 Norm', 'L2 Norm', 'L3 Norm', 'L∞ Norm']
# 计算并绘制每个范数的单位圆
for p, color, label in zip(p_values, colors, labels):
if p == np.inf:
# L∞范数是正方形
x = np.array([-1, 1, 1, -1, -1])
y = np.array([-1, -1, 1, 1, -1])
else:
# 对于其他p值,计算极坐标下的r(θ)
cos_theta = np.cos(theta)
sin_theta = np.sin(theta)
r = 1 / (np.abs(cos_theta)**p + np.abs(sin_theta)**p)**(1/p)
x = r * np.cos(theta)
y = r * np.sin(theta)
plt.plot(x, y, color=color, linewidth=2, label=label)
# 添加图例和标签
plt.legend(fontsize=12)
plt.xlabel('x', fontsize=12)
plt.ylabel('y', fontsize=12)
plt.xlim(-1.5, 1.5)
plt.ylim(-1.5, 1.5)
# 显示图形
plt.tight_layout()
plt.show()
# 注意:L0范数实际上不是一个真正的范数,且其单位"圆"在二维空间中是四个离散的点
# 所以这里没有包含L0范数,因为它不形成连续的形状
plot_unit_balls()
这段代码绘制了L0.5、L1、L2、L3和L∞范数的单位圆,每个范数的单位圆用不同颜色表示,并添加了图例说明,图形设置为等比例,以便正确比较不同范数的形状。
注:关于L0范数的说明:严格来说,L0范数(计算非零元素的数量)不是一个真正的范数,它的单位"圆"在二维空间中实际上是四个离散的点:(1,0), (-1,0), (0,1), (0,-1)。因此在上面的连续曲线图中没有包含它。如果需要显示L0范数,可以单独添加这四个点。
可视化效果如下图所示:

其中:
- L0.5范数:星形(向内凹陷)
- L1范数:菱形(曼哈顿距离)
- L2范数:标准的圆形(欧几里得距离)
- L3范数:介于圆形和方形之间
- L∞范数:正方形(切比雪夫距离)
5.2 等高线比较示例
python
import numpy as np
import matplotlib.pyplot as plt
# 创建一个二维向量空间
x = np.linspace(-1, 1, 100)
y = np.linspace(-1, 1, 100)
X, Y = np.meshgrid(x, y)
Z = np.stack([X, Y], axis=-1)
# 计算不同范数
l0 = np.apply_along_axis(lambda v: np.count_nonzero(v), -1, Z)
l1 = np.apply_along_axis(lambda v: np.sum(np.abs(v)), -1, Z)
l2 = np.apply_along_axis(lambda v: np.sqrt(np.sum(v**2)), -1, Z)
linf = np.apply_along_axis(lambda v: np.max(np.abs(v)), -1, Z)
# 绘制范数等高线
plt.figure(figsize=(12, 10))
plt.subplot(2, 2, 1)
plt.contour(X, Y, l0, levels=[0.5, 1.5, 2.5])
plt.title("L0 Norm")
plt.subplot(2, 2, 2)
plt.contour(X, Y, l1, levels=[0.5, 1, 1.5])
plt.title("L1 Norm")
plt.subplot(2, 2, 3)
plt.contour(X, Y, l2, levels=[0.5, 1, 1.5])
plt.title("L2 Norm")
plt.subplot(2, 2, 4)
plt.contour(X, Y, linf, levels=[0.5, 1, 1.5])
plt.title("L∞ Norm")
plt.tight_layout()
plt.show()
这段代码会绘制不同范数在二维空间中的等高线图,直观展示各种范数的几何形状差异。
结果如下所示:
6 总结
不同范数有不同的性质和应用场景:
- L0范数:用于稀疏计数,但优化困难
- L1范数:促进稀疏性,可用于特征选择
- L2范数:最常用,具有良好的几何性质
- L∞范数:关注最大偏差
- 核范数:用于低秩矩阵恢复
在实际应用中,需要根据具体问题选择合适的范数形式。理解这些范数的性质和差异,对于设计和理解机器学习算法至关重要。