在线性代数中,范数是为向量空间中的每个向量分配严格正的长度或大小的函数。它是矢量大小的度量。
从数学上来说,对于一个向量x
, the p
-范数定义为||x||p = (sum |xi|^p)^(1/p)
.
在本教程中,我们将使用numpy.linalg.norm()
function,这是Python中用于计算范数的关键函数。
numpy.linalg.norm() 的语法和参数
用于计算范数的函数NumPy is numpy.linalg.norm()
。这是它的语法:
numpy.linalg.norm(x, ord=None, axis=None, keepdims=False)
参数如下:
-
x
:输入数组。它可以是向量或矩阵。
-
ord
: 正常顺序。它可以是任何正数、np.inf、-np.inf、0、1 或 2.
-
axis
:计算范数所沿的一个或多个轴。如果这是一个整数元组,则在多个维度上计算范数。
-
keepdims
:如果设置为 True,则标准化的轴将作为尺寸为 1 的维度保留在结果中。
下面是它的使用示例:
import numpy as np
# Define a vector
vector = np.array([1, -2, 3, -4, 5])
# Compute L1 norm
l1_norm = np.linalg.norm(vector, ord=1)
print("L1 Norm: ", l1_norm)
Output:
L1 Norm: 15.0
在上面的代码中,我们定义了一个向量并使用以下方法计算其 L1 范数numpy.linalg.norm()
。我们传递向量并且ord=1
计算L1范数,结果为15.0
.
标准化与采用规范
标准化对数据进行缩放,使其落在特定范围内,通常在 0 到 1 之间。
取向量的范数可以计算向量空间中向量的大小或长度。
下面是一个例子来说明差异:
import numpy as np
vector = np.array([1, 2, 3, 4, 5])
# Normalize the vector
normalized_vector = vector / np.linalg.norm(vector)
# Compute the l2 norm (Euclidean distance)
l2_norm = np.linalg.norm(vector)
print("Normalized Vector: ", normalized_vector)
print("L2 Norm: ", l2_norm)
Output:
Normalized Vector: [0.13483997 0.26967994 0.40451992 0.53935989 0.67419986]
L2 Norm: 7.416198487095663
在此代码中,我们首先定义一个向量,然后通过将向量中的每个元素除以向量的 L2 范数来对其进行归一化。
我们还计算原始向量的 L2 范数。正如我们所看到的,归一化向量的数据在 0 和 1 之间重新缩放,而 L2 范数输出表示原始向量的长度或大小的单个数字。
向量范数的类型
有不同类型的向量范数,包括:
- L1范数:也称为曼哈顿距离,它是向量中元素的绝对值之和。
- L2范数:也称为欧氏距离,它是向量中每个元素的平方和的平方根。
- 无穷范数:该范数给出向量元素之间的最大绝对值。
- 负无穷范数:该范数给出向量元素中的最小绝对值。
让我们计算一下这些规范的每种类型。
L1范数(曼哈顿距离)
L1 范数也称为曼哈顿距离,计算为向量中元素的绝对值之和。
当绝对值的差异更重要时,它特别有用。以下是计算 L1 范数的方法:
import numpy as np
vector = np.array([1, -2, 3, -4, 5])
# Compute L1 norm
l1_norm = np.linalg.norm(vector, ord=1)
print("L1 Norm: ", l1_norm)
Output:
L1 Norm: 15.0
在上面的代码中,我们首先定义一个向量。然后我们使用以下方法计算向量的 L1 范数np.linalg.norm()
with ord=1
。结果是15.0
,它是向量中元素的绝对值之和。
L2范数(欧几里得距离)
L2范数,也称为欧几里得距离,是向量中元素的平方和的平方根。
它通常用于测量空间中点之间的距离。以下是计算 L2 范数的方法:
import numpy as np
vector = np.array([1, -2, 3, -4, 5])
# Compute L2 norm
l2_norm = np.linalg.norm(vector, ord=2)
print("L2 Norm: ", l2_norm)
Output:
L2 Norm: 7.416198487095663
在上面的代码中,我们首先定义一个向量。然后我们使用以下方法计算向量的 L2 范数np.linalg.norm()
with ord=2
.
结果是7.416198487095663
,它是向量中元素的平方和的平方根。
无穷范数(最大范数)
无穷范数,也称为最大范数,返回向量元素中的最大绝对值。
以下是计算无穷范数的方法:
import numpy as np
vector = np.array([1, -2, 3, -4, 5])
# Compute Infinity norm
infinity_norm = np.linalg.norm(vector, ord=np.inf)
print("Infinity Norm: ", infinity_norm)
Output:
Infinity Norm: 5.0
在上面的代码中,我们首先定义一个向量。然后我们使用以下方法计算向量的无穷范数np.linalg.norm()
with ord=np.inf
.
结果是5.0
,它是向量元素中的最大绝对值。
负无穷范数(最小范数)
负无穷范数,也称为最小范数,返回向量元素中的最小绝对值。
以下是计算负无穷范数的方法:
import numpy as np
vector = np.array([1, -2, 3, -4, 5])
# Compute Negative Infinity norm
negative_infinity_norm = np.linalg.norm(vector, ord=-np.inf)
print("Negative Infinity Norm: ", negative_infinity_norm)
Output:
Negative Infinity Norm: 1.0
在上面的代码中,我们首先定义一个向量。然后我们使用以下方法计算向量的负无穷范数np.linalg.norm()
with ord=-np.inf
.
结果是1.0
,它是向量元素中的最小绝对值。
计算其他 p 范数
除了 L1、L2、无穷大和负无穷范数之外,您还可以计算任何其他范数p
-规范使用numpy.linalg.norm()
.
The p
-范数定义为(sum |x_i|^p)^(1/p)
.
这是一个计算向量 3-范数的示例:
import numpy as np
vector = np.array([1, -2, 3, -4, 5])
# Compute 3-norm
p3_norm = np.linalg.norm(vector, ord=3)
print("3-Norm: ", p3_norm)
Output:
3-Norm: 6.082201995573399
在上面的代码中,我们首先定义一个向量。然后我们使用以下方法计算向量的 3-范数np.linalg.norm()
with ord=3
.
结果是6.082201995573399
,它是向量中元素绝对值的立方和的立方根。
矩阵范数解释
矩阵范数是向量范数的扩展。对于矩阵,我们有几种类型的范数。最流行的是:
- Frobenius Norm:其元素绝对平方和的平方根,类似于向量的 L2 范数。
- 谱范数(2-范数):矩阵的最大奇异值(即矩阵厄米特最大特征值的平方根)。
- 1-范数:矩阵的最大绝对列和。
- ∞-范数:矩阵的最大绝对行和。
矩阵范数可以使用相同的方法计算numpy.linalg.norm()
函数作为向量范数,但我们必须输入一个二维数组而不是一维数组。
让我们在下一节中计算这些矩阵范数。
弗罗贝尼乌斯范数
以下是计算 Frobenius 范数的方法:
import numpy as np
matrix = np.array([[1, -2, 3], [-4, 5, -6], [7, -8, 9]])
# Compute Frobenius norm
frobenius_norm = np.linalg.norm(matrix, ord='fro')
print("Frobenius Norm: ", frobenius_norm)
Output:
Frobenius Norm: 16.881943016134134
在上面的代码中,我们首先定义一个矩阵。然后我们使用以下方法计算矩阵的 Frobenius 范数np.linalg.norm()
with ord='fro'
.
结果是16.881943016134134
,它是矩阵中元素的平方和的平方根。
谱范数(最大奇异值)
以下是计算谱范数的方法:
import numpy as np
# Define a matrix
matrix = np.array([[1, -2, 3], [-4, 5, -6], [7, -8, 9]])
# Compute Spectral norm
spectral_norm = np.linalg.norm(matrix, ord=2)
print("Spectral Norm: ", spectral_norm)
Output:
Spectral Norm: 16.84810335261421
在上面的代码中,我们首先定义一个矩阵。然后我们使用计算矩阵的谱范数np.linalg.norm()
with ord=2
.
结果是16.84810335261421
,这是矩阵的最大奇异值。
计算其他归纳范数(1-范数、∞-范数)
以下是计算 1-范数和 Infini-范数的方法:
import numpy as np
matrix = np.array([[1, -2, 3], [-4, 5, -6], [7, -8, 9]])
# Compute 1-Norm
one_norm = np.linalg.norm(matrix, ord=1)
# Compute ∞-Norm
inf_norm = np.linalg.norm(matrix, ord=np.inf)
print("1-Norm: ", one_norm)
print("∞-Norm: ", inf_norm)
Output:
1-Norm: 18.0
∞-Norm: 24.0
在上面的代码中,我们首先定义一个矩阵。然后我们使用以下方法计算矩阵的 1-范数和 Infini-范数np.linalg.norm()
with ord=1
and ord=np.inf
分别。
1-范数结果是18.0
,这是矩阵的最大绝对列和。
∞-范数结果是24.0
,这是矩阵的最大绝对行和。
性能比较
为了比较性能,我们计算一个大向量的 L1 范数和 L2 范数并测量计算时间:
import numpy as np
import time
# Create a large vector
vector = np.random.rand(1000000)
# Compute L1 norm and measure time
start_time = time.time()
l1_norm = np.linalg.norm(vector, ord=1)
end_time = time.time()
print("L1 norm: ", l1_norm)
print("Time for L1 norm: %s seconds" % (end_time - start_time))
# Compute L2 norm and measure time
start_time = time.time()
l2_norm = np.linalg.norm(vector, ord=2)
end_time = time.time()
print("L2 norm: ", l2_norm)
print("Time for L2 norm: %s seconds" % (end_time - start_time))
注意:每次运行时,确切的输出都会有所不同,因为我们正在创建一个随机向量:
L1 norm: 500205.0234115845
Time for L1 norm: 0.006276130676269531 seconds
L2 norm: 577.4774120713894
Time for L2 norm: 0.00099945068359375 seconds
在这种情况下,计算 L2 范数比计算 L1 范数更快。
使用 numpy.linalg.norm() 时的常见错误
误认为默认标准: 默认情况下,numpy.linalg.norm()
计算矩阵的 Frobenius 范数和向量的 2-范数(欧几里得距离)。
始终指定ord
如果您想要不同的规范,请使用参数。
# Wrong usage for L1 norm
vector = np.array([1, -2, 3, -4, 5])
wrong_l1_norm = np.linalg.norm(vector) # This computes L2 norm, not L1
print("Wrong L1 Norm: ", wrong_l1_norm)
# Correct usage for L1 norm
correct_l1_norm = np.linalg.norm(vector, ord=1)
print("Correct L1 Norm: ", correct_l1_norm)
Output:
Wrong L1 Norm: 7.416198487095663
Correct L1 Norm: 15.0
将矩阵范数误认为向量范数:如果您正在处理矩阵,请确保使用矩阵范数。
例如,使用ord=1
使用矩阵将计算最大绝对列和,而不是所有元素的绝对值之和。
# Wrong usage for matrix
matrix = np.array([[1, -2, 3], [-4, 5, -6], [7, -8, 9]])
wrong_l1_norm = np.linalg.norm(matrix, ord=1) # This computes max column sum, not sum of absolute values
print("Wrong L1 Norm: ", wrong_l1_norm)
# Correct usage for matrix
correct_fro_norm = np.linalg.norm(matrix, ord='fro') # Frobenius norm gives the square root of sum of squares of all elements
print("Correct Frobenius Norm: ", correct_fro_norm)
Output:
Wrong L1 Norm: 18.0
Correct Frobenius Norm: 16.881943016134134
不考虑负无穷范数:负无穷范数返回数组中的最小绝对值,而不是最小值本身。
这意味着在选择最小的数之前,负数将变为正数。
vector = np.array([1, -2, 3, -4, 5])
neg_inf_norm = np.linalg.norm(vector, ord=-np.inf)
print("Negative Infinity Norm: ", neg_inf_norm)
Output:
Negative Infinity Norm: 1.0
numpy.linalg.norm() 的实际应用
规范在各种现实应用中发挥着不可或缺的作用,特别是在机器学习和数据科学中。
这是我们如何使用 L2 范数的示例自然语言处理(NLP) 用于文本向量标准化。
在此示例中,我们将使用TfidfVectorizer
from sklearn
,它将文本转换为可用作机器学习模型输入的特征向量。
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
# Sample corpus
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
vectorizer = TfidfVectorizer()
# Fit and transform the corpus
X = vectorizer.fit_transform(corpus)
# Get the first document's vector
first_vector = X[0].toarray()
# Before normalization
print("Before normalization: ", first_vector)
# Compute L2 norm
l2_norm = np.linalg.norm(first_vector, ord=2)
# After normalization
normalized_vector = first_vector / l2_norm
print("After normalization: ", normalized_vector)
Output:
Before normalization: [[0. 0.46979139 0.58028582 0.38408524 0. 0.
0.38408524 0. 0.38408524]]
After normalization: [[0. 0.46979139 0.58028582 0.38408524 0. 0.
0.38408524 0. 0.38408524]]
在上面的代码中,我们首先定义了四个文档的语料库。然后我们初始化一个TfidfVectorizer
,它将原始文档集合转换为 TF-IDF 特征矩阵。
我们使用矢量化器来拟合和转换我们的语料库。然后我们选择第一个文档的向量。
在标准化之前,向量的值的范围可能很大,具体取决于文档的长度和每个单词的频率。
在计算向量的 L2 范数并通过将向量除以 L2 范数来标准化向量后,所得向量的长度(或大小)为 1。
进一步阅读
https://numpy.org/doc/stable/reference/ generated/numpy.linalg.norm.html