《scikit-learn机器学习常用算法原理及编程实战》—2.3 Numpy简介

举报
华章计算机 发表于 2019/05/31 16:13:01 2019/05/31
【摘要】 本书摘自《scikit-learn机器学习常用算法原理及编程实战》一书中的第2章,第2.3.1节,编著是黄永昌 .

2.3  Numpy简介

  Numpy是Python科学计算的基础库,主要提供了高性能的N维数组实现以及计算能力,还提供了和其他语言如C/C++集成的能力,此外还实现了一些基础的数学算法,如线性代数相关、傅里叶变换及随机数生成等。

2.3.1  Numpy数组

  可以直接用Python列表来创建数组。

  

  In [1]: import numpy as np

  

  In [2]: a = np.array([1,2,3,4])

  

  In [3]: a

  Out[3]: array([1, 2, 3, 4])

  

  In [4]: b = np.array([[1, 2], [3, 4], [5, 6]])

  

  In [5]: b

  Out[5]:

  array([[1, 2],

          [3, 4],

        [5, 6]])

  

  可以查看array的属性,包括数据的维度和类型。

  

  In [6]: b.ndim

  Out[6]: 2

  

  In [7]: b.shape

  Out[7]: (3, 2)

  

  In [8]: b.dtype                        # 查看数组里元素的数据类型

  Out[8]: dtype('int32')

  

  也可以使用Numpy提供的函数来创建数组。

  

  In [6]: c = np.arange(10)                # 创建连续数组

  

  In [9]: c

  Out[9]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

  

  In [10]: d = np.linspace(0, 2, 11)        # [0, 2] 分成 11 等分后的数组

  

  In [11]: d

  Out[11]: array([ 0. , 0.2, 0.4, 0.6, 0.8,  1. , 1.2, 1.4, 1.6, 1.8, 2. ])

  

  In [12]: np.ones((3, 3))                # 注意参数两边的括号,参数是个元组

  Out[12]:

  array([[ 1.,  1.,  1.],

         [ 1.,  1.,  1.],

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

  

  

  

  In [13]: np.zeros((3, 6))

  Out[13]:

  array([[ 0.,  0.,  0.,  0.,  0.,  0.],

         [ 0.,  0.,  0.,  0.,  0.,  0.],

         [ 0.,  0.,  0.,  0.,  0.,  0.]])

  

  

  In [14]: np.eye(4)

  Out[14]:

  array([[ 1.,  0.,  0.,  0.],

         [ 0.,  1.,  0.,  0.],

         [ 0.,  0.,  1.,  0.],

         [ 0.,  0.,  0.,  1.]])

  

  In [17]: np.random.randn(6, 4)          # 创建6×4的随机数组

  Out[17]:

  array([[-0.49815866, -0.34571599, -0.44144955,  0.28833876],

         [ 1.48639293, -0.56259401, -0.32584788,  0.39799156],

         [ 1.35458161, -1.21808153, -0.17011994,  0.95870198],

         [-1.36688808,  0.75892299, -1.25336314, -1.12267624],

         [-2.24057506, -0.25099611,  1.6995657 , -0.14504619],

         [ 0.52316692, -1.55100505,  0.65085791, -1.45710045]])

  

  Numpy提供了灵活的索引机制来访问数组内的元素。

  

  In [23]: a = np.arange(10)

  

  In [24]: a

  Out[24]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

  

  In [25]: a[0], a[3], a[-1]

  Out[25]: (0, 3, 9)

  

  In [26]: a[:4]                      # 半开闭区间,不包含最后一个元素

  Out[26]: array([0, 1, 2, 3])

  

  In [27]: a[3:7]

  Out[27]: array([3, 4, 5, 6])

  

  In [28]: a[6:]

  Out[28]: array([6, 7, 8, 9])

  

  In [29]: a[2:8:2]                # 3个参数表示起始、结束和步长,不包含结束位置

  Out[29]: array([2, 4, 6])

  

  In [30]: a[2::2]                  # 结束位置可以省略

  Out[30]: array([2, 4, 6, 8])

  

  In [31]: a[::3]                  # 开始和结束都省略

  Out[31]: array([0, 3, 6, 9])

  

  二维数据的索引分成行和列两个维度,会更灵活一些。

  

  # 创建一个6行6列的二维数据,使用了广播机制,后文介绍

  In [32]: a = np.arange(0, 51, 10).reshape(6, 1) + np.arange(6)

  

  In [33]: a

  Out[33]:

  array([[ 0,  1,  2,  3,  4,  5],

        [10, 11, 12, 13, 14, 15],

        [20, 21, 22, 23, 24, 25],

        [30, 31, 32, 33, 34, 35],

        [40, 41, 42, 43, 44, 45],

        [50, 51, 52, 53, 54, 55]])

  

  In [34]: a[0, 0], a[2, -1]

  Out[34]: (0, 25)

  

  In [35]: a[0, 2:5]

  Out[35]: array([2, 3, 4])

  

  In [36]: a[:3, 3:]

  Out[36]:

  array([[ 3,  4,  5],

        [13, 14, 15],

        [23, 24, 25]])

  

  In [37]: a[2, :]

  Out[37]: array([20, 21, 22, 23, 24, 25])

  

  In [38]: a[:, 3]    #结果应该是列向量,但 Numpy 自动转换行向量形式

  Out[38]: array([ 3, 13, 23, 33, 43, 53])

  

  In [39]: a[:, ::2]

  Out[39]:

  array([[ 0,  2,  4],

        [10, 12, 14],

        [20, 22, 24],

        [30, 32, 34],

        [40, 42, 44],

        [50, 52, 54]])

  

  In [40]: a[::2, ::3]

  Out[40]:

  array([[ 0,  3],

         [20, 23],

         [40, 43]])

  

  另外一个索引的方法是通过布尔数组。

  

  In [45]: a = np.random.randint(10, 20, 6) # 在 [10, 20] 之间产生 6 个随机数

  

  In [46]: a

  Out[46]: array([12, 11, 14, 11, 18, 19])

  

  In [47]: a % 2 == 0

  Out[47]: array([ True, False,  True, False,  True, False], dtype=bool)

  

  In [48]: a[a % 2 == 0]

  Out[48]: array([12, 14, 18])

  

  需要特别注意的是,Numpy总是试图自动地把结果转换为行向量,这一机制对熟悉MATLAB的读者来讲会觉得很别扭。比如下面的例子,对二维数组进行布尔索引时,结果变成了一个行向量:

  

  In [49]: a = np.arange(0, 51, 10).reshape(6, 1) + np.arange(6)

  

  In [50]: a

  Out[50]:

  array([[ 0,  1,  2,  3,  4,  5],

        [10, 11, 12, 13, 14, 15],

        [20, 21, 22, 23, 24, 25],

        [30, 31, 32, 33, 34, 35],

        [40, 41, 42, 43, 44, 45],

        [50, 51, 52, 53, 54, 55]])

  

  In [51]: a[a % 2 == 0]

  Out[51]:

  array([ 0,  2,  4, 10, 12, 14, 20, 22, 24, 30, 32, 34, 40, 42, 44, 50, 52,

         54])

  

  另外需要注意的是,在大部分情况下,Numpy数组是共享内存的,如果要独立保存,需要显式地备份。可以使用np.may_share_memory()函数来判断两个数组是否共享内存。

  

  In [52]: a = np.arange(6)

  

  In [53]: a

  Out[53]: array([0, 1, 2, 3, 4, 5])

  

  In [54]: b = a[2:5]

  

  In [55]: b

  Out[55]: array([2, 3, 4])

  

  In [56]: b[1] = 100

  

  In [57]: b

  Out[57]: array([  2, 100,   4])

  

  In [58]: a                      # 数组 a 的值也改变了

  Out[58]: array([  0,   1,   2, 100,   4,   5])

  

  In [59]: np.may_share_memory(a, b)

  Out[59]: True

  

  In [60]: b = a[2:6].copy()      # 显式地备份

  

  In [61]: b

  Out[61]: array([  2, 100,   4,   5])

  

  In [62]: b[1] = 3

  

  In [63]: b

  Out[63]: array([2, 3, 4, 5])

  

  In [64]: a                      # a 数组的值没有改变

  Out[64]: array([  0,   1,   2, 100,   4,   5])

  

  In [65]: np.may_share_memory(a, b)

  Out[65]: False

  

  作为一个有趣的例子,我们使用埃拉托斯特尼筛法(Sieve of Eratosthenes)来打印出 [0, 100]之间的所有质数。维基百科页面en.wikipedia.org/wiki/Sieve_of_Eratosthenes上有个动画图片清楚地展示了算法原理。其主要思路是,从第一个质数 2 开始,数据里所有能被2整除的数字都不是质数,即从2开始、以2为步长,每跳经过的数字都能被2整除,把其标识为非质数。接着,从下一个质数3开始,重复上述过程。最终即可算出[1, 100]之间的所有质数。

  

  import numpy as np

  

  a = np.arange(1, 101)

  n_max = int(np.sqrt(len(a)))

  is_prime = np.ones(len(a), dtype=bool) # 创建100个元素的数组,用来标记是否为质数

  is_prime[0] = False

  

  for i in range(2,n_max):

      if i in a[is_prime]:                  # 跳过非质数

          is_prime[(i**2 - 1)::i] = False # 减 1 是为了修复从 0 开始索引的问题

  

  print a[is_prime]

  

  最终输出的结果是:

  

   [ 2  3  5  7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。