深度学习线性代数简明教程

2018 年 5 月 30 日 论智
 作者:Vihar Kurama
编译:weakish

编者按:Python软件基金会成员(Contibuting Member)Vihar Kurama简要介绍了深度学习算法背后的数学。

深度学习(Deep Learning)是机器学习的子领域。而线性代数(linear algebra)是有关连续值的数学。许多计算机科学家在此方面经验不足(传统上计算机科学更偏重离散数学)。想要理解和使用许多机器学习算法,特别是深度学习算法,对线性代数的良好理解是不可或缺的。

为什么要学数学?

线性代数、概率论和微积分是确切地表达机器学习的“语言”。学习这些主题有助于形成对机器学习算法底层机制的深入理解,也有助于开发新的算法。

如果我们查看的尺度足够小,那么深度学习背后的一切都是数学。所以在开始深度学习之前,有必要理解基本的线性代数。

标量、向量、矩阵、张量;图片来源:hadrienj.github.io

深度学习背后的核心数据结构是标量(Scalar)向量(Vector)矩阵(Matrix)张量(Tensor)。让我们通过编程,使用这些数据结构求解基本的线性代数问题。

标量

标量是单个数字,或者说,0阶(0th-order)张量。x ∈ ℝ表示x是一个属于实数集ℝ的标量。

在深度学习中,有不同的数字集合。ℕ表示正整数集(1,2,3,…)。ℤ表示整数集,包括正数、负数和零。ℚ表示有理数集(可以表达为两个整数之比的数)。

在Python中有几个内置的标量类型:intfloatcomplexbytesUnicode。Numpy又增加了二十多个新的标量类型。

  
  
    
  1. import numpy as np

  2. np.ScalarType

返回:

  
  
    
  1. (int,

  2. float,

  3. complex,

  4. int,

  5. bool,

  6. bytes,

  7. str,

  8. memoryview,

  9. numpy.bool_,

  10. numpy.int8,

  11. numpy.uint8,

  12. numpy.int16,

  13. numpy.uint16,

  14. numpy.int32,

  15. numpy.uint32,

  16. numpy.int64,

  17. numpy.uint64,

  18. numpy.int64,

  19. numpy.uint64,

  20. numpy.float16,

  21. numpy.float32,

  22. numpy.float64,

  23. numpy.float128,

  24. numpy.complex64,

  25. numpy.complex128,

  26. numpy.complex256,

  27. numpy.object_,

  28. numpy.bytes_,

  29. numpy.str_,

  30. numpy.void,

  31. numpy.datetime64,

  32. numpy.timedelta64)

其中,以下划线(_)结尾的数据类型和对应的Python内置类型基本上是等价的。

在Python中定义标量和一些运算

下面的代码演示了一些张量的算术运算。

  
  
    
  1. a = 5

  2. b = 7.5

  3. print(type(a))

  4. print(type(b))

  5. print(a + b)

  6. print(a - b)

  7. print(a * b)

  8. print(a / b)

输出:

  
  
    
  1. <class 'int'>

  2. <class 'float'>

  3. 12.5

  4. -2.5

  5. 37.5

  6. 0.6666666666666666

下面的代码段检查给定的变量是否是标量:

  
  
    
  1. import numpy as np

  2. def isscalar(num):

  3.    if isinstance(num, generic):

  4.        return True

  5.    else:

  6.        return False

  7. print(np.isscalar(3.1))

  8. print(np.isscalar([3.1]))

  9. print(np.isscalar(False))

输出:

  
  
    
  1. True

  2. False

  3. True


向量

向量是由单个数字组成的有序数组,或者说,1阶张量。向量是向量空间这一对象的组成部分。向量空间是特定长度(又叫维度)的所有可能的向量的整个集合。三维实数向量空间(ℝ3)常用于表示现实世界中的三维空间。

为了指明向量的分量(component),向量的第i个标量元素记为x[i]

在深度学习中,向量通常用来表示特征向量。

在Python中定义向量和一些运算

声明向量:

  
  
    
  1. x = [1, 2, 3]

  2. y = [4, 5, 6]

  3. print(type(x))

输出:

  
  
    
  1. <class 'list'>

+并不表示向量的加法,而是列表的连接:

  
  
    
  1. print(x + y)

输出:

  
  
    
  1. [1, 2, 3, 4, 5, 6]

需要使用Numpy进行向量加法:

  
  
    
  1. z = np.add(x, y)

  2. print(z)

  3. print(type(z))

输出:

  
  
    
  1. [5 7 9]

  2. <class 'numpy.ndarray'>

向量的叉积(cross product)

两个向量的叉积向量,大小等于以这两个向量为邻边的平行四边形面积,方向与这两个向量所在平面垂直:

图片来源:维基百科

  
  
    
  1. np.cross(x, y)

返回:

  
  
    
  1. [-3  6 -3]

向量的点积(dot product)

向量的点积为标量,对于给定长度但方向不同的两个向量而言,方向差异越大,点积越小。

图片来源:betterexplained.com

  
  
    
  1. np.dot(x, y)

返回:

  
  
    
  1. 32


矩阵

矩阵是由数字组成的矩形数组,或者说,2阶张量。如果m和n为正整数,即,m, n ∈ ℕ,那么,一个m x n矩阵包含m * n个数字,m行n列。

m x n可表示为以下形式:

有时简写为:

在Python中定义矩阵和一些运算

在Python中,我们使用numpy库创建n维数组,也就是矩阵。我们将列表传入matrix方法,以定义矩阵。

  
  
    
  1. x = np.matrix([[1,2],[3,4]])

  2. x

返回:

  
  
    
  1. matrix([[1, 2],

  2.        [3, 4]])

矩阵第0轴的元素均值:

  
  
    
  1. x.mean(0)

返回:

  
  
    
  1. matrix([[2., 3.]]) # (1+3)/2, (3+4)/2

矩阵第1轴的元素均值:

  
  
    
  1. x.mean(1)

返回:

  
  
    
  1. z = x.mean(1)

  2. z

返回:

  
  
    
  1. matrix([[1.5],   # (1+2)/2

  2.        [3.5]])  # (3+4)/2

shape属性返回矩阵的形状:

  
  
    
  1. z.shape

返回:

  
  
    
  1. (2, 1)

所以,矩阵z有2行1列。

顺便提下,向量的shape属性返回由单个数字(向量的长度)组成的元组:

  
  
    
  1. np.shape([1, 2, 3])

返回:

  
  
    
  1. (3,)

而标量的shape属性返回一个空元祖:

  
  
    
  1. np.shape(1)

返回:

  
  
    
  1. ()

矩阵加法和乘法

矩阵可以和标量及其他矩阵相加、相乘。这些运算在数学上都有精确的定义。机器学习和深度学习经常使用这些运算,所以有必要熟悉这些运算。

对矩阵求和:

  
  
    
  1. x = np.matrix([[1, 2], [4, 3]])

  2. x.sum()

返回:

  
  
    
  1. 10

矩阵-标量加法

在矩阵的每个元素上加上给定标量:

  
  
    
  1. x = np.matrix([[1, 2], [4, 3]])

  2. x + 1

返回:

  
  
    
  1. matrix([[2, 3],

  2.        [5, 4]])

矩阵-标量乘法

类似地,矩阵-标量乘法就是在矩阵的每个元素上乘以给定标量:

  
  
    
  1. x * 3

返回:

  
  
    
  1. matrix([[ 3,  6],

  2.        [12,  9]])

矩阵-矩阵加法

形状相同的矩阵才能相加。两个矩阵对应位置的元素之和作为新矩阵的元素,而新矩阵的形状和原本两个矩阵一样。

  
  
    
  1. x = np.matrix([[1, 2], [4, 3]])

  2. y = np.matrix([[3, 4], [3, 10]])

x和y的形状均为(2, 2)。

  
  
    
  1. x + y

返回:

  
  
    
  1. matrix([[ 4,  6],

  2.        [ 7, 13]])

矩阵-矩阵乘法

形状为m x n的矩阵与形状为n x p的矩阵相乘,得到形状为m x p的矩阵。

图片来源:hadrienj.github.io

从编程的角度,矩阵乘法的一个直观解释是,一个矩阵是数据,另一个矩阵是即将应用于数据的函数(操作):

图片来源:betterexplained.com

  
  
    
  1. x = np.matrix([[1, 2], [3, 4], [5, 6]])

  2. y = np.matrix([[7], [13]]

  3. x * y

返回:

  
  
    
  1. matrix([[ 33],

  2.        [ 73],

  3.        [113]])

上面的代码中,矩阵x的形状为(3, 2),矩阵y的形状为(2, 1),故所得矩阵的形状为(3, 1)。如果x的列数不等于y的行数,则x和y不能相乘,强行相乘会报错shapes not aligned

矩阵转置

矩阵转置交换原矩阵的行和列(行变为列,列变为行),即:

  
  
    
  1. x = np.matrix([[1, 2], [3, 4], [5, 6]])

  2. x

返回:

  
  
    
  1. matrix([[1, 2],

  2.        [3, 4],

  3.        [5, 6]])

使用numpy提供的transpose()方法转置矩阵:

  
  
    
  1. x.transpose()

返回:

  
  
    
  1. matrix([[1, 3, 5],

  2.        [2, 4, 6]])

张量

比标量、向量、矩阵更通用的是张量概念。在物理科学和机器学习中,有时有必要使用超过二阶的张量(还记得吗?标量、向量、矩阵分别可以视为0、1、2阶张量。)

图片来源:refactored.ai

在Python中定义张量和一些运算

张量当然也可以用numpy表示(超过二阶的张量不过是超过二维的数组):

  
  
    
  1. import numpy as np

  2. t = np.array([

  3.  [[1,2,3], [4,5,6], [7,8,9]],

  4.  [[11,12,13], [14,15,16], [17,18,19]],

  5.  [[21,22,23], [24,25,26], [27,28,29]],

  6.  ])

  7. t.shape

返回:

  
  
    
  1. (3, 3, 3)

张量加法

  
  
    
  1. s = np.array([

  2.  [[1,2,3], [4,5,6], [7,8,9]],

  3.  [[10, 11, 12], [13, 14, 15], [16, 17, 18]],

  4.  [[19, 20, 21], [22, 23, 24], [25, 26, 27]],

  5. ])

  6. s + t

返回:

  
  
    
  1. array([[[ 2,  4,  6],

  2.        [ 8, 10, 12],

  3.        [14, 16, 18]],

  4.       [[21, 23, 25],

  5.        [27, 29, 31],

  6.        [33, 35, 37]],

  7.       [[40, 42, 44],

  8.        [46, 48, 50],

  9.        [52, 54, 56]]])

张量乘法

s * t得到的是阿达马乘积(Hadamard Product),也就是分素相乘(element-wise multiplication),将张量s和t中的每个元素相乘,所得乘积为结果张量对应位置的元素。

  
  
    
  1. s * t

返回:

  
  
    
  1. array([[[  1,   4,   9],

  2.        [ 16,  25,  36],

  3.        [ 49,  64,  81]],

  4.       [[110, 132, 156],

  5.        [182, 210, 240],

  6.        [272, 306, 342]],

  7.       [[399, 440, 483],

  8.        [528, 575, 624],

  9.        [675, 728, 783]]])

张量积(Tensor Product)需要使用numpy的tensordot方法计算。

图片来源:维基百科

计算s ⊗ t:

  
  
    
  1. s = np.array([[[1, 2], [3, 4]]])

  2. t = np.array([[[5, 6], [7, 8]]])

  3. np.tensordot(s, t, 0)

返回:

  
  
    
  1. array([[[[[[ 5,  6],

  2.           [ 7,  8]]],

  3.         [[[10, 12],

  4.           [14, 16]]]],

  5.        [[[[15, 18],

  6.           [21, 24]]],

  7.         [[[20, 24],

  8.           [28, 32]]]]]])

其中,最后一个参数0表示求张量积。当该参数为1时,表示求张量的点积(tensor dot product),这一运算可以视为向量点积概念的推广;当该参数为2时,表示求张量的缩并(tensor double contraction),这一运算可以视为矩阵乘法概念的推广。

当然,由于张量常用于深度学习,因此我们也经常直接使用深度学习框架表达张量。比如,在PyTorch中,创建一个形状为(5, 5)的张量,然后用浮点数1填充该张量:

  
  
    
  1. torch.ones(5, 5)

返回:

  
  
    
  1. tensor([[ 1.,  1.,  1.,  1.,  1.],

  2.        [ 1.,  1.,  1.,  1.,  1.],

  3.        [ 1.,  1.,  1.,  1.,  1.],

  4.        [ 1.,  1.,  1.,  1.,  1.],

  5.        [ 1.,  1.,  1.,  1.,  1.]])

登录查看更多
11

相关内容

一份简明有趣的Python学习教程,42页pdf
专知会员服务
76+阅读 · 2020年6月22日
最新《自动微分手册》77页pdf
专知会员服务
100+阅读 · 2020年6月6日
一份循环神经网络RNNs简明教程,37页ppt
专知会员服务
172+阅读 · 2020年5月6日
【2020新书】简明机器学习导论,电子书与500页PPT
专知会员服务
200+阅读 · 2020年2月7日
强化学习最新教程,17页pdf
专知会员服务
174+阅读 · 2019年10月11日
图解NumPy,这是理解数组最形象的一份教程了
机器之心
6+阅读 · 2019年7月12日
从张量到自动微分:PyTorch入门教程
论智
9+阅读 · 2018年10月10日
深度学习入门笔记
论智
7+阅读 · 2018年3月31日
入门 | 这是一份文科生都能看懂的线性代数简介
机器之心
13+阅读 · 2018年3月31日
【干货】​深度学习中的线性代数
专知
21+阅读 · 2018年3月30日
【机器学习数学基础】动图解释泰勒级数(一)
机器学习研究会
5+阅读 · 2018年2月25日
【干货】理解深度学习中的矩阵运算
机器学习研究会
18+阅读 · 2018年2月12日
Caffe 深度学习框架上手教程
黑龙江大学自然语言处理实验室
14+阅读 · 2016年6月12日
Arxiv
15+阅读 · 2020年2月6日
Arxiv
22+阅读 · 2019年11月24日
Seeing What a GAN Cannot Generate
Arxiv
8+阅读 · 2019年10月24日
Arxiv
18+阅读 · 2019年1月16日
The Matrix Calculus You Need For Deep Learning
Arxiv
12+阅读 · 2018年7月2日
Arxiv
6+阅读 · 2018年2月24日
VIP会员
相关VIP内容
一份简明有趣的Python学习教程,42页pdf
专知会员服务
76+阅读 · 2020年6月22日
最新《自动微分手册》77页pdf
专知会员服务
100+阅读 · 2020年6月6日
一份循环神经网络RNNs简明教程,37页ppt
专知会员服务
172+阅读 · 2020年5月6日
【2020新书】简明机器学习导论,电子书与500页PPT
专知会员服务
200+阅读 · 2020年2月7日
强化学习最新教程,17页pdf
专知会员服务
174+阅读 · 2019年10月11日
相关资讯
图解NumPy,这是理解数组最形象的一份教程了
机器之心
6+阅读 · 2019年7月12日
从张量到自动微分:PyTorch入门教程
论智
9+阅读 · 2018年10月10日
深度学习入门笔记
论智
7+阅读 · 2018年3月31日
入门 | 这是一份文科生都能看懂的线性代数简介
机器之心
13+阅读 · 2018年3月31日
【干货】​深度学习中的线性代数
专知
21+阅读 · 2018年3月30日
【机器学习数学基础】动图解释泰勒级数(一)
机器学习研究会
5+阅读 · 2018年2月25日
【干货】理解深度学习中的矩阵运算
机器学习研究会
18+阅读 · 2018年2月12日
Caffe 深度学习框架上手教程
黑龙江大学自然语言处理实验室
14+阅读 · 2016年6月12日
相关论文
Arxiv
15+阅读 · 2020年2月6日
Arxiv
22+阅读 · 2019年11月24日
Seeing What a GAN Cannot Generate
Arxiv
8+阅读 · 2019年10月24日
Arxiv
18+阅读 · 2019年1月16日
The Matrix Calculus You Need For Deep Learning
Arxiv
12+阅读 · 2018年7月2日
Arxiv
6+阅读 · 2018年2月24日
Top
微信扫码咨询专知VIP会员