《scikit-learn機器學習常用算法原理及編程實戰》—2.3 Numpy簡介
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]
機器學習 scikit-learn
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。