【李沐-动手深度学习v2】笔记整理-05线性代数

标量、向量、矩阵

矩阵把空间进行扭曲
矩阵的范数:F范数:所有元素的平方加和再开根号
特征向量:不被矩阵改变方向的向量

向量是标量的推广,矩阵是向量的推广,张量(多维)是矩阵的推广

线性代数的实现

import torch

# 标量由只有一个元素的张量表示
x = torch.tensor([3.0])

# 向量:由标量值组成的列表
x = torch.arange(4)
print(x)      # tensor([0, 1, 2, 3])
# 通过张量的索引访问任一元素
print(x[3])   # tensor(3)

# 访问张量的长度
print(len(x))    # 4

# 张量的形状,只有一个轴的张量,形状只有一个元素
print(x.shape)   # torch.Size([4])

# 创建一个形状为(2,3)的矩阵,并将其转置
A = torch.arange(6).reshape((2,3))
print(A.T)

# 对称矩阵等于其转置后的矩阵
B = torch.tensor([[1,2,3],[2,0,4],[3,4,5]])
print(B == B.T)
# tensor([[True, True, True],
#         [True, True, True],
#         [True, True, True]])

# 创建更多轴的数据结构
X = torch.arange(24).reshape((2,3,4))
print(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]]])  在一个三维张量中,有2个二维矩阵,每个二维矩阵中有3个向量,每个向量有4个标量

# 矩阵相加
A = torch.arange(20,dtype=torch.float32).reshape(5,4)
B = A.clone()  # 通过分配新内存,将A的一个副本分配给B

# 两个矩阵按元素相乘,称为哈达玛积
print(A * B)
# tensor([[  0.,   1.,   4.,   9.],
#         [ 16.,  25.,  36.,  49.],
#         [ 64.,  81., 100., 121.],
#         [144., 169., 196., 225.],
#         [256., 289., 324., 361.]])

# 标量与矩阵的运算,即为与矩阵中每个元素的运算,形状不变
a = 2
X = torch.arange(24).reshape(2,3,4)
print(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]]])
print(a+X,(a+X).shape)
# 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]]]) torch.Size([2, 3, 4])
print(a*X,(a*X).shape)
# tensor([[[ 0,  2,  4,  6],
#          [ 8, 10, 12, 14],
#          [16, 18, 20, 22]],
#
#         [[24, 26, 28, 30],
#          [32, 34, 36, 38],
#          [40, 42, 44, 46]]]) torch.Size([2, 3, 4])

# 矩阵求和:按指定张量维度求和
# 按哪个维度求和,哪个维度消失 把哪个维度压扁
A = torch.arange(24).reshape(2,3,4)
print(A)
# 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]]])
print(A.sum(axis=0),A.sum(axis=0).shape)
# tensor([[12, 14, 16, 18],
#         [20, 22, 24, 26],
#         [28, 30, 32, 34]])  torch.Size([3, 4])
print(A.sum(axis=1),A.sum(axis=1).shape)
# tensor([[12, 15, 18, 21],
#         [48, 51, 54, 57]]) torch.Size([2, 4])
print(A.sum(axis=2),A.sum(axis=2).shape)
# tensor([[ 6, 22, 38],
#         [54, 70, 86]]) torch.Size([2, 3])
print(A.sum(axis=[0,1]),A.sum(axis=[0,1]).shape)  # 按两个维度求和
# tensor([60, 66, 72, 78]) torch.Size([4])

# 平均值mean   mean()要求矩阵是浮点型
A = torch.arange(12,dtype=torch.float32).reshape(3,4)
print(A)
# tensor([[ 0.,  1.,  2.,  3.],
#         [ 4.,  5.,  6.,  7.],
#         [ 8.,  9., 10., 11.]])
print(A.mean())            # tensor(5.5000)
print(A.sum()/A.numel())   # tensor(5.5000)
print(A.mean(axis=0))              # tensor([4., 5., 6., 7.])
print(A.sum(axis=0)/A.shape[0])    # tensor([4., 5., 6., 7.])

# 计算总和或均值是保持轴数不变,即不要丢掉维数,将求和维度的值变为1
sum_A = A.sum(axis=0,keepdims=True)
print(sum_A,sum_A.shape)    # tensor([[12., 15., 18., 21.]]) torch.Size([1, 4])
# 这样就可以保证A与sum_A的维度一致,可以通过广播机制进行计算
print(A/sum_A)

# 某个轴计算A元素的累计求和
print(A.cumsum(axis=0))
# tensor([[ 0.,  1.,  2.,  3.],
#         [ 4.,  6.,  8., 10.],
#         [12., 15., 18., 21.]])

# 点积:相同位置的按元素乘积的和 (向量-向量)
x = torch.arange(4,dtype=torch.float32)
y = torch.ones(4,dtype=torch.float32)
print(torch.dot(x,y))  # tensor(6.)
print(torch.sum(x*y))  # tensor(6.) 也可以通过执行按元素乘法,再求和表示

# 矩阵-向量积
print(A.shape)  # torch.Size([3, 4])
print(x.shape)  # torch.Size([4])
print(torch.mv(A,x),torch.mv(A,x).shape)  # tensor([14., 38., 62.]) torch.Size([3])

# 矩阵-矩阵乘法
B = torch.ones(2,3)
print(A.shape)   # torch.Size([3, 4])
print(B.shape)   # torch.Size([2, 3])
print(torch.mm(B,A),torch.mm(B,A).shape)
# tensor([[12., 15., 18., 21.],
#         [12., 15., 18., 21.]]) torch.Size([2, 4])

# L2范数是向量元素平方和的平方根
u = torch.tensor([3.0,-4.0])
print(torch.norm(u))  # tensor(5.)

# L1范数是向量元素的绝对值之和
print(torch.abs(u).sum())  # tensor(7.)

# 矩阵的范数:是矩阵元素的平方和的平方根
print(torch.norm(torch.ones((4,9)))) # tensor(6.)

QA互动

Q1:torch不区分行向量和列向量吗?

向量就是一维的,在计算机里是一维数组,没有行列之分。要想区分行列向量,就要按矩阵来看。

猜你喜欢

转载自blog.csdn.net/m0_51141265/article/details/128962734