05 线性代数【动手学深度学习v2】

线性代数

多维数组和线性代数的区别?
- 多维数组是一个计算机的概念,纯计算机的语言
- 线性代数是从数学上的表达,具有数学上的意义
标量
- 可以理解为一个单个的值
简单操作
- c = a + b
- c = a * b
- c = sin(a)
长度

向量
- 可以理解为一行值,既可以是行向量,也可以是列向量
简单操作

长度


点乘

- 对应元素相同
正交

- 两个向量如果是垂直的话,他们的点乘的值为0
矩阵
一般用大写字母表示矩阵,下面为了方便用小写字母表示
简单操作

乘法
- 矩阵乘以向量(从直观上来讲是一个扭曲的空间)线性代数 P1 - 04:43

- 矩阵乘以矩阵

范数(矩阵的长度)





- 对称矩阵总是能找到特征向量,但不是每个矩阵都能找到特征向量
线性代数实现
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.]))
2、可以将向量视为标量值组成的列表
x = torch.arange(4)
x
输出:
tensor([0, 1, 2, 3])
3、通过张量的索引来访问任一元素
x[3]
输出:
tensor(3)
4、访问张量的长度
len(x)
输出:
4
5、只有一个轴的张量,形状只有一个元素
x.shape
输出:
torch.Size([4])
6、通过指定两个分量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]])
7、矩阵的转置
a.T
输出:
tensor([[ 0, 4, 8, 12, 16],
[ 1, 5, 9, 13, 17],
[ 2, 6, 10, 14, 18],
[ 3, 7, 11, 15, 19]])
8、对称矩阵(symmetric matrix)
对称矩阵等于其转置:a = aT
b = torch.tensor([[1,2,3],[2,3,1],[3,2,1]])
b
输出:
tensor([[1, 2, 3],
[2, 3, 1],
[3, 2, 1]])
b == b.T
输出:
tensor([[ True, True, True],
[ True, True, False],
[ True, False, True]])
- 矩阵的所有元素都是关于对角线对称的
9、就像向量是标量的推广,矩阵是向量的推广一样,我们可以构建具有更多轴的数据结构
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]]])
- tensor中的行是最后一维,列是倒数第二维,以此类推
10、给定具有相同形状的任何两个张量,任何按元素二元计算的结果都将是相同形状的张量
a = torch.arange(20,dtype = torch.float32).reshape(5,4)
b = a.clone()
a , a + b
- 通过分配新内存,将 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.]]))
11、两个矩阵的按元素乘法称为 哈达玛积(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.]])
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]))
- 张量和一个标量进行运算实际上就是张量的所有元素和这个标量进行运算
12、计算其元素的和
x = torch.arange(4,dtype=torch.float32)
x , x.sum()
输出:
(tensor([0., 1., 2., 3.]), tensor(6.))
13、表示任意形状张量的元素和
a = torch.arange(20,dtype = torch.float32).reshape(5,4)
a.shape , a.sum()
输出:
(torch.Size([5, 4]), tensor(190.))
- .sum():不管张量是什么形状,计算出来的结果始终是一个标量
a = torch.arange(20 * 2,dtype = torch.float32).reshape(2,5,4)
a.shape , a.sum()
输出:
(torch.Size([2, 5, 4]), tensor(780.))
14、指定求和张量的值
a_sum_axis0 = a.sum(axis = 0)
a_sum_axis0 , a_sum_axis0.shape
输出:
(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.sum(axis = [0 , 1]).shape
输出:
torch.Size([4])
15、一个与求和相关的量是 平均值(mean或average)
a = torch.arange(20,dtype = torch.float32).reshape(5,4)
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.]))
16、计算综合或均值时保持轴数不变
sum_a = a.sum(axis = 1 , keepdims = True)
sum_a
- keepdims=True:使被求和的维度大小变为1,为1的好处是可以利用广播机制
输出:
tensor([[ 6.],
[22.],
[38.],
[54.],
[70.]])
17、通过广播将 a 除以sum_a
a / sum_a
输出:
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]])
18、某个轴计算a元素的累积总和
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.]])
19、点积是相同位置的按元素乘积的和
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.))
20、可以通过执行按元素乘法,然后进行求和来表示两个向量的点积
torch.sum(x * y)
输出:
tensor(6.)
21、

a.shape , x.shape , torch.mv(a,x)
- torch.mv():做矩阵向量的乘积
输出:
(torch.Size([5, 4]), torch.Size([4]), tensor([ 14., 38., 62., 86., 110.]))
22、可以将矩阵-矩阵乘法AB看作简单地执行m次矩阵-向量积,并将结果拼接到一起,形成一个n * m矩阵
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.]])
23、L2范数是向量元素平方和的平方根

u = torch.tensor([3.0,-4.0])
torch.norm(u)
输出:
tensor(5.)
24、L1范数表示为向量元素的绝对值之和

torch.abs(u).sum()
输出:
tensor(7.)
25、矩阵的 弗罗贝尼乌斯范数(Frobenius norm) 实矩阵元素的平方和的平方根

torch.norm(torch.ones((4,9)))
输出:
tensor(6.)
- 等价于将矩阵拉成一个向量,然后做一个向量的范数
- 计算简单,是最常用的范数
按待定轴求和
总的来说axis等于几就去掉那一维(keepdim不为True时),当keepdim为True时,将axis指定的那一维的shape置为1
import torch
a = torch.ones(2,5,4)
a.shape
输出:
torch.Size([2, 5, 4])
a.sum().shape
输出:
torch.Size([])
- shape为空,表示它是一个标量
a.sum(axis = 1).shape
输出:
torch.Size([2, 4])
a.sum(axis = 1)
输出:
tensor([[5., 5., 5., 5.],
[5., 5., 5., 5.]])
a.sum(axis = 0).shape
输出:
torch.Size([5, 4])
a.sum(axis = [0,2]).shape
输出:
torch.Size([5])
a.sum(axis = 1,keepdim=True).shape
输出:
torch.Size([2, 1, 4])
- 维度的个数没有发生变化只是第2个元素(下标为1)变换成了1
Q&A
1、这么转化有什么负面影响?比如数值变得稀疏
稀疏矩阵不会有太多影响
2、问什么深度学习要用张量来表示?
整个机器学习都是用张量或者是用数值的矩阵来表示的,深度学习是由机器学习发展过来的,机器学习实际上是统计的计算机版本
3、求copy与clone的区别(是关于内存的吗)?
copy有可能是不copy内存的(深度copy与浅copy)
clone一定会复制内存
4、对哪一维求和就是消除那一维可以这么理解吗?
可以这么理解,将某一维缩减成一个值
5、torch不区分行向量和列向量吗?
- 如果是一维向量的话一定是一个行向量
- 列向量是一个矩阵
- 可以用一个二维的矩阵来区分一个列向量和一个行向量
6、sum(axis=[0,1])怎么求?
- 相当于每次求和是对于一个矩阵来说的
7、请问torch中L1,L2正则项要怎么加入?
之后会讲
8、稀疏的时候可以把它当成单词做词向量解决吗?
之后会讲,稀疏的话可以当成词向量来进行查表,但不见得每次都能这样做,绝大部分可以这么做
9、张量的概念机器学习里和数学有哪些主要的区别?
- 机器学习的张量其实不是张量,就是一个多维数组,跟数学的张量是不一样的
- 深度学习大部分的运算都是矩阵的运算,不会用到数学中张量的概念
10、这门课是不是只讲基于pytorch的神经网络算法?学习其他算法可以先听这门课吗?
- 工具和学习应该是分开的
- 主要是学会,然后拓展至其他框架
11、病理图片的SVS格式和医生勾画的区域XML格式的文件如何进行预处理?
12、稀疏化之后有什么好的解决办法?
被跳过了。。。
13、老师后面讲算法的时候可以着重讲一下算法提出的过程的直觉和数学吗,想多了解算法背后的why?
----end----