深度学习之Python的科学计算包 – Numpy
2017-10-28 14:22
851 查看
umpy(Numerical Python extensions)是一个第三方的Python包,用于科学计算。这个库的前身是1995年就开始开发的一个用于数组运算的库。经过了长时间的发展,基本上成了绝大部分Python科学计算的基础包,当然也包括所有提供Python接口的深度学习框架。
numpy在Linux下的安装已经在5.1.2中作为例子讲过,Windows下也可以通过pip,或者到下面网址下载:
Obtaining
NumPy & SciPy libraries
array,也就是数组,是numpy中最基础的数据结构,最关键的属性是维度和元素类型,在numpy中,可以非常方便地创建各种不同类型的多维数组,并且执行一些基本基本操作,来看例子:
Python
注意到在导入numpy的时候,我们将np作为numpy的别名。这是一种习惯性的用法,后面的章节中我们也默认这么使用。作为一种多维数组结构,array的数组相关操作是非常丰富的:Python
对于一维的array所有Python列表支持的下标相关的方法array也都支持,所以在此没有特别列出。
既然叫numerical python,基础数学运算也是强大的:
Python
对于array,默认执行对位运算。涉及到多个array的对位运算需要array的维度一致,如果一个array的维度和另一个array的子维度一致,则在没有对齐的维度上分别执行对位运算,这种机制叫做广播(broadcasting),言语解释比较难,还是看例子理解:Python
在深度学习相关的数据处理和运算中,线性代数模块(linalg)是最常用的之一。结合numpy提供的基本函数,可以对向量,矩阵,或是说多维张量进行一些基本的运算:
Python
随机模块可以很方便地让我们做一些快速模拟去验证一些结论。比如来考虑一个非常违反直觉的概率题例子:一个选手去参加一个TV秀,有三扇门,其中一扇门后有奖品,这扇门只有主持人知道。选手先随机选一扇门,但并不打开,主持人看到后,会打开其余两扇门中没有奖品的一扇门。然后,主持人问选手,是否要改变一开始的选择?
这个问题的答案是应该改变一开始的选择。在第一次选择的时候,选错的概率是2/3,选对的概率是1/3。第一次选择之后,主持人相当于帮忙剔除了一个错误答案,所以如果一开始选的是错的,这时候换掉就选对了;而如果一开始就选对,则这时候换掉就错了。根据以上,一开始选错的概率就是换掉之后选对的概率(2/3),这个概率大于一开始就选对的概率(1/3),所以应该换。虽然道理上是这样,但是还是有些绕,要是通过推理就是搞不明白怎么办,没关系,用随机模拟就可以轻松得到答案:
Python
numpy在Linux下的安装已经在5.1.2中作为例子讲过,Windows下也可以通过pip,或者到下面网址下载:
Obtaining
NumPy & SciPy libraries
5.3.1 基本类型(array)
array,也就是数组,是numpy中最基础的数据结构,最关键的属性是维度和元素类型,在numpy中,可以非常方便地创建各种不同类型的多维数组,并且执行一些基本基本操作,来看例子:Python
123456789101112131415161718192021222324252627282930313233343536373839404142 | import numpy as np a = [1, 2, 3, 4] #b = np.array(a) # array([1, 2, 3, 4])type(b) # <type 'numpy.ndarray'> b.shape # (4,)b.argmax() # 3b.max() # 4b.mean() # 2.5 c = [[1, 2], [3, 4]] # 二维列表d = np.array(c) # 二维numpy数组d.shape # (2, 2)d.size # 4d.max(axis=0) # 找维度0,也就是最后一个维度上的最大值,array([3, 4])d.max(axis=1) # 找维度1,也就是倒数第二个维度上的最大值,array([2, 4])d.mean(axis=0) # 找维度0,也就是第一个维度上的均值,array([ 2., 3.])d.flatten() # 展开一个numpy数组为1维数组,array([1, 2, 3, 4])np.ravel(c) # 展开一个可以解析的结构为1维数组,array([1, 2, 3, 4]) # 3x3的浮点型2维数组,并且初始化所有元素值为1e = np.ones((3, 3), dtype=np.float) # 创建一个一维数组,元素值是把3重复4次,array([3, 3, 3, 3])f = np.repeat(3, 4) # 2x2x3的无符号8位整型3维数组,并且初始化所有元素值为0g = np.zeros((2, 2, 3), dtype=np.uint8)g.shape # (2, 2, 3)h = g.astype(np.float) # 用另一种类型表示 l = np.arange(10) # 类似range,array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])m = np.linspace(0, 6, 5)# 等差数列,0到6之间5个取值,array([ 0., 1.5, 3., 4.5, 6.]) p = np.array( [[1, 2, 3, 4], [5, 6, 7, 8]]) np.save('p.npy', p) # 保存到文件q = np.load('p.npy') # 从文件读取 |
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | import numpy as np ''' array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]) ''' a = np.arange(24).reshape((2, 3, 4)) b = a[1][1][1] # 17 ''' array([[ 8, 9, 10, 11], [20, 21, 22, 23]]) ''' c = a[:, 2, :] ''' 用:表示当前维度上所有下标 array([[ 1, 5, 9], [13, 17, 21]]) ''' d = a[:, :, 1] ''' 用...表示没有明确指出的维度 array([[ 1, 5, 9], [13, 17, 21]]) ''' e = a[..., 1] ''' array([[[ 5, 6], [ 9, 10]], [[17, 18], [21, 22]]]) ''' f = a[:, 1:, 1:-1] ''' 平均分成3份 [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])] ''' g = np.split(np.arange(9), 3) ''' 按照下标位置进行划分 [array([0, 1]), array([2, 3, 4, 5]), array([6, 7, 8])] ''' h = np.split(np.arange(9), [2, -3]) l0 = np.arange(6).reshape((2, 3)) l1 = np.arange(6, 12).reshape((2, 3)) ''' vstack是指沿着纵轴拼接两个array,vertical hstack是指沿着横轴拼接两个array,horizontal 更广义的拼接用concatenate实现,horizontal后的两句依次等效于vstack和hstack stack不是拼接而是在输入array的基础上增加一个新的维度 ''' m = np.vstack((l0, l1)) p = np.hstack((l0, l1)) q = np.concatenate((l0, l1)) r = np.concatenate((l0, l1), axis=-1) s = np.stack((l0, l1)) ''' 按指定轴进行转置 array([[[ 0, 3], [ 6, 9]], [[ 1, 4], [ 7, 10]], [[ 2, 5], [ 8, 11]]]) ''' t = s.transpose((2, 0, 1)) ''' 默认转置将维度倒序,对于2维就是横纵轴互换 array([[ 0, 4, 8], [ 1, 5, 9], [ 2, 6, 10], [ 3, 7, 11]]) ''' u = a[0].transpose() # 或者u=a[0].T也是获得转置 ''' 逆时针旋转90度,第二个参数是旋转次数 array([[ 3, 2, 1, 0], [ 7, 6, 5, 4], [11, 10, 9, 8]]) ''' v = np.rot90(u, 3) ''' 沿纵轴左右翻转 array([[ 8, 4, 0], [ 9, 5, 1], [10, 6, 2], [11, 7, 3]]) ''' w = np.fliplr(u) ''' 沿水平轴上下翻转 array([[ 3, 7, 11], [ 2, 6, 10], [ 1, 5, 9], [ 0, 4, 8]]) ''' x = np.flipud(u) ''' 按照一维顺序滚动位移 array([[11, 0, 4], [ 8, 1, 5], [ 9, 2, 6], [10, 3, 7]]) ''' y = np.roll(u, 1) ''' 按照指定轴滚动位移 array([[ 8, 0, 4], [ 9, 1, 5], [10, 2, 6], [11, 3, 7]]) ''' z = np.roll(u, 1, axis=1) |
既然叫numerical python,基础数学运算也是强大的:
Python
12345678910111213141516171819202122232425262728293031 | import numpy as np # 绝对值,1a = np.abs(-1) # sin函数,1.0b = np.sin(np.pi/2) # tanh逆函数,0.50000107157840523c = np.arctanh(0.462118) # e为底的指数函数,20.085536923187668d = np.exp(3) # 2的3次方,8f = np.power(2, 3) # 点积,1*3+2*4=11g = np.dot([1, 2], [3, 4]) # 开方,5h = np.sqrt(25) # 求和,10l = np.sum([1, 2, 3, 4]) # 平均值,5.5m = np.mean([4, 5, 6, 7]) # 标准差,0.96824583655185426p = np.std([1, 2, 3, 2, 1, 3, 2, 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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | import numpy as np a = np.array([ [1, 2, 3], [4, 5, 6] ]) b = np.array([ [1, 2, 3], [1, 2, 3] ]) ''' 维度一样的array,对位计算 array([[2, 4, 6], [5, 7, 9]]) ''' a + b ''' array([[0, 0, 0], [3, 3, 3]]) ''' a - b ''' array([[ 1, 4, 9], [ 4, 10, 18]]) ''' a * b ''' array([[1, 1, 1], [4, 2, 2]]) ''' a / b ''' array([[ 1, 4, 9], [16, 25, 36]]) ''' a ** 2 ''' array([[ 1, 4, 27], [ 4, 25, 216]]) ''' a ** b c = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]) d = np.array([2, 2, 2]) ''' 广播机制让计算的表达式保持简洁 d和c的每一行分别进行运算 array([[ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11], [12, 13, 14]]) ''' c + d ''' array([[ 2, 4, 6], [ 8, 10, 12], [14, 16, 18], [20, 22, 24]]) ''' c * d ''' 1和c的每个元素分别进行运算 array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]]) ''' c - 1 |
5.3.2 线性代数模块(linalg)
在深度学习相关的数据处理和运算中,线性代数模块(linalg)是最常用的之一。结合numpy提供的基本函数,可以对向量,矩阵,或是说多维张量进行一些基本的运算:Python
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 | import numpy as np a = np.array([3, 4])np.linalg.norm(a) b = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9]])c = np.array([1, 0, 1]) # 矩阵和向量之间的乘法np.dot(b, c) # array([ 4, 10, 16])np.dot(c, b.T) # array([ 4, 10, 16]) np.trace(b) # 求矩阵的迹,15np.linalg.det(b) # 求矩阵的行列式值,0np.linalg.matrix_rank(b) # 求矩阵的秩,2,不满秩,因为行与行之间等差 d = np.array([ [2, 1], [1, 2]]) '''对正定矩阵求本征值和本征向量本征值为u,array([ 3., 1.])本征向量构成的二维array为v,array([[ 0.70710678, -0.70710678], [ 0.70710678, 0.70710678]])是沿着45°方向eig()是一般情况的本征值分解,对于更常见的对称实数矩阵,eigh()更快且更稳定,不过输出的值的顺序和eig()是相反的'''u, v = np.linalg.eig(d) # Cholesky分解并重建l = np.linalg.cholesky(d) '''array([[ 2., 1.], [ 1., 2.]])'''np.dot(l, l.T) e = np.array([ [1, 2], [3, 4]]) # 对不镇定矩阵,进行SVD分解并重建U, s, V = np.linalg.svd(e) S = np.array([ [s[0], 0], [0, s[1]]]) '''array([[ 1., 2.], [ 3., 4.]])'''np.dot(U, np.dot(S, V)) |
5.3.3 随机模块(random)
随机模块包含了随机数产生和统计分布相关的基本函数,Python本身也有随机模块random,不过功能更丰富,还是来看例子:Python1 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 40 41 42 43 44 45 46 47 48 49 50 | import numpy as np import numpy.random as random # 设置随机数种子 random.seed(42) # 产生一个1x3,[0,1)之间的浮点型随机数 # array([[ 0.37454012, 0.95071431, 0.73199394]]) # 后面的例子就不在注释中给出具体结果了 random.rand(1, 3) # 产生一个[0,1)之间的浮点型随机数 random.random() # 下边4个没有区别,都是按照指定大小产生[0,1)之间的浮点型随机数array,不Pythonic… random.random((3, 3)) random.sample((3, 3)) random.random_sample((3, 3)) random.ranf((3, 3)) # 产生10个[1,6)之间的浮点型随机数 5*random.random(10) + 1 random.uniform(1, 6, 10) # 产生10个[1,6]之间的整型随机数 random.randint(1, 6, 10) # 产生2x5的标准正态分布样本 random.normal(size=(5, 2)) # 产生5个,n=5,p=0.5的二项分布样本 random.binomial(n=5, p=0.5, size=5) a = np.arange(10) # 从a中有回放的随机采样7个 random.choice(a, 7) # 从a中无回放的随机采样7个 random.choice(a, 7, replace=False) # 对a进行乱序并返回一个新的array b = random.permutation(a) # 对a进行in-place乱序 random.shuffle(a) # 生成一个长度为9的随机bytes序列并作为str返回 # '\x96\x9d\xd1?\xe6\x18\xbb\x9a\xec' random.bytes(9) |
这个问题的答案是应该改变一开始的选择。在第一次选择的时候,选错的概率是2/3,选对的概率是1/3。第一次选择之后,主持人相当于帮忙剔除了一个错误答案,所以如果一开始选的是错的,这时候换掉就选对了;而如果一开始就选对,则这时候换掉就错了。根据以上,一开始选错的概率就是换掉之后选对的概率(2/3),这个概率大于一开始就选对的概率(1/3),所以应该换。虽然道理上是这样,但是还是有些绕,要是通过推理就是搞不明白怎么办,没关系,用随机模拟就可以轻松得到答案:
Python
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | import numpy.random as random random.seed(42) # 做10000次实验 n_tests = 10000 # 生成每次实验的奖品所在的门的编号 # 0表示第一扇门,1表示第二扇门,2表示第三扇门 winning_doors = random.randint(0, 3, n_tests) # 记录如果换门的中奖次数 change_mind_wins = 0 # 记录如果坚持的中奖次数 insist_wins = 0 # winning_door就是获胜门的编号 for winning_door in winning_doors: # 随机挑了一扇门 first_try = random.randint(0, 3) # 其他门的编号 remaining_choices = [i for i in range(3) if i != first_try] # 没有奖品的门的编号,这个信息只有主持人知道 wrong_choices = [i for i in range(3) if i != winning_door] # 一开始选择的门主持人没法打开,所以从主持人可以打开的门中剔除 if first_try in wrong_choices: wrong_choices.remove(first_try) # 这时wrong_choices变量就是主持人可以打开的门的编号 # 注意此时如果一开始选择正确,则可以打开的门是两扇,主持人随便开一扇门 # 如果一开始选到了空门,则主持人只能打开剩下一扇空门 screened_out = random.choice(wrong_choices) remaining_choices.remove(screened_out) # 所以虽然代码写了好些行,如果策略固定的话, # 改变主意的获胜概率就是一开始选错的概率,是2/3 # 而坚持选择的获胜概率就是一开始就选对的概率,是1/3 # 现在除了一开始选择的编号,和主持人帮助剔除的错误编号,只剩下一扇门 # 如果要改变注意则这扇门就是最终的选择 changed_mind_try = remaining_choices[0] # 结果揭晓,记录下来 change_mind_wins += 1 if changed_mind_try == winning_door else 0 insist_wins += 1 if first_try == winning_door else 0 # 输出10000次测试的最终结果,和推导的结果差不多: # You win 6616 out of 10000 tests if you changed your mind # You win 3384 out of 10000 tests if you insist on the initial choice print( 'You win {1} out of {0} tests if you changed your mind\n' 'You win {2} out of {0} tests if you insist on the initial choice'.format( n_tests, change_mind_wins, insist_wins ) ) |
相关文章推荐
- Python科学计算学习一 NumPy 快速处理数据
- python 科学计算学习一:numpy文件存取,内存映射
- python 科学计算 — numpy 学习笔记
- python 学习之 用python做科学计算Numpy
- python-框架-网页爬虫-文本处理-科学计算-可视化-机器学习-数据挖掘-深度学习
- python 科学计算学习一:numpy文件存取,内存映射
- Coursera 深度学习 deep learning.ai 吴恩达 神经网络和深度学习 第一课 第二周 编程作业 Python Basics with Numpy
- 给深度学习入门者的Python快速教程 - numpy和Matplotlib篇
- python科学计算_numpy_线性代数/掩码数组/内存映射数组
- python科学计算_numpy_简单的多项式应用
- 记录ubuntu安装python科学计算工具包numpy
- python科学计算_numpy_ufunc
- Python画图库 matplotlib, 数值计算库 numpy, 科学计算库 scipy 的安装
- python科学计算学习二:matplotlib绘图(极坐标 3D绘图等)(3)
- python科学计算学习二:matplotlib绘图,图标注释(2)
- 【Python学习笔记 】10.Numpy科学计算库(下)
- python 科学计算学习一:numpy快速处理数据(3)
- python科学计算之numpy+pandas+matplotlib+mysql
- 神经网络与深度学习第二周-1- Python Basics With Numpy