原文链接:为什么线代在人工智能中被广泛应用?
大家好,我是泰哥。在机器学习建模过程中,经常会使用矩阵运算以提升效率,在深度学习中,往往会涉及矩阵的集合运算,就是三维或四维数据的计算。
它们的基础就是线性代数理论,而线代基础的核心又是矩阵,矩阵的本质其实是线性方程!是不是很神奇?本文首先介绍矩阵的构造,然后详解矩阵的运算与本质意义。
一、矩阵形变的构造
矩阵的形变与构造的方法与二维张量的方法相同。
t1 = torch.arange(6).reshape(2, 3).float()
t1
1.1 t :转置
torch.t(t1)
# tensor([[0., 3.],
# [1., 4.],
# [2., 5.]])
矩阵的转置是每个元素行列位置进行互换。
1.2 eye :单位矩阵
torch.eye(3)
# tensor([[1., 0., 0.],
# [0., 1., 0.],
# [0., 0., 1.]])
1.3 diag :对角矩阵
注意参数的数据类型必须是张量。
t = torch.arange(1, 4)
t
# tensor([1, 2, 3])
torch.diag(t)
# tensor([[1, 0, 0],
# [0, 2, 0],
# [0, 0, 3]])
torch.diag(t, 1)
# tensor([[0, 1, 0, 0],
# [0, 0, 2, 0],
# [0, 0, 0, 3],
# [0, 0, 0, 0]])
torch.diag(t, -1)
# tensor([[0, 0, 0, 0],
# [1, 0, 0, 0],
# [0, 2, 0, 0],
# [0, 0, 3, 0]])
1.4 triu :取上三角矩阵
t2 = torch.arange(1, 10).reshape(3, 3)
t2
# tensor([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
torch.triu(t2)
# tensor([[1, 2, 3],
# [0, 5, 6],
# [0, 0, 9]])
torch.triu(t2, -1)
# tensor([[1, 2, 3],
# [4, 5, 6],
# [0, 8, 9]])
1.5 tril :取下三角矩阵
torch.tril(t2)
# tensor([[1, 0, 0],
# [4, 5, 0],
# [7, 8, 9]])
二、矩阵的基本运算与意义
矩阵的线性代数含义主要体现在它的基本运算上。
2.1 dot\vdot :点积计算
在PyTorch 中,dot 和vdot 只能用于一维张量。两种函数只在进行复数运算时有区别。
t = torch.arange(1, 4)
t
# tensor([1, 2, 3])
torch.dot(t, t)
# tensor(14)
torch.vdot(t, t)
# tensor(14)
2.2 mm :矩阵乘法
t1 = torch.arange(1, 7).reshape(2, 3)
t1
# tensor([[1, 2, 3],
# [4, 5, 6]])
t2 = torch.arange(1, 10).reshape(3, 3)
t2
# tensor([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
矩阵对应位置元素相乘,要求两个矩阵的形状相同。
t1 * t1
# tensor([[ 1, 4, 9],
# [16, 25, 36]])
而矩阵乘法两个矩阵的形状可以不同。
torch.mm(t1, t2)
# tensor([[ 1, 4, 9],
# [16, 25, 36]])
计算过程如下所示:
规律总结如下:
- 左边矩阵的列数要和右边矩阵的行数相等,左边矩阵每行与右边矩阵每列对应位置元素相乘后相加
- 左边矩阵的行数决定了结果矩阵的行数,右边矩阵的列数决定了结果矩阵的列数
矩阵相乘需要注意:
A = torch.tensor([1, 1, -1, -1])..reshape(2, 2)
A
# tensor([[ 1, 1],
# [-1, -1]])
B = torch.tensor([1, -1, -1, 1]).reshape(2, 2)
B
# tensor([[ 1, -1],
# [-1, 1]])
torch.mm(A, B)
# tensor([[0, 0],
# [0, 0]])
torch.mm(B, A)
# tensor([[ 2, 2],
# [-2, -2]])
- 不满足消去律:
A
B
=
A
C
,
A
≠
O
,
但
B
≠
C
AB = AC, A\ne O, 但B \ne C
AB=AC,A?=O,但B?=C
C = torch.tensor([0, 0, 0, 0]).reshape(2, 2)
C
# tensor([[0, 0],
# [0, 0]])
torch.mm(A, B)
# tensor([[0, 0],
# [0, 0]])
torch.mm(A, C)
# tensor([[0, 0],
# [0, 0]])
2.3 mv :矩阵与向量相乘
矩阵和向量相乘的过程中,需要矩阵的列数和向量的元素个数相同。
m = torch.arange(1, 7).reshape(2, 3)
m
# tensor([[1, 2, 3],
# [4, 5, 6]])
v = torch.arange(1, 4)
v
# tensor([1, 2, 3])
torch.mv(m, v)
# tensor([14, 32])
矩阵和向量相乘的过程我们可以看成是先将向量转化为列向量然后再相乘。
# 转化为列向量
v.reshape(3, 1)
# tensor([[1],
# [2],
# [3]])
torch.mm(m, v.reshape(3, 1))
# tensor([[14],
# [32]])
torch.mm(m, v.reshape(3, 1)).flatten()
# tensor([14, 32])
2.4 矩阵的本质是线性方程
mv 函数本质上提供了一种二维张量和一维张量相乘的方法,在线性代数运算过程中,有很多矩阵乘向量的场景,典型的如线性回归的求解过程。
{
2
x
+
y
=
3
4
x
+
y
=
7
\begin{cases} 2x + y = 3 \\ 4x + y = 7 \end{cases}
{2x+y=34x+y=7? 矩阵的最初目的,只是为线性方程组提供一个简写形式。
(
2
1
4
3
)
(
x
y
)
=
(
3
7
)
\begin{pmatrix}2 & 1 \\ 4 & 3\\ \end{pmatrix} \begin{pmatrix}x \\ y \end{pmatrix}= \begin{pmatrix}3 \\ 7 \end{pmatrix}
(24?13?)(xy?)=(37?)
通常情况下我们需要将行向量(x,y) 转化为列向量然后进行计算,但PyTorch 中单独设置了一个矩阵和向量相乘的方法,从而简化了将向量转化为列向量的转化过程。
2.5 bmm :批量矩阵相乘
批量矩阵相乘指的是三维张量的矩阵乘法,本质是三维张量内部各对应位置的矩阵相乘,在深度学习中有非常多的应用场景。
t3 = torch.arange(1, 13).reshape(3, 2, 2)
t3
# tensor([[[ 1, 2],
# [ 3, 4]],
# [[ 5, 6],
# [ 7, 8]],
# [[ 9, 10],
# [11, 12]]])
t4 = torch.arange(1, 19).reshape(3, 2, 3)
t4
# tensor([[[ 1, 2, 3],
# [ 4, 5, 6]],
# [[ 7, 8, 9],
# [10, 11, 12]],
# [[13, 14, 15],
# [16, 17, 18]]])
torch.bmm(t3, t4)
# tensor([[[ 9, 12, 15],
# [ 19, 26, 33]],
# [[ 95, 106, 117],
# [129, 144, 159]],
# [[277, 296, 315],
# [335, 358, 381]]])
需要注意:
- 三维张量包含的矩阵个数需要相同
- 每个内部矩阵,需要满足左乘矩阵的列数要等于右乘矩阵的行数
2.6 addmm :矩阵相乘后相加
-
addmm函数结构:addmm(input, mat1, mat2, beta=1, alpha=1) -
输出结果:beta * input + alpha * (mat1 * mat2) -
相当于y = ax + b 中加偏置的过程,就是线性方程或基本的神经元
t1
# tensor([[1, 2, 3],
# [4, 5, 6]])
t2
# tensor([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
t = torch.arange(3)
t
# tensor([0, 1, 2]
# 矩阵乘法
torch.mm(t1, t2)
# tensor([[30, 36, 42],
# [66, 81, 96]])
# 先乘法后相加
torch.addmm(t, t1, t2)
# tensor([[30, 37, 44],
# [66, 82, 98]])
torch.addmm(t, t1, t2, beta = 0, alpha = 10)
# tensor([[300, 360, 420],
# [660, 810, 960]])
2.7 addbmm :批量矩阵相乘后相加
不同的是addbmm 是批量矩阵相乘,并且在相加的过程中也是矩阵相加,而非向量加矩阵。
t = torch.arange(6).reshape(2, 3)
t
# tensor([[0, 1, 2],
# [3, 4, 5]])
t3
# tensor([[[ 1, 2],
# [ 3, 4]],
# [[ 5, 6],
# [ 7, 8]],
# [[ 9, 10],
# [11, 12]]])
t4
# tensor([[[ 1, 2, 3],
# [ 4, 5, 6]],
# [[ 7, 8, 9],
# [10, 11, 12]],
# [[13, 14, 15],
# [16, 17, 18]]])
torch.bmm(t3, t4)
# tensor([[[ 9, 12, 15],
# [ 19, 26, 33]],
# [[ 95, 106, 117],
# [129, 144, 159]],
# [[277, 296, 315],
# [335, 358, 381]]])
torch.addbmm(t, t3, t4)
# tensor([[381, 415, 449],
# [486, 532, 578]])
addbmm 会在原来三维张量基础之上,对其内部矩阵进行求和,而不是矩阵和向量相加。
原文链接:为什么线代在人工智能中被广泛应用?
|