作者 | Vihar Kurama
编译 | 专知
整理 | Mandy
线性代数对于理解机器学习和深度学习内部原理至关重要,线性代数是有关连续值的数学。许多计算机科学家在此方面经验不足,传统上计算机科学更偏重离散数学。这篇博文主要介绍了线性代数的基本概念,包括标量、向量、矩阵、张量,以及常见的矩阵运算,并且也有相应的Python代码实现。
Linear Algebra for Deep Learning
深度学习(Deep Learning)是机器学习的一个子领域,涉及的算法模仿大脑的功能和结构,称为人工神经网络。
线性代数(linear algebra)是有关连续值的数学。许多计算机科学家在此方面经验不足(传统上计算机科学更偏重离散数学)。想要理解和使用许多机器学习算法,特别是深度学习算法,对线性代数的良好理解是不可或缺的。
为什么要学习数学?
线性代数、概率论和微积分是用来表达机器学习的“语言”。学习这些内容将有助于深入理解底层的算法机制,也有助于开发新的算法。
当被限制在足够小的尺度上,深度学习背后的一切都是数学。所以在开始深度学习之前,了解基本的线性代数是非常重要的。
深度学习背后的核心数据结构是标量(Scalar)、向量(Vector)、矩阵(Matrix)、张量(Tensor)。在编程中,让我们使用这些数据结构求解基本的线性代数问题。
标量(Scalars)
标量是一个数字,或者说,是一个0阶张量。符号表示是一个属于实数集的标量。
深度学习中有着不同的数字集合。表示正整数集。表示整数集,包括正整数,负整数和零。表示有理数集,可以表达两个整数之比的数。
在Python中有几个内置的标量类型:int、float、complex、bytes、Unicode。Numpy又增加了二十多种新的标量类型。有关数据类型的更多信息,请参阅文档。
在Python中定义标量和一些运算: 下面的代码片段展示了对标量的几个运算操作。
# In-Built Scalars
a = 5
b = 7.5
print(type(a))
print(type(b))
print(a + b)
print(a - b)
print(a * b)
print(a / b)
输出结果:
<class 'int'>
<class 'float'>
12.5
-2.5
37.5
0.6666666666666666
下面的代码片段用来检查给定的变量是否是标量。
import numpy as np
# Is Scalar Function
def isscalar(num):
if isinstance(num, generic):
return True
else:
return False
print(np.isscalar(3.1))
print(np.isscalar([3.1]))
print(np.isscalar(False))
输出结果:
True
False
True
向量(Vectors)
向量是由单个数字组成的有序数组,或者说,1阶张量。向量是向量空间这一对象的组成部分。一个向量空间可以看作是一个特定长度(或维度)的所有可能向量的集合。三维实数向量空间()常用于表示现实世界中的三维空间。 为了明确地识别向量的分量(component),向量的第个标量元素被记为。
在深度学习中,向量通常表示特征向量,其原始分量定义了特定特征的相关性。这些元素可以是二维图像中一组像素的强度的相关性或者是金融工具截面的历史价格值。
在Python中定义向量和一些运算:
import numpy as np
# 声明向量
x = [1, 2, 3]
y = [4, 5, 6]
print(type(x))
# +并不表示向量的加法,而是列表的连接:
print(x + y)
# 需要使用Numpy进行向量加法:
z = np.add(x, y)
print(z)
print(type(z))
# 向量的叉积(cross product):两个向量的叉积向量,
大小等于以这两个向量为邻边的平行四边形面积,方向与这两个向量所在平面垂直
mul = np.cross(x, y)
print(mul)
输出结果:
<class 'list'>
[1, 2, 3, 4, 5, 6]
[5 7 9]
<class 'numpy.ndarray'>
[-3 6 -3]
矩阵(Matrices)
矩阵是由数字组成的矩形数组,或者说,2阶张量。如果和为正整数,即 ,那么一个的矩阵包含个数字,行列。 一个的矩阵可表示成:
有时可简写为:
在Python中,我们使用numpy库创建n维数组,也就是矩阵。我们将列表传入matrix方法,以定义矩阵。
>>> import numpy as np
>>> x = np.matrix([[1,2],[2,3]])
>>> x
matrix([[1, 2],
[2, 3]])
>>> a = x.mean(0)
>>> a
matrix([[1.5, 2.5]])
>>> # Finding the mean with 1 with the matrix x.
>>> z = x.mean(1)
>>> z
matrix([[ 1.5],
[ 2.5]])
>>> z.shape
(2, 1)
>>> y = x - z
matrix([[-0.5, 0.5],
[-0.5, 0.5]])
>>> print(type(z))
<class 'numpy.matrixlib.defmatrix.matrix'>
在Python中定义矩阵和一些运算:
矩阵加法
矩阵可以与标量、向量和其他矩阵相加。每个操作都有一个精确的定义。这些技术在机器学习和深度学习中经常被使用,所以你需要熟悉它们。
# Matrix Addition
import numpy as np
x = np.matrix([[1, 2], [4, 3]])
sum = x.sum()
print(sum)
# Output: 10
矩阵-矩阵相加
C = A + B(矩阵A和矩阵B应该具有相等的行数和列数)
两个矩阵的相对应的元素分别相加,如果矩阵的形状不相同,则会抛出一个错误,说明不能相加。
# Matrix-Matrix Addition
import numpy as np
x = np.matrix([[1, 2], [4, 3]])
y = np.matrix([[3, 4], [3, 10]])
print(x.shape)
# (2, 2)
print(y.shape)
# (2, 2)
m_sum = np.add(x, y)
print(m_sum)
print(m_sum.shape)
"""
Output :
[[ 4 6]
[ 7 13]]
(2, 2)
"""
矩阵-标量相加
将给定的标量与给定矩阵中的所有元素相加。
# Matrix-Scalar Addition
import numpy as np
x = np.matrix([[1, 2], [4, 3]])
s_sum = x + 1
print(s_sum)
"""
Output:
[[2 3]
[5 4]]
"""
矩阵-标量相乘
将给定的标量与给定矩阵中的所有元素相乘。
# Matrix Scalar Multiplication
import numpy as np
x = np.matrix([[1, 2], [4, 3]])
s_mul = x * 3
print(s_mul)
"""
[[ 3 6]
[12 9]]
"""
矩阵-矩阵相乘
矩阵A(m行n列)与矩阵B(n行p列)得到矩阵C(m行p列),如下图所示:
# Matrix Multiplication
import numpy as np
a = [[1, 0], [0, 1]]
b = [1, 2]
np.matmul(a, b)
# Output: array([1, 2])
complex_mul = np.matmul([2j, 3j], [2j, 3j])
print(complex_mul)
# Output: (-13+0j)
矩阵转置
矩阵转置交换原矩阵的行和列(行变为列,列变为行)。通过转置,可以将行向量转换为列向量,反之亦然:
# Matrix Transpose
import numpy as np
a = np.array([[1, 2], [3, 4]])
print(a)
"""
[[1 2]
[3 4]]
"""
a.transpose()
print(a)
"""
array([[1, 3],
[2, 4]])
"""
张量(Tensors)
比标量、向量、矩阵更通用的概念是张量。在物理科学和机器学习中,有时需要使用超过二阶的张量(如前文中所说,标量、向量、矩阵分别可以视为0、1、2阶张量。)
一般来说,我们使用像tensorflow或PyTorch这样的Python库来声明张量。
在PyTorch中定义一个简单的张量:
import torch
a = torch.Tensor([26])
print(type(a))
# <class 'torch.FloatTensor'>
print(a.shape)
# torch.Size([1])
# Creates a Random Torch Variable of size 5x3.
t = torch.Tensor(5, 3)
print(t)
"""
0.0000e+00 0.0000e+00 0.0000e+00
0.0000e+00 7.0065e-45 1.1614e-41
0.0000e+00 2.2369e+08 0.0000e+00
0.0000e+00 0.0000e+00 0.0000e+00
nan nan -1.4469e+35
[torch.FloatTensor of size 5x3]
"""
print(t.shape)
# torch.Size([5, 3])
Python中对张量的一些算术运算:
import torch
# Creating Tensors
p = torch.Tensor(4,4)
q = torch.Tensor(4,4)
ones = torch.ones(4,4)
print(p, q, ones)
"""
Output:
0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00
1.6009e-19 4.4721e+21 6.2625e+22 4.7428e+30
3.1921e-09 8.0221e+17 5.1019e-08 8.1121e+17
8.1631e-07 8.2022e+17 1.1703e-19 1.5637e-01
[torch.FloatTensor of size 4x4]
0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00
1.8217e-44 1.1614e-41 0.0000e+00 2.2369e+08
0.0000e+00 0.0000e+00 2.0376e-40 2.0376e-40
nan nan -5.3105e+37 nan
[torch.FloatTensor of size 4x4]
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
[torch.FloatTensor of size 4x4]
"""
print("Addition:{}".format(p + q))
print("Subtraction:{}".format(p - ones))
print("Multiplication:{}".format(p * ones))
print("Division:{}".format(q / ones))
"""
Addition:
0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00
1.6009e-19 4.4721e+21 6.2625e+22 4.7428e+30
3.1921e-09 8.0221e+17 5.1019e-08 8.1121e+17
nan nan -5.3105e+37 nan
[torch.FloatTensor of size 4x4]
Subtraction:
-1.0000e+00 -1.0000e+00 -1.0000e+00 -1.0000e+00
-1.0000e+00 4.4721e+21 6.2625e+22 4.7428e+30
-1.0000e+00 8.0221e+17 -1.0000e+00 8.1121e+17
-1.0000e+00 8.2022e+17 -1.0000e+00 -8.4363e-01
[torch.FloatTensor of size 4x4]
Multiplication:
0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00
1.6009e-19 4.4721e+21 6.2625e+22 4.7428e+30
3.1921e-09 8.0221e+17 5.1019e-08 8.1121e+17
8.1631e-07 8.2022e+17 1.1703e-19 1.5637e-01
[torch.FloatTensor of size 4x4]
Division:
0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00
1.8217e-44 1.1614e-41 0.0000e+00 2.2369e+08
0.0000e+00 0.0000e+00 2.0376e-40 2.0376e-40
nan nan -5.3105e+37 nan
[torch.FloatTensor of size 4x4]
"""
有关张量和PyTorch的更多文档,请查阅文档。
原文链接:
https://towardsdatascience.com/linear-algebra-for-deep-learning-506c19c0d6fa
推荐阅读:
【学术福利】Pytorch的tensorboard食谱帮你可视化误差结果
通俗易懂讲解感知机(三)--收敛性证明与对偶形式以及python代码讲解
扫码加好友,加入海归Python编程和人工智能群