李沐深度学习笔记-05线性代数

1.线性代数

标量由只有一个元素的张量表示

import torch
x=torch.tensor([3.0])
y=torch.tensor([2.0])
x+y,x*y,x/y,x**y
#输出(tensor([5.]), tensor([6.]), tensor([1.5000]), tensor([9.]))

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

x=torch.arange(4)
x
#输出tensor([0, 1, 2, 3])

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

x[3]
#输出tensor(3)

访问张量的长度

len(x)
#4

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

x.shape
#torch.Size([4])

通过指定两个分量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]])
'''
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]])
A=torch.arange(20,dtype=torch.float32).reshape(5,4)
B=A.clone()   #通过分配新内存,将A的一个副本分配给B
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.]]))'''

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)
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]))'''

计算其元素的和

x=torch.arange(4,dtype=torch.float32)
x,x.sum(),x.shape
#(tensor([0., 1., 2., 3.]), tensor(6.)), torch.Size([4]))

A_sum_axis0=A.sum(axis=0)
A_sum_axis0,A_sum_axis0.shape
# axis=0表示按列相加
#(tensor([40, 45, 50, 55]), torch.Size([4]))

A_sum_axis1=A.sum(axis=1)
A_sum_axis1,A_sum_axis1.shape
#axis=1表示按行相加 
#(tensor([ 6, 22, 38, 54, 70]), torch.Size([5]))

A.sum(axis=[0,1])
#相当于A.sum
#tensor(190)

A=torch.arange(20,dtype=torch.float32).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.]])
'''
A.mean(),A.sum()/A.numel()
#求均值,求和除以个数
#输出(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等于1,则把1的元素去掉

如shape[2,5,4]

axis=1,[2,4]

axis=2,[2,5]

axis=[1,2],[4]

如果keepdims = True,则保留该列为1

axis=1,keepdims = True,[2,1,4]

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

sum_A=A.sum(axis=1,keepdims=True)
sum_A
'''输出tensor([[ 6.],
        [22.],
        [38.],
        [54.],
        [70.]])'''
#keepdims=True保持维度
A.cumsum(axis=0)
'''tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  6.,  8., 10.],
        [12., 15., 18., 21.],
        [24., 28., 32., 36.],
        [40., 45., 50., 55.]])'''
#某个轴计算A元素的累积总和

点积

x=torch.arange(4,dtype=torch.float32)
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.))
#我们也可以执行按元素乘法,然后进行求和来表示两个向量的点积
torch.sum(x*y)
#tensor(6.)

矩阵向量积Ax

A.shape,x.shape,torch.mv(A,x)
#输出(torch.Size([5, 4]), torch.Size([4]), tensor([ 14.,  38.,  62.,  86., 110.]))

向量积AB

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.]])
'''

李沐深度学习笔记-05线性代数_第1张图片

李沐深度学习笔记-05线性代数_第2张图片

李沐深度学习笔记-05线性代数_第3张图片

2.拷贝

这个讲的很清楚:Python深拷贝和浅拷贝详解 (biancheng.net)

2.1浅拷贝

共享data的内存地址,数据会同步变化

指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。

  • a.numpy() # Tensor—>Numpy array
  • .view() #改变tensor的形状,但共享数据内存,不要直接使用id进行判断
  • y = x[:] # 索引
  • torch.from_numpy() # Numpy array—>Tensor
  • torch.as_tensor() #任意的Python类型的数据—>Tensor
  • torch.detach() # 新的tensor会脱离计算图,不会牵扯梯度计算
  • model.forward()
  • 就地操作in-place(详细解答:初识CV:PyTorch中In-palce(就地操作))

还有很多选择函数也是数据共享内存,如index_select(), masked_select(), gather()

(来源:PyTorch中的拷贝 - 知乎 (zhihu.com))

2.2深拷贝

会在内存中也创建一个副本

深拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。

拷贝数值、指针和指针指向的深层次内存空间,拷贝了父对象及其子对象。

  1. torch.clone() # 新的tensor会保留在计算图中,参与梯度计算
  • torch.clone()函数可以返回一个完全相同的tensor,新的tensor开辟新的内存,但是仍然留在计算图中。
  • torch.clone()操作在不共享数据内存的同时支持梯度回溯,所以常用在神经网络中某个单元需要重复使用的场景下。
  1. torch.Tensor() # 类的构造方法
  2. torch.tensor() # 工厂函数

你可能感兴趣的:(李沐深度学习笔记,深度学习,线性代数,pytorch)