Python 機器學習庫 NumPy

來源:互聯網
上載者:User
在我們使用Python語言進行機器學習編程的時候,這是一個非常常用的基礎庫。本文針對Python 機器學習庫 NumPy入門教程,感興趣的朋友一起學習吧

NumPy是一個Python語言的軟體包,它非常適合於科學計算。在我們使用Python語言進行機器學習編程的時候,這是一個非常常用的基礎庫。

本文是對它的一個入門教程。

介紹

NumPy是一個用於科技計算的基礎軟體包,它是Python語言實現的。它包含了:

  • 強大的N維數組結構

  • 精密複雜的函數

  • 可整合到C/C++和Fortran代碼的工具

  • 線性代數,傅裡葉變換以及隨機數能力

除了科學計算的用途以外,NumPy也可被用作高效的通用資料的多維容器。由於它適用於任意類型的資料,這使得NumPy可以無縫和高效的整合到多種類型的資料庫中。

擷取NumPy

由於這是一個Python語言的軟體包,因此需要你的機器上首先需要具備Python語言的環境。關於這一點,請自行在網路上搜尋擷取方法。

關於如何擷取NumPy也請參閱scipy.org官網上的Installing packages。本文不再贅述。

筆者推薦使用pip的方式安裝Python包,命令如下:


pip3 install numpy


本文的代碼在如下的環境中驗證和測試:

  • 硬體:MacBook Pro 2015

  • OS:macOS High Sierra

  • 語言環境:Python 3.6.2

  • 軟體包:numpy 1.13.3

可以在這裡擷取到本文的所有源碼:https://github.com/paulQuei/numpy_tutorial

另外,

  • 為了簡單起見,本文我們會通過Python的print函數來進行結果的驗證

  • 為了拼字方便,我們會預設import numpy as np

基礎屬性與數組建立

NumPy的基礎是一個同構的多維資料,數組中的元素可以通過下標來索引。在NumPy中,維度稱之為axis(複數是axes),維度數量稱之為rank。

例如:

下面是一個具有rank 1的數組,axis的長度為3:

[1, 2, 3]

下面是一個具有rank 2的數組,axis的長度也是3:

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

我們可以通過array函數來建立NumPy的數組,例如這樣:


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


請注意,這裡方括弧是必須的,下面這種寫法是錯誤的:


a = np.array(1,2,3,4) # WRONG!!!


NumPy的數組類是ndarray,它有一個別名是 numpy.array,但這與Python標準庫的array.array並不一樣。後者僅僅是一個一維數組。而ndarray具有以下的屬性:

  • ndarray.ndim:數組的維數。在Python世界中,維數稱之為rank

  • ndarray.shape:數組的維度。這是一系列數字,長度由數組的維度(ndim)決定。例如:長度為n的一維數組的shape是n。一個n行m列的矩陣的shape是n,m

  • ndarray.size:數組中所有元素的數量

  • ndarray.dtype:數組中元素的類型,例如numpy.int32, numpy.int16或者numpy.float64

  • ndarray.itemsize:數組中每個元素的大小,單位為位元組

  • ndarray.data:儲存數組元素的緩衝。通常我們只需要通過下標來訪問元素,而不需要訪問緩衝

下面我們來看一下程式碼範例:


# create_array.pyimport numpy as npa = np.array([1, 2, 3])b = np.array([(1,2,3), (4,5,6)])print('a=')print(a)print("a's ndim {}".format(a.ndim))print("a's shape {}".format(a.shape))print("a's size {}".format(a.size))print("a's dtype {}".format(a.dtype))print("a's itemsize {}".format(a.itemsize))print('')print('b=')print(b)print("b's ndim {}".format(b.ndim))print("b's shape {}".format(b.shape))print("b's size {}".format(b.size))print("b's dtype {}".format(b.dtype))print("b's itemsize {}".format(b.itemsize))


下面是這段代碼的輸出:


a=[1 2 3]a's ndim 1a's shape (3,)a's size 3a's dtype int64a's itemsize 8b=[[1 2 3] [4 5 6]]b's ndim 2b's shape (2, 3)b's size 6b's dtype int64b's itemsize 8


我們也可以在建立數組的時候,指定元素的類型,例如這樣:


c = np.array( [ [1,2], [3,4] ], dtype=complex )



關於array函數的更多參數說明,請參見這裡:numpy.array

註:NumPy本身支援多維陣列,也支援各種類型元素的資料。但考慮到,三維及以上的數組結構並不容易理解,而且我們在進行機器學習編程的時候,用的最多的是矩陣運算。因此,本文接下來的例子主要以一維和二維數字型數組來進行樣本說明。

特定array的建立

在實際上的項目工程中,我們常常會需要一些特定的資料,NumPy中提供了這麼一些輔助函數:

  • zeros:用來建立元素全部是0的數組

  • ones:用來建立元素全部是1的數組

  • empty:用來建立未初始化的資料,因此是內容是不確定的

  • arange:通過指定範圍和步長來建立數組

  • linespace:通過指定範圍和元素數量來建立數組

  • random:用來產生隨機數


# create_specific_array.pyimport numpy as npa = np.zeros((2,3))print('np.zeros((2,3)= \n{}\n'.format(a))b = np.ones((2,3))print('np.ones((2,3))= \n{}\n'.format(b))c = np.empty((2,3))print('np.empty((2,3))= \n{}\n'.format(c))d = np.arange(1, 2, 0.3)print('np.arange(1, 2, 0.3)= \n{}\n'.format(d))e = np.linspace(1, 2, 7)print('np.linspace(1, 2, 7)= \n{}\n'.format(e))f = np.random.random((2,3))print('np.random.random((2,3))= \n{}\n'.format(f))


這段代碼的輸出如下


np.zeros((2,3)= [[ 0. 0. 0.] [ 0. 0. 0.]]np.ones((2,3))= [[ 1. 1. 1.] [ 1. 1. 1.]]np.empty((2,3))= [[ 1. 1. 1.] [ 1. 1. 1.]]np.arange(1, 2, 0.3)= [ 1. 1.3 1.6 1.9]np.linspace(1, 2, 7)= [ 1.  1.16666667 1.33333333 1.5  1.66666667 1.83333333 2. ]np.random.random((2,3))= [[ 0.5744616 0.58700653 0.59609648] [ 0.0417809 0.23810732 0.38372978]]


Shape與操作

除了產生數組之外,當我們已經持有某個資料之後,我們可能會需要根據已有數組來產生一些新的資料結構,這時候我們可以使用下面這些函數:

  • reshape:根據已有數組和指定的shape,產生一個新的數組

  • vstack:用來將多個數組在垂直(v代表vertical)方向拼接(數組的維度必須匹配)

  • hstack:用來將多個數組在水平(h代表horizontal)方向拼接(數組的維度必須匹配)

  • hsplit:用來將數組在水平方向拆分

  • vsplit:用來將數組在垂直方向拆分

下面我們通過一些例子來進行說明。

為了便於測試,我們先建立幾個資料。這裡我們建立了:

  • zero_line:一行包含3個0的數組

  • one_column:一列包含3個1的數組

  • a:一個2行3列的矩陣

  • b:[11, 20)區間的整數數組


# shape_manipulation.pyzero_line = np.zeros((1,3))one_column = np.ones((3,1))print("zero_line = \n{}\n".format(zero_line))print("one_column = \n{}\n".format(one_column))a = np.array([(1,2,3), (4,5,6)])b = np.arange(11, 20)print("a = \n{}\n".format(a))print("b = \n{}\n".format(b))


通過輸出我們可以看到它們的結構:


zero_line = [[ 0. 0. 0.]]one_column = [[ 1.] [ 1.] [ 1.]]a = [[1 2 3] [4 5 6]]b = [11 12 13 14 15 16 17 18 19]


數組b原先是一個一維數組,現在我們通過reshape方法將其調整成為一個3行3列的矩陣:


# shape_manipulation.pyb = b.reshape(3, -1)print("b.reshape(3, -1) = \n{}\n".format(b))


這裡的第二參數設為-1,表示根據實際情況自動決定。由於原先是9個元素的數組,因此調整後剛好是3X3的矩陣。這段代碼輸出如下:


b.reshape(3, -1) = [[11 12 13] [14 15 16] [17 18 19]]


接著,我們通過vstack函數,將三個數組在垂直方向拼接:


# shape_manipulation.pyc = np.vstack((a, b, zero_line))print("c = np.vstack((a,b, zero_line)) = \n{}\n".format(c))



這段代碼輸出如下,請讀者仔細觀察一下拼接前後的資料結構:


c = np.vstack((a,b, zero_line)) = [[ 1. 2. 3.] [ 4. 5. 6.] [ 11. 12. 13.] [ 14. 15. 16.] [ 17. 18. 19.] [ 0. 0. 0.]]


同樣的,我們也可以通過hstack進行水平方向的拼接。為了可以拼接我們需要先將數組a調整一下結構:


# shape_manipulation.pya = a.reshape(3, 2)print("a.reshape(3, 2) = \n{}\n".format(a))d = np.hstack((a, b, one_column))print("d = np.hstack((a,b, one_column)) = \n{}\n".format(d))


這段代碼輸出如下,請再次仔細觀察拼接前後的資料結構:


a.reshape(3, 2) = [[1 2] [3 4] [5 6]]d = np.hstack((a,b, one_column)) = [[ 1.  2. 11. 12. 13.  1.] [ 3.  4. 14. 15. 16.  1.] [ 5.  6. 17. 18. 19.  1.]]


請注意,如果兩個數組的結構是不相容的,拼接將無法完成。例如下面這行代碼,它將無法執行:


# shape_manipulation.py# np.vstack((a,b)) # ValueError: dimensions not match


這是因為數組a具有兩列,而數組b具有3列,所以它們無法拼接。

接下來我們再看一下拆分。首先,我們將數組d在水平方向拆分成3個數組。然後我們將中間一個(下標是1)數組列印出來:


# shape_manipulation.pye = np.hsplit(d, 3) # Split a into 3print("e = np.hsplit(d, 3) = \n{}\n".format(e))print("e[1] = \n{}\n".format(e[1]))


這段代碼輸出如下:


e = np.hsplit(d, 3) = [array([[ 1., 2.],    [ 3., 4.],    [ 5., 6.]]), array([[ 11., 12.],    [ 14., 15.],    [ 17., 18.]]), array([[ 13.,  1.],    [ 16.,  1.],    [ 19.,  1.]])]e[1] = [[ 11. 12.] [ 14. 15.] [ 17. 18.]]


另外,假設我們設定的拆分數量使得原先的數組無法平均拆分,則操作會失敗:


# np.hsplit(d, 4) # ValueError: array split does not result in an equal pision



除了指定數量平均拆分,我們也可以指定列數進行拆分。下面是將數組d從第1列和第3列兩個地方進行拆分:



# shape_manipulation.pyf = np.hsplit(d, (1, 3)) # # Split a after the 1st and the 3rd columnprint("f = np.hsplit(d, (1, 3)) = \n{}\n".format(f))


這段代碼輸出如下。數組d被拆分成了分別包含1,2,3列的三個數組:


f = np.hsplit(d, (1, 3)) = [array([[ 1.],    [ 3.],    [ 5.]]), array([[ 2., 11.],    [ 4., 14.],    [ 6., 17.]]), array([[ 12., 13.,  1.],    [ 15., 16.,  1.],    [ 18., 19.,  1.]])]


最後我們再將數組d在垂直方向進行拆分。同樣的,如果指定的拆分數無法平均拆分則會失敗:


# shape_manipulation.pyg = np.vsplit(d, 3)print("np.hsplit(d, 2) = \n{}\n".format(g))# np.vsplit(d, 2) # ValueError: array split does not result in an equal pisionnp.vsplit(d, 3)將產生三個一維數組:np.vsplit(d, 3) = [array([[ 1.,  2., 11., 12., 13.,  1.]]), array([[ 3.,  4., 14., 15., 16.,  1.]]), array([[ 5.,  6., 17., 18., 19.,  1.]])]


索引

接下來我們看看如何訪問NumPy數組中的資料。

同樣的,為了測試方便,我們先建立一個一維數組。它的內容是 [100,200)區間的整數。

最基本的,我們可以通過array[index]的方式指定下標來訪問數組的元素,這一點對於有一點編程經驗的人來說應該都是很熟悉的。


# array_index.pyimport numpy as npbase_data = np.arange(100, 200)print("base_data\n={}\n".format(base_data))print("base_data[10] = {}\n".format(base_data[10]))


上面這段代碼輸出如下:


base_data=[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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199]base_data[10] = 110


在NumPy中,我們可以建立一個包含了若干個下標的數組來擷取目標數組中的元素。如下所示:


# array_index.pyevery_five = np.arange(0, 100, 5)print("base_data[every_five] = \n{}\n".format(  base_data[every_five]))


every_five是包含了我們要擷取的下標的數組,它的內容大家應該很容易理解。我們可以直接通過方括弧的形式來擷取到所有我們指定了下標的元素,它們如下:


base_data[every_five] = [100 105 110 115 120 125 130 135 140 145 150 155 160 165 170 175 180 185 190 195]


下標數組可以是一維的,當然也可以是多維的。假設我們要擷取一個2X2的矩陣,這個矩陣的內容來自於目標數組中1,2,10,20這四個下標的元素,則可以這樣寫:


# array_index.pya = np.array([(1,2), (10,20)])print("a = \n{}\n".format(a))print("base_data[a] = \n{}\n".format(base_data[a]))


這段代碼輸出如下:


a = [[ 1 2] [10 20]]base_data[a] = [[101 102] [110 120]]


上面我們看到的是目標數組是一維的情況,下面我們把這個數群組轉換成一個10X10的二維數組。


# array_index.pybase_data2 = base_data.reshape(10, -1)print("base_data2 = np.reshape(base_data, (10, -1)) = \n{}\n".format(base_data2))


reshape函數前面已經介紹過,大家應該能夠想到它的結果:


base_data2 = np.reshape(base_data, (10, -1)) = [[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 134 135 136 137 138 139] [140 141 142 143 144 145 146 147 148 149] [150 151 152 153 154 155 156 157 158 159] [160 161 162 163 164 165 166 167 168 169] [170 171 172 173 174 175 176 177 178 179] [180 181 182 183 184 185 186 187 188 189] [190 191 192 193 194 195 196 197 198 199]]


對於二維數組來說:

  • 假設我們只指定了一個下標,則訪問的結果仍然是一個數組。

  • 假設我們指定了兩個下標,則訪問得到的是其中的元素


我們也可以通過”-1”來指定“最後一個”的元素


# array_index.pyprint("base_data2[2] = \n{}\n".format(base_data2[2]))print("base_data2[2, 3] = \n{}\n".format(base_data2[2, 3]))print("base_data2[-1, -1] = \n{}\n".format(base_data2[-1, -1]))


這段代碼輸出如下。

對於更高維的數組,原理是一樣的,讀者可以自行推理。


base_data2[2] = [120 121 122 123 124 125 126 127 128 129]base_data2[2, 3] = 123base_data2[-1, -1] = 199


除此之外,我們還可以通過”:“的形式來指定範圍,例如:2:5 這樣。唯寫”:“則表示全部範圍。

請看下面這段代碼:


# array_index.pyprint("base_data2[2, :]] = \n{}\n".format(base_data2[2, :]))print("base_data2[:, 3]] = \n{}\n".format(base_data2[:, 3]))print("base_data2[2:5, 2:4]] = \n{}\n".format(base_data2[2:5, 2:4]))



它的含義是:

  • 擷取下標為2的行的所有元素

  • 擷取下標為3的列的所有元素

擷取下標為[2,5)行,下標為[2,4)列的所有元素。請讀者仔細觀察一下下面的輸出結果:


base_data2[2, :]] = [120 121 122 123 124 125 126 127 128 129]base_data2[:, 3]] = [103 113 123 133 143 153 163 173 183 193]base_data2[2:5, 2:4]] = [[122 123] [132 133] [142 143]]



數學運算

NumPy中自然也少不了大量的數學運算函數,下面是一些例子,更多的函數請參見這裡NumPy manual contents:


# operation.pyimport numpy as npbase_data = (np.random.random((5, 5)) - 0.5) * 100print("base_data = \n{}\n".format(base_data))print("np.amin(base_data) = {}".format(np.amin(base_data)))print("np.amax(base_data) = {}".format(np.amax(base_data)))print("np.average(base_data) = {}".format(np.average(base_data)))print("np.sum(base_data) = {}".format(np.sum(base_data)))print("np.sin(base_data) = \n{}".format(np.sin(base_data)))



這段代碼輸出如下:


base_data = [[ -9.63895991 6.9292461 -2.35654712 -48.45969283 13.56031937] [-39.75875796 -43.21031705 -49.27708561 6.80357128 33.71975059] [ 36.32228175 30.92546582 -41.63728955 28.68799187 6.44818484] [ 7.71568596 43.24884701 -14.90716555 -9.24092252 3.69738718] [-31.90994273 34.06067289 18.47830413 -16.02495202 -44.84625246]]np.amin(base_data) = -49.277085606595726np.amax(base_data) = 43.24884701268845np.average(base_data) = -3.22680706079886np.sum(base_data) = -80.6701765199715np.sin(base_data) = [[ 0.21254814 0.60204578 -0.70685739 0.9725159 0.8381861 ] [-0.88287359 0.69755541 0.83514527 0.49721505 0.74315189] [-0.98124746 -0.47103234 0.7149727 -0.40196147 0.16425187] [ 0.99045239 -0.66943662 -0.71791164 -0.18282139 -0.5276184 ] [-0.4741657 0.47665553 -0.36278223 0.31170676 -0.76041722]]


矩陣

接下來我們看一下以矩陣的方式使用NumPy。

首先,我們建立一個5X5的隨機數整數矩陣。有兩種方式可以獲得矩陣的轉置:通過.T或者transpose函數。另外, 通過dot函數可以進行矩陣的乘法,範例程式碼如下:


# matrix.pyimport numpy as npbase_data = np.floor((np.random.random((5, 5)) - 0.5) * 100)print("base_data = \n{}\n".format(base_data))print("base_data.T = \n{}\n".format(base_data.T))print("base_data.transpose() = \n{}\n".format(base_data.transpose()))matrix_one = np.ones((5, 5))print("matrix_one = \n{}\n".format(matrix_one))minus_one = np.dot(matrix_one, -1)print("minus_one = \n{}\n".format(minus_one))print("np.dot(base_data, minus_one) = \n{}\n".format( np.dot(base_data, minus_one)))這段代碼輸出如下:base_data = [[-49. -5. 11. -13. -41.] [ -6. -33. -33. -47. -4.] [-38. 26. 28. -18. 18.] [ -3. -19. -15. -39. 45.] [-43. 6. 18. -15. -21.]]base_data.T = [[-49. -6. -38. -3. -43.] [ -5. -33. 26. -19. 6.] [ 11. -33. 28. -15. 18.] [-13. -47. -18. -39. -15.] [-41. -4. 18. 45. -21.]]base_data.transpose() = [[-49. -6. -38. -3. -43.] [ -5. -33. 26. -19. 6.] [ 11. -33. 28. -15. 18.] [-13. -47. -18. -39. -15.] [-41. -4. 18. 45. -21.]]matrix_one = [[ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1.]]minus_one = [[-1. -1. -1. -1. -1.] [-1. -1. -1. -1. -1.] [-1. -1. -1. -1. -1.] [-1. -1. -1. -1. -1.] [-1. -1. -1. -1. -1.]]np.dot(base_data, minus_one) = [[ 97. 97. 97. 97. 97.] [ 123. 123. 123. 123. 123.] [ -16. -16. -16. -16. -16.] [ 31. 31. 31. 31. 31.] [ 55. 55. 55. 55. 55.]]



隨機數

本文的最後,我們來看一下隨機數的使用。

隨機數是我們在編程過程中非常頻繁用到的一個功能。例如:產生示範資料,或者將已有的資料順序隨機打亂以便分割出建模資料和驗證資料。

numpy.random 包中包含了很多中隨機數的演算法。下面我們列舉四種最常見的用法:


# rand.pyimport numpy as npprint("random: {}\n".format(np.random.random(20)));print("rand: {}\n".format(np.random.rand(3, 4)));print("randint: {}\n".format(np.random.randint(0, 100, 20)));print("permutation: {}\n".format(np.random.permutation(np.arange(20))));


在四種用法分別是:

  1. 產生20個隨機數,它們每一個都是[0.0, 1.0)之間

  2. 根據指定的shape產生隨機數

  3. 產生指定範圍內([0, 100))的指定數量(20)的隨機整數

  4. 對已有的資料([0, 1, 2, ..., 19])的順序隨機打亂順序

這段代碼的輸出如下所示:


random: [0.62956026 0.56816277 0.30903156 0.50427765 0.92117724 0.43044905 0.54591323 0.47286235 0.93241333 0.32636472 0.14692983 0.02163887 0.85014782 0.20164791 0.76556972 0.15137427 0.14626625 0.60972522 0.2995841 0.27569573]rand: [[0.38629927 0.43779617 0.96276889 0.80018417] [0.67656892 0.97189483 0.13323458 0.90663724] [0.99440473 0.85197677 0.9420241 0.79598706]]randint: [74 65 51 34 22 69 81 36 73 35 98 26 41 84 0 93 41 6 51 55]permutation: [15 3 8 18 14 19 16 1 0 4 10 17 5 2 6 12 9 11 13 7]
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.