李沐动手学深度学习:05 线性代数(矩阵、张量、范数)

一、相关资料连接

  1. 链接: 哔哩哔哩李沐课程
  2. 链接: 课程代码及PPT

二、代码及笔记(使用Jupyter Notebook)

(矩阵、张量、范数)

1. 矩阵乘法其实是空间扭曲,标量由只有一个元素的张量显示

import torch

x = torch.tensor([3.0])
y = torch.tensor([2.0])

x + y, x * y, x / y, x**y

3. 你可以将向量视为标量值组成的列表

x = torch.arange(4)
x


tensor([0, 1, 2, 3])  # 运行结果

4. 通过张量的索引来访问任一元素

x[3]


tensor(3)   # 运行结果

5. 访问张量的长度

len(x)


4   # 运行结果

6. 只有一个轴的张量,形状只有一个元素

x.shape


torch.Size([4])   # 运行结果

7. 通过指定两个分量m和 n来创建一个形状为m×n的矩阵

A = torch.arange(20).reshape(5,4)
A



tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11],
        [12, 13, 14, 15],
        [16, 17, 18, 19]])   # 运行结果

8. 矩阵的转置

A.T


tensor([[ 0,  4,  8, 12, 16],
        [ 1,  5,  9, 13, 17],
        [ 2,  6, 10, 14, 18],
        [ 3,  7, 11, 15, 19]])   # 运行结果

9. 对称矩阵(symmetric matrix)A等于其转置:A=A^T

B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
B


tensor([[1, 2, 3],
        [2, 0, 4],
        [3, 4, 5]])    # 运行结果
B == B.T   


tensor([[True, True, True],
        [True, True, True],
        [True, True, True]])    # 运行结果

10. 就像向量是标量的推广,矩阵是向量的推广一样,我们可以构建具有更多轴的数据结构。(2,3,4)表示一共两个矩阵,每个矩阵是3行4列,可以以此类推,比如(2345),就是2个三维张量,每个三维张量是3个矩阵,每个矩阵是4行5列

X = torch.arange(24).reshape(2, 3, 4)
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]]])    # 运行结果

11. 给定具有相同形状的任意两个张量,任何按元素二元运算的结果都将是相同形状的张量

A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
B = A.clone()
A, A + B   




(tensor([[ 0.,  1.,  2.,  3.],
         [ 4.,  5.,  6.,  7.],
         [ 8.,  9., 10., 11.],
         [12., 13., 14., 15.],
         [16., 17., 18., 19.]]),
 tensor([[ 0.,  2.,  4.,  6.],
         [ 8., 10., 12., 14.],
         [16., 18., 20., 22.],
         [24., 26., 28., 30.],
         [32., 34., 36., 38.]]))    # 运行结果

# AA+B的shape是一样的

12. 两个矩阵的按元素乘法称为哈达玛积(Hadamard product)(数学符号⊙)

A*B


tensor([[  0.,   1.,   4.,   9.],
        [ 16.,  25.,  36.,  49.],
        [ 64.,  81., 100., 121.],
        [144., 169., 196., 225.],
        [256., 289., 324., 361.]])    # 运行结果

13. a+X:是把X中的每一个数都加上a,a* X是把X中的每一个数都乘上a

a = 2
X = torch.arange(24).reshape(2, 3, 4)
X , a + X , (a * X).shape



(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]]]),
 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]))               # 运行结果                  

14. 计算其元素的和,不管x是什么样子的形状,他的sum永远都是一个标量

x = torch.arange(4, dtype=torch.float32)
x, x.sum()


(tensor([0., 1., 2., 3.]), tensor(6.))  # 运行结果

15. 表示任意形状张量的元素和

A = torch.arange(20).reshape(5,4)
A.shape, A.sum()



(torch.Size([5, 4]), tensor(190))    # 运行结果
A = torch.arange(20*2).reshape(2,5,4)
A,A.shape, A.sum()



(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],
          [24, 25, 26, 27],
          [28, 29, 30, 31],
          [32, 33, 34, 35],
          [36, 37, 38, 39]]]),
 torch.Size([2, 5, 4]),
 tensor(780))                       # 运行结果

16. 指定张量沿哪一个轴来通过求和降低维度

A_sum_axis0 = A.sum(axis=0)
A,A_sum_axis0, A_sum_axis0.shape


(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],
          [24, 25, 26, 27],
          [28, 29, 30, 31],
          [32, 33, 34, 35],
          [36, 37, 38, 39]]]),
 tensor([[20, 22, 24, 26],
         [28, 30, 32, 34],
         [36, 38, 40, 42],
         [44, 46, 48, 50],
         [52, 54, 56, 58]]),
 torch.Size([5, 4]))                   # 运行结果
A_sum_axis1 = A.sum(axis=1)
A_sum_axis1, A_sum_axis1.shape



(tensor([[ 40,  45,  50,  55],
         [140, 145, 150, 155]]),
 torch.Size([2, 4]))                   # 运行结果
A_sum_axis2 = A.sum(axis=2)
A_sum_axis2, A_sum_axis2.shape



(tensor([[  6,  22,  38,  54,  70],
         [ 86, 102, 118, 134, 150]]),
 torch.Size([2, 5]))                     # 运行结果

解释:A的shape是(2,5,4),axis0是对(2,5,4)中的2维度求和,axis1是对5的维度(按行求和),axis2是对4的维度(按列)求和。对某个维度求和时,保留其他的维度,保留的是哪些维度,则shape就是多少。eg: 一、 axis = 0,则按照2维度(2表示两个矩阵的对应位置相加求和),留下的是(5,4)则其结果的shape就是(5,4),即为5行4列的矩阵 二、 axis = 1,则按照5维度(5表示一个矩阵中有5行,则在行这个维度上相加求和,即纵向相加求和,40=0+4+8+12+16,45=1+5+9+13+17,等等),留下的是(2,4),则shape为(2,4)即2个矩阵,一个矩阵为4列 三、 axis = 2,则按照4维度(4表示一个矩阵中有4列,则在列这个维度上相加求和,即横向相加求和,6=0+1+2+3,22=4+5+6+7,等等),留下的是(2,5),则shape为(2,5)即2个矩阵,一个矩阵有5列

17. 按照两个维度求和
axis=[0,1],即按照2和5的维度求和,
180 = 0+4+8+12+16+20+24+28+32+36,
190 = 1+5+9+13+17+21+25+29+33+37。
剩下了4维度,则shape为4列

A,A.sum(axis=[0, 1])


(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],
          [24, 25, 26, 27],
          [28, 29, 30, 31],
          [32, 33, 34, 35],
          [36, 37, 38, 39]]]),
 tensor([180, 190, 200, 210]))         # 运行结果  
A.sum(axis=[0, 1]).shape

torch.Size([4])        # 运行结果

18. 一个与求和相关的量是平均值(mean或average)

A =torch.arange(20,dtype=torch.float32).reshape(5,4)
A,A.mean(), A.sum() / A.numel()




(tensor([[ 0.,  1.,  2.,  3.],
         [ 4.,  5.,  6.,  7.],
         [ 8.,  9., 10., 11.],
         [12., 13., 14., 15.],
         [16., 17., 18., 19.]]),
 tensor(9.5000),
 tensor(9.5000))                       # 运行结果

注意:没有定义浮点类型的时候运行报错,是因为均值是除法运算,会产生浮点数,因此被除数要为浮点数类型才能求出准确值

A.mean(axis=0), A.sum(axis=0) / A.shape[0]


(tensor([ 8.,  9., 10., 11.]), tensor([ 8.,  9., 10., 11.]))   # 运行结果

axis=0:表示纵向,(0+4+8+12+16)/5 = 8,(1+5+9+13+17)/5 = 9 等等,某一个维度算均值等价于,某一个维度求和在除以维度的形状是一样的

20. 计算总和或均值时保持轴数不变

sum_A = A.sum(axis=1, keepdims=True)
A,sum_A



(tensor([[ 0.,  1.,  2.,  3.],
         [ 4.,  5.,  6.,  7.],
         [ 8.,  9., 10., 11.],
         [12., 13., 14., 15.],
         [16., 17., 18., 19.]]),
 tensor([[ 6.],
         [22.],
         [38.],
         [54.],
         [70.]]))                    # 运行结果
sum_A = A.sum(axis=1, keepdims=False)
A,sum_A



(tensor([[ 0.,  1.,  2.,  3.],
         [ 4.,  5.,  6.,  7.],
         [ 8.,  9., 10., 11.],
         [12., 13., 14., 15.],
         [16., 17., 18., 19.]]),
 tensor([ 6., 22., 38., 54., 70.]))   # 运行结果

解释:我们想在按照某一个维度求和的时候,不想吧这个维度丢掉若按照维度为1的维度求和则1维度就丢掉了。若是3维矩阵按照一个维度求和会变成一个2维的矩阵,如果是一个2维的矩阵按照一个维度求和则会变成一个一维的向量。当 keepidms=True,保持其二维或者三维的特性,(结果保持其原来维数) 默认为 False,不保持其二维或者三维的特性.(结果不保持其原来维数)。 eg:shape为[2,5,4],keepdims = True,若按照轴axis=1求和,其结果的shape应该为[2,1,4],即把5变成1,剩下的2,4还是保留,如果为False则shape结果为[2,4]。若按照1轴和2轴axis=[1,2]求和,那么结果shape为[2,1,1],这个变成1,数值没有改变,只是维度变成1维。
21. 通过广播将A除以sum_A

A / sum_A

此行报错原因是因为,广播机制一定得维度相同,由于上面keepdims = False,没有保持原来的维度,所以维度改变,应该使用keepdims = True的结果,如下:

sum_A = A.sum(axis=1, keepdims=True)
A,sum_A,A / sum_A



(tensor([[ 0.,  1.,  2.,  3.],
         [ 4.,  5.,  6.,  7.],
         [ 8.,  9., 10., 11.],
         [12., 13., 14., 15.],
         [16., 17., 18., 19.]]),
 tensor([[ 6.],
         [22.],
         [38.],
         [54.],
         [70.]]),
 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]]))     # 运行结果

axis = 1表示横向,0/6=0,1/6=0.1667,2/6=0.3333,3/6=0.5,4/22=0.1818,5/22=0.2273等等
22. 某个轴计算A元素的累积总和

A,A.cumsum(axis=0)



(tensor([[ 0.,  1.,  2.,  3.],
         [ 4.,  5.,  6.,  7.],
         [ 8.,  9., 10., 11.],
         [12., 13., 14., 15.],
         [16., 17., 18., 19.]]),
 tensor([[ 0.,  1.,  2.,  3.],
         [ 4.,  6.,  8., 10.],
         [12., 15., 18., 21.],
         [24., 28., 32., 36.],
         [40., 45., 50., 55.]]))        # 运行结果

axis=0表示纵向,4=0+4,12=0+4+8,24=0+4+8+12,40=0+4+8+12+16,6+1+5,15=1+5=9,等等

23. 点积是相同位置的按元素乘积的和
x和y都是向量,dot表示是他们的点积:按元素相乘在求和,这是一个标量,torch.dot只能对一维向量做乘积

y = torch.ones(4, dtype=torch.float32)
x, y, torch.dot(x, y)



(tensor([0., 1., 2., 3.]), tensor([1., 1., 1., 1.]), tensor(6.)) # 运行结果

24. 我们可以通过执行按元素乘法,然后进行求和来表示两个向量的点积

torch.sum(x * y)


tensor(6.)     # 运行结果

25. 假设A是一个m * n的一个矩阵,x是一个n * 1的矩阵,则Ax是一个长度为m的一个列向量,它的第i个元素是A的第i行和x做点积。

A,x,A.shape, x.shape, torch.mv(A, x)



(tensor([[ 0.,  1.,  2.,  3.],
         [ 4.,  5.,  6.,  7.],
         [ 8.,  9., 10., 11.],
         [12., 13., 14., 15.],
         [16., 17., 18., 19.]]),
 tensor([0., 1., 2., 3.]),
 torch.Size([5, 4]),
 torch.Size([4]),
 tensor([ 14.,  38.,  62.,  86., 110.]))      # 运行结果

(5,4)* (4,1) = (5,1)是5行1列 torch.mv的mv是指matrix-vector multiplication,用矩阵A乘以x作为向量,mv是矩阵和向量的乘积。mm是矩阵与矩阵相乘(mm:Matrix-Matrix Multipliction)。一维向量是列向量(torch中一维向量是按照一维列向量参加运算,但是输出形式是行向量的形式)
26. 我们可以将矩阵-矩阵乘法AB看作是简单地执行m次矩阵-向量积,并将结果拼接在一起,形成一个n×m矩阵。A是一个5 * 4的矩阵,B是一个4 * 3的矩阵,那么AB做mm(即矩阵与矩阵的乘法)

B = torch.ones(4, 3)
torch.mm(A, B)


tensor([[ 6.,  6.,  6.],
        [22., 22., 22.],
        [38., 38., 38.],
        [54., 54., 54.],
        [70., 70., 70.]])         # 运行结果

结果是:(5,4)* (4,3) = (5,3)
27. 范数:是一个向量或者矩阵的长度。 L1 L2范数是针对向量而言的,F范数是针对矩阵而言的
(1)L2范数是向量元素平方和的平方根:
u是一个向量,则它的L2范数是,所有元素的做平方再求和再开根号,它的范数是用norm来定义,是一个标量

u = torch.tensor([3.0, -4.0])
torch.norm(u)



tensor(5.)       # 运行结果

(2)L1范数,它表示向量每个元素的绝对值的和:
对u取绝对值再求和

torch.abs(u).sum()



tensor(7.)       # 运行结果

28. 矩阵也有很对不也一样的范数,常用的是F范数。每个矩阵元素的平方,求和再开根号,等价于吧这个矩阵拉成一个向量,然后做一个向量的范数。矩阵 的弗罗贝尼乌斯范数(Frobenius norm)是矩阵元素平方和的平方根:

torch.norm(torch.ones((4, 9)))



tensor(6.)       # 运行结果

猜你喜欢

转载自blog.csdn.net/m0_45521766/article/details/126331734
今日推荐