在前面的例子中,我们已经讨论了标量的概念,并展示了如何使用代码对标量进行基本的算术运算。接下来,我将进一步说明该过程,并解释每一步的实现。
标量(Scalar)的基本操作
标量是只有一个元素的数值。它可以是整数、浮点数等。通过下面的 Python 代码,我们可以很容易地进行标量的加法、乘法、除法和指数运算。
代码实现:
import torch
# 定义两个标量
x = torch.tensor(3.0) # 标量x,值为3.0
y = torch.tensor(2.0) # 标量y,值为2.0
# 执行加法、乘法、除法、指数运算
x + y, x * y, x / y, x**y
输出解释:
x + y
:标量的加法,3.0 + 2.0 = 5.0x * y
:标量的乘法,3.0 * 2.0 = 6.0x / y
:标量的除法,3.0 / 2.0 = 1.5x**y
:标量的指数运算,3.0 的 2 次方,即 3.0^2 = 9.0
输出:
(tensor(5.), tensor(6.), tensor(1.5000), tensor(9.))
在这里,tensor(5.)
表示存储标量值 5.0 的张量。通过这种方式,我们可以将基本的标量运算转化为机器可执行的代码。
在这个小节中,我们将介绍 向量 的概念以及如何使用代码表示和操作向量。
向量(Vector)的定义
向量是由标量组成的列表,可以看作是多维数据的表示。向量的每个分量都有其特定的含义,比如在某些机器学习应用中,向量的分量可能代表特定样本的特征,如收入、年龄、健康指标等。
在数学符号中,向量通常记作粗体的小写字母,例如 ( \mathbf{x}, \mathbf{y}, \mathbf{z} )。如果一个向量包含 (n) 个元素,可以表示为:
[
\mathbf{x} = \begin{bmatrix} x_1 \ x_2 \ \vdots \ x_n \end{bmatrix}
]
其中,( x_i ) 是向量的第 (i) 个元素。
向量的代码实现
在深度学习框架中,向量可以用 一维张量 来表示。我们可以轻松创建一个包含多个元素的向量,并访问其任意元素。
代码示例:
import torch
# 创建一个向量(长度为4)
x = torch.arange(4) # 创建包含 0, 1, 2, 3 的向量
print(x) # 输出整个向量
输出:
tensor([0, 1, 2, 3])
在这个例子中,torch.arange(4)
创建了一个向量,包含从 0 到 3 的 4 个元素。
访问向量中的元素
我们可以通过索引访问向量中的任意元素。请注意,索引是从 0 开始的。
代码示例:
# 访问向量的第 4 个元素(索引为 3)
print(x[3]) # 输出 tensor(3)
输出:
tensor(3)
在这个例子中,我们通过 x[3]
访问向量中的第四个元素(索引从 0 开始),即 3。
长度、维度和形状
向量:向量可以看作一个数字数组。每个向量都有一个长度,在数学上我们表示一个向量由若干个实值标量组成,向量的长度通常称为维度(dimension)。
长度获取:与普通的 Python 数组一样,我们可以通过调用 Python 的内置
len()
函数来获取向量的长度。例如,在深度学习框架(如 MXNet、PyTorch、TensorFlow 和 Paddle)中,len(x)
可以返回向量的长度。
print(len(x)) # 返回 4,表示向量的长度
- 形状:当用张量表示一个向量时(只有一个轴),我们可以通过
.shape
属性访问该向量的长度。形状(shape)是一个列出张量每个轴长度的元素组。对于一维张量,其形状为(n,)
,例如:
print(x.shape) # 返回 torch.Size([4]),表示张量有一个长度为 4 的轴
- 术语解释:
- 向量或轴的维度:指向量或轴的长度,即元素的数量。
- 张量的维度:指张量拥有的轴数,张量的某个轴的维数就是该轴的长度。
矩阵
矩阵:将向量扩展到二阶,通常用粗体大写字母表示,如 ( A )、( B ) 等。矩阵在代码中表示为具有两个轴的张量。矩阵 ( A ) 的形状为 ( (m, n) ),其中 ( m ) 是行数,( n ) 是列数。若行列相等,称为方阵。
创建矩阵:可以通过函数指定行数和列数来创建矩阵。例如:
A = torch.arange(20).reshape(5, 4)
访问元素:通过行索引和列索引访问矩阵中的元素,如 ( A_{i,j} )。在表达式中,通常使用小写字母和下标来表示矩阵的某个元素。
矩阵转置:交换矩阵的行和列称为转置,用 ( A^T ) 表示。代码中访问转置矩阵:
A.T
对称矩阵:若矩阵等于其转置,则称为对称矩阵。可以通过代码比较矩阵与其转置是否相等,例如:
B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]]) B == B.T # 返回一个布尔矩阵,表示是否对称
应用场景:矩阵常用于组织和处理具有不同模式的数据,例如,行对应不同的数据样本,列对应不同的属性。在深度学习中,这种方式很常见,支持小批量数据的处理。
import torch
# 矩阵是将向量从一阶推广到二阶,通常用粗体大写字母表示,例如 A 和 B。
# 矩阵在代码中表示为具有两个轴的张量。
# 创建一个 5 行 4 列的矩阵 A
A = torch.arange(20).reshape(5, 4)
print("矩阵 A:")
print(A)
# 可以通过行索引和列索引访问矩阵中的元素。
# 例如访问 A 的第 1 行,第 2 列的元素 A[1-1, 2-1]
element = A[1-1, 2-1]
print(f"A[0, 1] 的元素值为: {element}")
# 交换矩阵的行和列称为转置,用 A.T 表示
A_T = A.T
print("矩阵 A 的转置:")
print(A_T)
# 对称矩阵是一个特殊的矩阵,等于其转置
# 例如,创建一个 3x3 的对称矩阵 B
B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
print("对称矩阵 B:")
print(B)
# 比较 B 与 B.T,判断是否为对称矩阵
is_symmetric = B == B.T
print("B 是否对称 (B == B.T):")
print(is_symmetric)
# 矩阵可以用于组织不同模式的数据,例如行可以对应不同的数据样本,列对应不同的属性。
# 这种方式在深度学习中很常见。
张量
张量的定义:张量是具有任意数量轴的高维数组。向量是一阶张量,矩阵是二阶张量,张量的维度可以更高,用于表示更复杂的数据结构。张量的索引机制与矩阵类似,通常用特殊字体的大写字母表示(如 ( X )、( Y ) 等)。
图像与张量:当处理图像时,张量非常重要。图像可以表示为一个三维数组,其中三个轴对应图像的高度、宽度,以及通道(channel),例如红、绿、蓝颜色通道。
张量示例:下面的代码展示了一个形状为 ( (2, 3, 4) ) 的三阶张量,其中有 2 个矩阵,每个矩阵包含 3 行 4 列的元素。
import torch
# 创建一个形状为 (2, 3, 4) 的张量 X
X = torch.arange(24).reshape(2, 3, 4)
print("三阶张量 X:")
print(X)
输出:
三阶张量 X:
tensor([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
在这个例子中,张量 X
的形状是 (2, 3, 4)
,它包含 2 个 3x4 的矩阵。每个矩阵包含 3 行和 4 列的数据。这展示了张量的基本结构,未来可以进一步扩展到更复杂的多维数据,例如处理图像时的三维张量。
张量的基本性质
按元素操作:
- 对张量执行的按元素操作不会改变张量的形状。无论是一元运算还是二元运算,结果张量的形状和操作数保持一致。
- 例如,将两个相同形状的张量相加或相乘,结果仍是相同形状的张量。
Hadamard积:
- 两个矩阵的按元素乘法称为 Hadamard 积。其结果是对应元素相乘的矩阵。
张量与标量运算:
- 张量与标量相加或相乘不会改变张量的形状,运算结果是对每个元素进行相同的操作。
代码示例
import torch
# 创建两个相同形状的矩阵 A 和 B
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
B = A.clone() # 复制 A 到 B
print("矩阵 A:")
print(A)
print("矩阵 B:")
print(B)
# 对两个矩阵执行按元素加法
print("A + B 的结果:")
print(A + B)
# Hadamard 积 (按元素乘法)
print("A 和 B 的 Hadamard 积 (A * B):")
print(A * B)
# 张量与标量的运算
a = 2
X = torch.arange(24).reshape(2, 3, 4)
print("标量 a 与张量 X 的加法结果:")
print(a + X)
print("标量 a 与张量 X 的乘法结果的形状:")
print((a * X).shape)
输出结果:
矩阵 A:
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.],
[16., 17., 18., 19.]])
矩阵 B:
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.],
[16., 17., 18., 19.]])
A + B 的结果:
tensor([[ 0., 2., 4., 6.],
[ 8., 10., 12., 14.],
[16., 18., 20., 22.],
[24., 26., 28., 30.],
[32., 34., 36., 38.]])
A 和 B 的 Hadamard 积 (A * B):
tensor([[ 0., 1., 4., 9.],
[ 16., 25., 36., 49.],
[ 64., 81., 100., 121.],
[144., 169., 196., 225.],
[256., 289., 324., 361.]])
标量 a 与张量 X 的加法结果:
tensor([[[ 2, 3, 4, 5],
[ 6, 7, 8, 9],
[10, 11, 12, 13]],
[[14, 15, 16, 17],
[18, 19, 20, 21],
[22, 23, 24, 25]]])
标量 a 与张量 X 的乘法结果的形状:
torch.Size([2, 3, 4])
解释:
- A + B:矩阵
A
和B
的按元素相加,结果是同样形状的矩阵,每个元素是对应位置的元素相加。 - A * B:这是矩阵
A
和B
的 Hadamard 积,每个元素是对应位置的元素相乘。 - a + X:标量
a
与张量X
的相加操作,对X
的每个元素都加上标量a
,形状不变。 - a * X:标量
a
与张量X
的乘法,对X
的每个元素乘以a
,并且结果张量的形状依然保持不变。
这段笔记讲述了张量的降维操作,特别是通过求和与平均值计算来降低张量的维度。下面是详细总结并结合代码示例:
张量降维
求和操作:
- 对张量的所有元素进行求和,称为降维。默认情况下,求和操作会沿所有轴进行,使张量的维度降为标量。
- 通过指定轴(
axis
),可以选择沿哪个轴进行求和,从而降低维度。
示例:
import torch
# 创建一个向量 x
x = torch.arange(4, dtype=torch.float32)
print("向量 x:")
print(x)
# 对向量 x 进行求和
x_sum = x.sum()
print("向量 x 的元素和:")
print(x_sum)
# 创建一个 5x4 的矩阵 A
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
print("矩阵 A:")
print(A)
# 对矩阵 A 的所有元素进行求和
A_sum = A.sum()
print("矩阵 A 的元素和:")
print(A_sum)
# 沿轴 0(行)进行求和,降维为向量
A_sum_axis0 = A.sum(axis=0)
print("沿轴 0 降维后 (对每列求和) 的结果:")
print(A_sum_axis0)
# 沿轴 1(列)进行求和,降维为向量
A_sum_axis1 = A.sum(axis=1)
print("沿轴 1 降维后 (对每行求和) 的结果:")
print(A_sum_axis1)
# 同时沿轴 0 和轴 1 进行求和,相当于对所有元素求和
A_sum_all = A.sum(axis=[0, 1])
print("沿所有轴降维后 (对所有元素求和) 的结果:")
print(A_sum_all)
平均值计算:
- 平均值是通过将张量的元素和除以元素总数来计算的。
- 和求和操作一样,平均值计算也可以指定轴来降低维度。
平均值计算示例:
# 计算矩阵 A 的平均值
A_mean = A.mean()
print("矩阵 A 的平均值:")
print(A_mean)
# 沿轴 0 计算平均值
A_mean_axis0 = A.mean(axis=0)
print("沿轴 0 降维后的平均值 (对每列计算平均值):")
print(A_mean_axis0)
# 手动计算平均值,与直接调用 .mean() 结果相同
A_mean_manual = A.sum() / A.numel()
print("手动计算的平均值:")
print(A_mean_manual)
输出结果:
向量 x:
tensor([0., 1., 2., 3.])
向量 x 的元素和:
tensor(6.)
矩阵 A:
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.],
[16., 17., 18., 19.]])
矩阵 A 的元素和:
tensor(190.)
沿轴 0 降维后 (对每列求和) 的结果:
tensor([40., 45., 50., 55.])
沿轴 1 降维后 (对每行求和) 的结果:
tensor([ 6., 22., 38., 54., 70.])
沿所有轴降维后 (对所有元素求和) 的结果:
tensor(190.)
矩阵 A 的平均值:
tensor(9.5000)
沿轴 0 降维后的平均值 (对每列计算平均值):
tensor([ 8., 9., 10., 11.])
手动计算的平均值:
tensor(9.5000)
解释:
- 向量求和:计算向量
x
的所有元素和,结果为6
。 - 矩阵求和:矩阵
A
的所有元素求和结果为190
。可以指定轴来对行或列进行求和,得到相应的降维结果。 - 平均值:计算矩阵
A
的平均值,通过mean()
函数或手动求和除以元素总数得到结果。
这段笔记介绍了 非降维求和 操作及 累积和 的计算方式。以下是详细总结,并结合代码进行演示:
非降维求和
保持维度求和:
- 通常情况下,
sum()
函数会降低维度。如果我们希望在求和后保持原来的维度结构,可以使用keepdims=True
参数,这样输出张量将保持与输入张量相同的维度数量。 - 例如,对矩阵
A
沿轴 1(列)进行求和并保持维度不变,这样可以方便进行后续操作,如广播。
- 通常情况下,
示例:
import torch
# 创建一个 5x4 的矩阵 A
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
print("矩阵 A:")
print(A)
# 沿轴 1 求和并保持维度不变
sum_A = A.sum(axis=1, keepdims=True)
print("沿轴 1 求和并保持维度的结果 (sum_A):")
print(sum_A)
# 通过广播将矩阵 A 除以 sum_A
A_div_sum_A = A / sum_A
print("将矩阵 A 除以 sum_A (通过广播):")
print(A_div_sum_A)
累积和
累积和:
- 累积和可以通过
cumsum()
函数实现,它沿指定轴计算每个元素的累积和,且不降低维度。 - 例如,沿轴 0(行)计算累积和。
- 累积和可以通过
示例:
# 沿轴 0 计算累积和 (按行累积)
A_cumsum = A.cumsum(axis=0)
print("矩阵 A 沿轴 0 的累积和 (cumsum):")
print(A_cumsum)
输出结果:
矩阵 A:
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.],
[16., 17., 18., 19.]])
沿轴 1 求和并保持维度的结果 (sum_A):
tensor([[ 6.],
[22.],
[38.],
[54.],
[70.]])
将矩阵 A 除以 sum_A (通过广播):
tensor([[0.0000, 0.1667, 0.3333, 0.5000],
[0.1818, 0.2273, 0.2727, 0.3182],
[0.2105, 0.2368, 0.2632, 0.2895],
[0.2222, 0.2407, 0.2593, 0.2778],
[0.2286, 0.2429, 0.2571, 0.2714]])
矩阵 A 沿轴 0 的累积和 (cumsum):
tensor([[ 0., 1., 2., 3.],
[ 4., 6., 8., 10.],
[12., 15., 18., 21.],
[24., 28., 32., 36.],
[40., 45., 50., 55.]])
解释:
- 非降维求和:沿轴 1(列)对矩阵
A
求和后,结果是一个 5x1 的矩阵,保持了原来的轴结构。通过广播机制,我们可以轻松将矩阵A
除以这个结果。 - 累积和:
A.cumsum(axis=0)
计算了沿行方向的累积和,结果中的每个元素是其当前列之前所有元素的和。
点积(Dot Product)
点积 是两个向量之间的基本运算之一,表示相同位置的元素乘积之和。数学表示为:
[
\mathbf{x} \cdot \mathbf{y} = \sum_{i} x_i y_i
]
其中 ( \mathbf{x} ) 和 ( \mathbf{y} ) 是两个向量,( x_i ) 和 ( y_i ) 是它们对应位置的元素。
代码示例:
import torch
# 创建两个向量 x 和 y
x = torch.arange(4, dtype=torch.float32)
y = torch.ones(4, dtype=torch.float32)
print("向量 x:")
print(x)
print("向量 y:")
print(y)
# 计算 x 和 y 的点积
dot_product = torch.dot(x, y)
print("x 和 y 的点积:")
print(dot_product)
输出结果:
向量 x:
tensor([0., 1., 2., 3.])
向量 y:
tensor([1., 1., 1., 1.])
x 和 y 的点积:
tensor(6.)
解释:
- 向量
x
是[0, 1, 2, 3]
,向量y
是[1, 1, 1, 1]
。 - 点积计算为:( 0 \times 1 + 1 \times 1 + 2 \times 1 + 3 \times 1 = 6 )。
点积的另一种计算方式:
点积也可以通过按元素相乘后再求和来实现:
elementwise_product_sum = torch.sum(x * y)
print("通过按元素相乘并求和计算的点积:")
print(elementwise_product_sum)
输出结果:
通过按元素相乘并求和计算的点积:
tensor(6.)
点积的实际应用:
加权和:
- 给定一个值向量 ( \mathbf{x} ) 和权重向量 ( \mathbf{w} ),点积可以表示值的加权和。加权和在许多场景中很有用,比如在机器学习中,权重表示模型的参数,值是输入数据。
[
\mathbf{x} \cdot \mathbf{w} = \sum_{i} x_i w_i
]加权平均:
- 当权重是非负数并且和为 1 时(即 ( \sum w_i = 1 )),点积表示加权平均:
[
\mathbf{x} \cdot \mathbf{w} = \text{weighted average}
]余弦相似度:
- 如果将两个向量规范化为单位向量(即长度为 1),它们的点积就是它们夹角的余弦值。这在计算两个向量的相似度时非常有用。
[
\cos(\theta) = \frac{\mathbf{x} \cdot \mathbf{y}}{|\mathbf{x}| |\mathbf{y}|}
]
矩阵-向量积
矩阵-向量积 是线性代数中一个非常基础的运算,它表示矩阵与向量相乘,得到另一个向量。设矩阵 ( \mathbf{A} ) 是一个 ( m \times n ) 矩阵,向量 ( \mathbf{x} ) 是一个长度为 ( n ) 的向量,那么矩阵-向量积 ( \mathbf{A} \mathbf{x} ) 是一个长度为 ( m ) 的向量。
矩阵-向量积的公式:
设矩阵 ( \mathbf{A} ) 的每一行表示为一个行向量 ( \mathbf{A}_i ),那么矩阵-向量积 ( \mathbf{A} \mathbf{x} ) 的第 ( i ) 个元素是矩阵第 ( i ) 行向量 ( \mathbf{A}_i ) 与向量 ( \mathbf{x} ) 的点积:
[
\mathbf{A} \mathbf{x} = \begin{bmatrix} \mathbf{A}_1 \cdot \mathbf{x} \ \mathbf{A}_2 \cdot \mathbf{x} \ \vdots \ \mathbf{A}_m \cdot \mathbf{x} \end{bmatrix}
]
也就是说,矩阵的每一行都与向量进行点积,得到的结果是一个新向量。
代码示例:
import torch
# 创建一个 3x4 的矩阵 A 和一个长度为 4 的向量 x
A = torch.arange(12, dtype=torch.float32).reshape(3, 4)
x = torch.tensor([1.0, 2.0, 3.0, 4.0])
print("矩阵 A:")
print(A)
print("向量 x:")
print(x)
# 计算矩阵 A 和向量 x 的矩阵-向量积
matrix_vector_product = torch.mv(A, x)
print("矩阵 A 和向量 x 的矩阵-向量积:")
print(matrix_vector_product)
输出结果:
矩阵 A:
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
向量 x:
tensor([1., 2., 3., 4.])
矩阵 A 和向量 x 的矩阵-向量积:
tensor([ 20., 60., 100.])
解释:
- 矩阵 ( A ) 是 ( 3 \times 4 ) 的矩阵,向量 ( x ) 是长度为 4 的向量。
- 计算矩阵-向量积时,每一行与向量 ( x ) 做点积:
- 第 1 行点积:( 0 \times 1 + 1 \times 2 + 2 \times 3 + 3 \times 4 = 20 )
- 第 2 行点积:( 4 \times 1 + 5 \times 2 + 6 \times 3 + 7 \times 4 = 60 )
- 第 3 行点积:( 8 \times 1 + 9 \times 2 + 10 \times 3 + 11 \times 4 = 100 )
- 结果是一个长度为 3 的向量:[20, 60, 100]。
矩阵-向量积的意义:
- 线性变换:矩阵-向量积可以看作是一种从向量到向量的线性变换。它可以将向量映射到另一个空间,例如在计算机图形学中,矩阵乘法可以用来表示旋转、缩放等变换。
- 神经网络:在深度学习中,矩阵-向量积用于计算神经网络层的激活输出,表示从一层到下一层的权重映射。
通过矩阵-向量积,能够有效地进行多维数据的转换与操作,特别是在多维空间中的线性变换应用。
矩阵-矩阵乘法
矩阵-矩阵乘法 是两个矩阵之间的基本运算,表示两个矩阵的行和列之间进行的点积运算。假设有两个矩阵 ( \mathbf{A} ) 和 ( \mathbf{B} ),其中 ( \mathbf{A} ) 的形状为 ( m \times n ),而 ( \mathbf{B} ) 的形状为 ( n \times p ),那么它们的乘积 ( \mathbf{C} ) 是一个形状为 ( m \times p ) 的矩阵。
矩阵乘法的每个元素 ( C_{ij} ) 是矩阵 ( \mathbf{A} ) 的第 ( i ) 行与矩阵 ( \mathbf{B} ) 的第 ( j ) 列的点积:
[
C_{ij} = \sum_{k=1}^{n} A_{ik} B_{kj}
]
代码示例:
import torch
# 创建两个矩阵 A 和 B
A = torch.arange(20, dtype=torch.float32).reshape(5, 4) # 5x4 矩阵
B = torch.ones(4, 3) # 4x3 矩阵
print("矩阵 A:")
print(A)
print("矩阵 B:")
print(B)
# 计算矩阵 A 和矩阵 B 的乘积
C = torch.mm(A, B)
print("矩阵 A 和矩阵 B 的矩阵乘积:")
print(C)
输出结果:
矩阵 A:
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.],
[16., 17., 18., 19.]])
矩阵 B:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
矩阵 A 和矩阵 B 的矩阵乘积:
tensor([[ 6., 6., 6.],
[22., 22., 22.],
[38., 38., 38.],
[54., 54., 54.],
[70., 70., 70.]])
解释:
- 矩阵 A 是一个 ( 5 \times 4 ) 的矩阵,矩阵 B 是一个 ( 4 \times 3 ) 的矩阵。
- 矩阵乘法 ( A \times B ) 结果是一个 ( 5 \times 3 ) 的矩阵。
- 例如,矩阵乘法的第一个元素 ( C_{11} ) 是矩阵 ( A ) 的第一行 ([0, 1, 2, 3]) 与矩阵 ( B ) 的第一列 ([1, 1, 1, 1]) 的点积:( 0 \times 1 + 1 \times 1 + 2 \times 1 + 3 \times 1 = 6 )。
- 类似地,计算每一行和每一列的点积得到结果矩阵 ( C )。
矩阵乘法与 Hadamard 乘积的区别:
- 矩阵乘法:是通过行与列的点积生成的新矩阵,形状取决于两个矩阵的行和列数。
- Hadamard 乘积:是按元素相乘,要求两个矩阵的形状相同,并且对应位置的元素相乘。
应用:
- 线性变换:矩阵乘法可以表示从一个空间到另一个空间的线性变换。在计算机图形学、物理学和深度学习等领域,矩阵乘法用于表示变换操作(如旋转、缩放、投影等)。
- 神经网络:在深度学习中,矩阵乘法用于计算神经网络层之间的权重映射,从上一层输入得到下一层输出。
范数(Norm)
范数 是线性代数中的一个重要概念,用于衡量向量或矩阵的“大小”。范数是一种将向量映射到标量的函数,用于表示向量的长度或大小。不同类型的范数在不同的场景下具有不同的应用,常见的范数包括 ( L_1 ) 范数、( L_2 ) 范数和 Frobenius 范数。
范数的基本性质:
- 缩放不变性:如果向量按常数因子缩放,其范数也按相同的常数因子缩放。
- 三角不等式:两个向量的范数和不小于它们的和的范数。
- 非负性:范数始终是非负的,且最小值为 0。
- 零向量的范数为 0:只有向量全由零组成时,范数为 0。
常见的向量范数:
( L_2 ) 范数(欧几里得范数):
定义为向量元素的平方和的平方根。它表示向量的欧几里得距离。
公式为:
[
| \mathbf{u} |2 = \sqrt{\sum{i} u_i^2}
]代码示例:
import torch u = torch.tensor([3.0, -4.0]) l2_norm = torch.norm(u) print("向量 u 的 L2 范数:", l2_norm)
输出结果:
向量 u 的 L2 范数: tensor(5.)
( L_1 ) 范数:
定义为向量元素的绝对值之和。它比 ( L_2 ) 范数更不容易受到异常值的影响。
公式为:
[
| \mathbf{u} |1 = \sum{i} |u_i|
]代码示例:
l1_norm = torch.abs(u).sum() print("向量 u 的 L1 范数:", l1_norm)
输出结果:
向量 u 的 L1 范数: tensor(7.)
( L_p ) 范数:
- 是 ( L_1 ) 和 ( L_2 ) 范数的推广,定义为:
[
| \mathbf{u} |p = \left( \sum{i} |u_i|^p \right)^{1/p}
] - 当 ( p = 1 ) 时为 ( L_1 ) 范数,当 ( p = 2 ) 时为 ( L_2 ) 范数。
- 是 ( L_1 ) 和 ( L_2 ) 范数的推广,定义为:
矩阵的 Frobenius 范数:
类似于向量的 ( L_2 ) 范数,Frobenius 范数 是矩阵元素平方和的平方根。
公式为:
[
| \mathbf{A} |F = \sqrt{\sum{i,j} A_{ij}^2}
]Frobenius 范数可以看作是将矩阵视为向量后的 ( L_2 ) 范数。
代码示例:
A = torch.ones((4, 9)) frobenius_norm = torch.norm(A) print("矩阵 A 的 Frobenius 范数:", frobenius_norm)
输出结果:
矩阵 A 的 Frobenius 范数: tensor(6.)
范数的应用:
在深度学习中,范数有广泛的应用,尤其在优化问题中。我们经常需要最小化损失函数,而损失函数可以用范数来衡量预测值与真实值之间的误差。常见的应用场景包括:
- 最大化分配给观测数据的概率。
- 最小化预测值和真实观测值之间的距离,例如回归问题中使用 ( L_2 ) 范数计算误差。
- 加权向量的表示:如在词嵌入或推荐系统中,使用范数来最小化相似项之间的距离,最大化不同项之间的距离。
通过理解范数的基本性质和计算方式,可以在各种机器学习和深度学习任务中更好地评估和优化模型。