【鼠鼠学AI代码合集#5】线性代数

发布于:2024-09-18 ⋅ 阅读:(35) ⋅ 点赞:(0)

在前面的例子中,我们已经讨论了标量的概念,并展示了如何使用代码对标量进行基本的算术运算。接下来,我将进一步说明该过程,并解释每一步的实现。

标量(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.0
  • x * y:标量的乘法,3.0 * 2.0 = 6.0
  • x / y:标量的除法,3.0 / 2.0 = 1.5
  • x**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 列的数据。这展示了张量的基本结构,未来可以进一步扩展到更复杂的多维数据,例如处理图像时的三维张量。

张量的基本性质

  1. 按元素操作

    • 对张量执行的按元素操作不会改变张量的形状。无论是一元运算还是二元运算,结果张量的形状和操作数保持一致。
    • 例如,将两个相同形状的张量相加或相乘,结果仍是相同形状的张量。
  2. Hadamard积

    • 两个矩阵的按元素乘法称为 Hadamard 积。其结果是对应元素相乘的矩阵。
  3. 张量与标量运算

    • 张量与标量相加或相乘不会改变张量的形状,运算结果是对每个元素进行相同的操作。
代码示例
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])
解释:
  1. A + B:矩阵 AB 的按元素相加,结果是同样形状的矩阵,每个元素是对应位置的元素相加。
  2. A * B:这是矩阵 AB 的 Hadamard 积,每个元素是对应位置的元素相乘。
  3. a + X:标量 a 与张量 X 的相加操作,对 X 的每个元素都加上标量 a,形状不变。
  4. a * X:标量 a 与张量 X 的乘法,对 X 的每个元素乘以 a,并且结果张量的形状依然保持不变。

这段笔记讲述了张量的降维操作,特别是通过求和与平均值计算来降低张量的维度。下面是详细总结并结合代码示例:

张量降维

  1. 求和操作

    • 对张量的所有元素进行求和,称为降维。默认情况下,求和操作会沿所有轴进行,使张量的维度降为标量。
    • 通过指定轴(axis),可以选择沿哪个轴进行求和,从而降低维度。
  2. 示例

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)
  1. 平均值计算

    • 平均值是通过将张量的元素和除以元素总数来计算的。
    • 和求和操作一样,平均值计算也可以指定轴来降低维度。
  2. 平均值计算示例

# 计算矩阵 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)
解释:
  1. 向量求和:计算向量 x 的所有元素和,结果为 6
  2. 矩阵求和:矩阵 A 的所有元素求和结果为 190。可以指定轴来对行或列进行求和,得到相应的降维结果。
  3. 平均值:计算矩阵 A 的平均值,通过 mean() 函数或手动求和除以元素总数得到结果。
    这段笔记介绍了 非降维求和 操作及 累积和 的计算方式。以下是详细总结,并结合代码进行演示:

非降维求和

  1. 保持维度求和

    • 通常情况下,sum() 函数会降低维度。如果我们希望在求和后保持原来的维度结构,可以使用 keepdims=True 参数,这样输出张量将保持与输入张量相同的维度数量。
    • 例如,对矩阵 A 沿轴 1(列)进行求和并保持维度不变,这样可以方便进行后续操作,如广播。
  2. 示例

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)
累积和
  1. 累积和

    • 累积和可以通过 cumsum() 函数实现,它沿指定轴计算每个元素的累积和,且不降低维度。
    • 例如,沿轴 0(行)计算累积和。
  2. 示例

# 沿轴 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. 非降维求和:沿轴 1(列)对矩阵 A 求和后,结果是一个 5x1 的矩阵,保持了原来的轴结构。通过广播机制,我们可以轻松将矩阵 A 除以这个结果。
  2. 累积和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.)
点积的实际应用:
  1. 加权和

    • 给定一个值向量 ( \mathbf{x} ) 和权重向量 ( \mathbf{w} ),点积可以表示值的加权和。加权和在许多场景中很有用,比如在机器学习中,权重表示模型的参数,值是输入数据。

    [
    \mathbf{x} \cdot \mathbf{w} = \sum_{i} x_i w_i
    ]

  2. 加权平均

    • 当权重是非负数并且和为 1 时(即 ( \sum w_i = 1 )),点积表示加权平均:

    [
    \mathbf{x} \cdot \mathbf{w} = \text{weighted average}
    ]

  3. 余弦相似度

    • 如果将两个向量规范化为单位向量(即长度为 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 范数。

范数的基本性质:
  1. 缩放不变性:如果向量按常数因子缩放,其范数也按相同的常数因子缩放。
  2. 三角不等式:两个向量的范数和不小于它们的和的范数。
  3. 非负性:范数始终是非负的,且最小值为 0。
  4. 零向量的范数为 0:只有向量全由零组成时,范数为 0。
常见的向量范数:
  1. ( 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.)
      
  2. ( 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.)
      
  3. ( 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 ) 范数。
矩阵的 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.)
    
范数的应用:

在深度学习中,范数有广泛的应用,尤其在优化问题中。我们经常需要最小化损失函数,而损失函数可以用范数来衡量预测值与真实值之间的误差。常见的应用场景包括:

  1. 最大化分配给观测数据的概率
  2. 最小化预测值和真实观测值之间的距离,例如回归问题中使用 ( L_2 ) 范数计算误差。
  3. 加权向量的表示:如在词嵌入或推荐系统中,使用范数来最小化相似项之间的距离,最大化不同项之间的距离。

通过理解范数的基本性质和计算方式,可以在各种机器学习和深度学习任务中更好地评估和优化模型。