线性代数与向量
标量与向量
如何衡量一个人的健康程度?
在医学上,我们可以根据一个人的 身高、体重、年龄 来大致推算其健康程度。如果转换成数学语言的话,我们可以考虑写出这样一个公式,其中 x 表示身高, y 表示体重, z 表示年龄:(x+y)/z ,公式的计算结果表示一个人的健康程度。
公式中的 x 、 y 、 z 可以是任何数字,我们将其称之为 标量 ,多个标量组合在一起,产生了一个新的含义(一个人的健康程度),我们将这个组合称为 向量 。
在代码中,我们可以使用一维数组来表示一个向量:
python
import torch
x=torch.tensor([0,1,2,3])
print(x)
# tensor([0, 1, 2, 3])
一个只有一个元素的一维数组,可以表示一个标量:
python
import torch
x=torch.tensor([1])
print(x)
# tensor([1])
矩阵
在使用数据的过程中,我们不可能只用一组数据(一个向量),例如医院必须要很多人的身体数据才能衡量出整体的健康指标。
当我们将多个向量 组合在一起时,就形成了一个二维数组,称之为矩阵:
python
import torch
x=torch.arange(12).reshape(3,-1)
print(x)
# tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
如果我们将矩阵中的元素沿着斜对称轴互换的话(也就是将XijX_{ij}Xij变成 XjiX_{ji}Xji),就可以得到数组的转置 (数学表示为XTX^TXT):
python
import torch
x=torch.arange(12).reshape(3,-1)
print(x)
# tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
y=x.T
print(y)
# tensor([[ 0, 4, 8],
# [ 1, 5, 9],
# [ 2, 6, 10],
# [ 3, 7, 11]])
如果X=XTX=X^TX=XT,我们称其为对称矩阵:
python
import torch
x=torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
print(x)
# tensor([[1, 2, 3],
# [2, 0, 4],
# [3, 4, 5]])
y=x.T
print(y)
# tensor([[1, 2, 3],
# [2, 0, 4],
# [3, 4, 5]])
print(x==y)
# tensor([[True, True, True],
# [True, True, True],
# [True, True, True]])
当我们对一个矩阵(二维数组)或者更高维数组进行求和时,可以单独对某一维进行求和:
python
import torch
x=torch.ones(3,4)
print(x)
# tensor([[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]])
print(x.sum())
# tensor(12.)
print(x.sum(axis=0))
# tensor([3., 3., 3., 3.])
print(x.sum(axis=1))
# tensor([4., 4., 4.])
axis=0 表示对第0维进行求和,对于一个矩阵(二维数组)来说,也就是将矩阵的高进行压缩,变成了一个一维数组(向量)。
同理,我们对一个矩阵(二维数组)或者更高维数组进行求平均值时,可以单独对某一维进行求平均值:
python
import torch
x=torch.arange(12,dtype=float).reshape(3,-1)
print(x)
# tensor([[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]])
print(x.mean())
# tensor(12.)
print(x.mean(axis=0))
# tensor([3., 3., 3., 3.])
不过,在某些操作中,我们可能不想降低数组的维度:
python
import torch
x=torch.ones(3,4)
print(x)
# tensor([[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]])
print(x.sum())
# tensor(12.)
# 得到的依旧是一个二维数组,只不过第1维的数组长度为0
print(x.sum(axis=0,keepdim=True))
# tensor([[3., 3., 3., 3.]])
此外,还有个函数 cumsum 可以在某个维度上进行累计求和:
python
import torch
x=torch.ones(3,4)
print(x)
# tensor([[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]])
print(x.sum())
# tensor(12.)
print(x.cumsum(axis=1))
# tensor([[1., 2., 3., 4.],
# [1., 2., 3., 4.],
# [1., 2., 3., 4.]])
向量点积
对于两个相同形状的向量 ,将对应位置元素相乘,然后取和,可以得到这两个向量的点积 (数学表示为XTYX^TYXTY 或者 <X,Y><X,Y><X,Y>):
python
import torch
x=torch.tensor([1,1,1])
y=torch.tensor([2,2,2])
print(torch.dot(x,y))
# tensor(6)
矩阵-向量积
矩阵-向量积 可以理解为向量点积 的扩展,将向量与矩阵的每行向量进行点积 ,再将每个结果组合成一个向量,就得到了矩阵-向量积:
python
import torch
x=torch.tensor([[1,1,1],[1,1,1],[1,1,1]])
y=torch.tensor([2,2,2])
# 用函数 mv 来得到矩阵-向量积
print(torch.mv(x,y))
# tensor([6, 6, 6])
for i in range(len(x)):
print(torch.dot(y,x[i]))
# tensor(6)
# tensor(6)
# tensor(6)
矩阵乘法
矩阵乘法 也可以理解为向量点积 的扩展,只需将一个矩阵的第i行,与另一个矩阵的第j列进行向量点积,就可以得到结果矩阵的第i行j列的元素:
python
import torch
x=torch.tensor([[1,1,1],[1,1,1],[1,1,1]])
y=torch.tensor([[2,2,2],[2,2,2],[2,2,2]])
# 用函数 mm 来得到矩阵乘法的结果
print(torch.mm(x,y))
# tensor([[6, 6, 6],
# [6, 6, 6],
# [6, 6, 6]])
范数
我们将一个向量 的大小称为向量的范数。
范数有多种计算方式。L2L_2L2范数的计算方式是将向量中所有元素的平方求和,然后求平方根:∥x∥2=∑i=1nxi2\|\mathbf{x}\|2 = \sqrt{\sum{i=1}^n x_i^2}∥x∥2=∑i=1nxi2 ,在PyTorch中可以通过 norm 函数获得:
python
import torch
x=torch.tensor([3.0,-4.0])
print(x.norm())
# tensor(5.)
L1L_1L1范数的计算方式是将向量中的所有元素的绝对值求和: ∥x∥1=∑i=1n∣xi∣\|\mathbf{x}\|1 = \sum{i=1}^n \left|x_i \right|∥x∥1=∑i=1n∣xi∣,在PyTorch中可以通过这种方式获得:
python
import torch
x=torch.tensor([3.0,-4.0])
print(torch.abs(x).sum())
# tensor(7.)
范数 的意义在于,我们可以衡量两个向量之间的差距:
python
import torch
x=torch.tensor([2.,3.,2.])
y=torch.tensor([1.,1.,1.])
print(x.norm())
# tensor(4.1231)
print(y.norm())
# tensor(1.7321)
print((x-y).norm())
# tensor(2.4495)