[人工智能]NumPy基礎

理解NumPy

本文主要介紹NumPy的基礎知識,NumPy是一個功能強大的Python庫,容許更高級的數據操做和數學計算。html

什麼是NumPy

NumPy,來源自兩個單詞:Numerical和Python,是一個強大的Python庫,主要用於多維數組的執行計算。它很是重視數組,容許你在Python中進行向量和矩陣計算,其許多底層函數是由C編寫的。NumPy提供了大量的庫函數和操做,能夠輕鬆地進行數值計算,這類數字計算普遍用於如下任務:python

  • 機器學習模型:在編寫機器學習算法時,須要對矩陣進行各類數值計算,例如矩陣乘法、換位、加法等。NumPy提供了一個很是好的庫,用於簡單(在編寫代碼方面)和快速(在速度方面)計算。NumPy數組用於存儲訓練數據和機器學習模型的參數。
  • 圖像處理和計算機圖形學:計算機中的圖像表示爲多維數組。NumPy成爲一樣狀況下最天然的選擇。實際上,NumPy提供了一些優秀的庫函數來快速處理圖像,例如鏡像圖像、按特定角度旋轉圖像等。
  • 數學任務:NumPy對於執行各類數學任務很是有用,如數值積分、微分、內插、外推等,所以當涉及到數學任務是,它造成了一種基於Python的MATLIB的快速替代。

安裝

這裏使用pip的方式進行安裝。算法

pip3 install numpy

NumPy數組

NumPy庫的核心是數組對象或ndarray對象(n維數組)。使用NumPy數組,能夠進行邏輯、統計和傅里葉變換等運算。建立NumPy數組有如下三種不一樣方式:數組

  1. 使用NumPy內部功能函數
  2. 從列表等其餘Python的結構進行轉換
  3. 使用特殊的庫函數

使用NumPy內部功能函數

Nump提供了用於建立數組的內置函數。bash

建立一個一維的數組

首先,建立一維數組或rank爲1的數組。arange是一種普遍使用的函數,用於快速建立數組:將數值num傳入arange函數,將會建立一個值範圍爲0到num的數組。dom

import Numpy as np

a = np.arange(20)
a

輸出以下:機器學習

array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])

能夠是用shape屬性驗證此數組的維度:ide

In [11]: a.shape                                   
Out[11]: (20,)

建立一個二維數組

若是隻是arange函數,它將輸出一個一維數組,要使其成爲一個二維數組,可使用reshape函數連接其輸出:函數

# 首先建立20個整數,而後將數組轉換成4行5列的二維數組
In [12]: a = np.arange(20).reshape(4,5)              

In [13]: a                                  
Out[13]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
# 檢查下數組的維度
In [14]: a.shape                                    
Out[14]: (4, 5)

建立三維數組及更多維度

要建立三維數組,那麼須要爲reshape函數指定3個參數。學習

# 注意,此時數組中元素的數量(27)必須是尺寸(3,3,3)的乘積
In [15]: a = np.arange(27).reshape(3,3,3)            

In [16]: a                                           
Out[16]: 
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],
        [24, 25, 26]]])

# 檢查數組的維度
In [17]: a.shape                                       
Out[17]: (3, 3, 3)

使用其餘NumPy函數

除了arange函數以外,還可使用其餘有用的函數,例如zerosones,來快速建立和填充數組。

使用zeros函數建立一個填充爲零的數組,其參數表示行數和列數(或其維數)。

In [18]: np.zeros((2,4))                             
Out[18]: 
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.]])

使用ones函數建立一個填充爲1的數組:

In [19]: np.ones((3,4))                              
Out[19]: 
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])

empty函數建立一個數組,其初始內容是隨機的,取決於內存的狀態:

In [20]: np.empty((5,6))                              
Out[20]: 
array([[-2.31584178e+077, -2.00389912e+000,  2.30561760e-314,
         2.30789649e-314,  2.30702697e-314,  2.30772173e-314],
       [ 2.30796369e-314,  2.23928337e-314,  2.23928347e-314,
         2.30792536e-314,  2.23798476e-314,  2.30569256e-314],
       [-2.31584178e+077,  3.11108964e+231,  4.44659081e-323,
         0.00000000e+000, -0.00000000e+000,  0.00000000e+000],
       [ 5.45352918e-312,  4.94065646e-324,  4.94065646e-324,
         0.00000000e+000,  1.77229088e-310,  2.30690648e-314],
       [ 0.00000000e+000,  0.00000000e+000,  0.00000000e+000,
         2.30690648e-314,  2.30690648e-314,  2.08600674e-308]])

full函數建立一個填充給定值得n*n數組:

In [21]: np.full((5,5),6)                              
Out[21]: 
array([[6, 6, 6, 6, 6],
       [6, 6, 6, 6, 6],
       [6, 6, 6, 6, 6],
       [6, 6, 6, 6, 6],
       [6, 6, 6, 6, 6]])

eye函數建立一個n*n矩陣,其對角線爲1,其他爲0:

In [22]: np.eye(3,3)                                 
Out[22]: 
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

linspace函數在指定的時間間隔內返回均勻間隔的數組:

In [24]: np.linspace(0,20,num=5)                            
Out[24]: array([ 0.,  5., 10., 15., 20.])

從Python列表轉換

建立一維數組

除了使用NumPy函數以外,還能夠直接從Python列表建立數組:將Python列表傳遞給數組函數以建立NumPy數組:

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

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

還能夠建立Python列表並傳遞其變量名以建立NumPy數組:

In [27]: l = [4,5,6]

In [28]: l
Out[28]: [4, 5, 6]

In [29]: a = np.array(l)

In [30]: a
Out[30]: array([4, 5, 6])

建立二維數組

要建立二維數組,能夠將一系列列表傳遞給數組函數:

In [31]: a = np.array([(1,2,3),(4,5,6)])                      
                                                       
In [32]: a
Out[32]: 
array([[1, 2, 3],
       [4, 5, 6]])

In [33]: a.shape
Out[33]: (2, 3)

使用特殊的庫函數

除了上述的兩種方式以外,還可使用特殊庫函數來建立數組。例如,要建立一個填充0到1之間隨機值得數組,可使用rando函數,這對於須要隨機狀態才能開始的問題特別有用。

In [34]: np.random.random((2,4))
Out[34]: 
array([[0.41392644, 0.21315258, 0.43934646, 0.46239945],
       [0.84670981, 0.81019245, 0.57370054, 0.74415838]])

數組索引

NumPy提供了幾種索引數組的方法。

  • 切片(Slicing):與Python列表相似,能夠對numpy數組進行切片,因爲數組多是多維的,所以必須爲數組的每一維指定一個切片:
In [1]: import numpy as np

In [2]: a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]]) 

In [3]: b = a[:2,1:3]

In [4]: b
Out[4]: 
array([[2, 3],
       [6, 7]])

In [6]: a[0,1]
Out[6]: 2

In [7]: b[0,0] = 77

In [8]: a[0,1]
Out[8]: 77

還能夠將整數索引與切片索引混合使用,但這樣會產生比原始數組更低級別的數組。

  • 整數數組索引:使用切片索引到numpy數組時,生成的數組始終是原始數組的子數組;使用整數數組索引容許你使用另外一個數組中的數據構造任意數組。整數數組索引能夠從矩陣的每一行中選擇或改變一個元素。

  • 布爾數組索引:布爾數組索引容許你選擇數組的任意元素。一般,這種類型的索引用於選擇知足某些條件的數組元素。

數據類型

每一個numpy數組都是相同類型元素的網格。NumP提供了一組可用於構造數組的大量數值數據類型:NumPy在建立數組是嘗試猜想數據類型,到構造數組的函數一般還包含一個可選參數來顯示指定數據類型。

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

In [10]: a.dtype
Out[10]: dtype('int64')

In [11]: a = np.array([1.0,2.0])

In [12]: a.dtype
Out[12]: dtype('float64')

In [13]: a = np.array([1,2],dtype=np.int64)

In [14]: a.dtype                          
Out[14]: dtype('int64')

數組中的數學

基本數學函數在數組上以屬性的方式運行,既能夠做爲運算符重載,也能夠做爲numpy模塊的函數:

In [16]: x = np.array([[1,2],[3,4]],dtype=np.float64)

In [17]: y = np.array([[5,6],[7,8]],dtype=np.float64)

In [18]: x+y
Out[18]:
array([[ 6.,  8.],
       [10., 12.]])

In [19]: np.add(x,y)
Out[19]:
array([[ 6.,  8.],
       [10., 12.]])

In [20]: x-y
Out[20]:
array([[-4., -4.],
       [-4., -4.]])

In [21]: np.subtract(x,y)
Out[21]:
array([[-4., -4.],
       [-4., -4.]])

# * 是元素乘法,不是矩陣乘法
In [22]: x*y
Out[22]:
array([[ 5., 12.],
       [21., 32.]])

In [23]: np.multiply(x,y)
Out[23]:
array([[ 5., 12.],
       [21., 32.]])

In [24]: x/y
Out[24]:
array([[0.2       , 0.33333333],
       [0.42857143, 0.5       ]])

In [25]: np.divide(x,y)
Out[25]:
array([[0.2       , 0.33333333],
       [0.42857143, 0.5       ]])

In [26]: np.sqrt(x)
Out[26]:
array([[1.        , 1.41421356],
       [1.73205081, 2.        ]])

# 使用 dot函數計算向量的內積。dot既能夠做爲numpy模塊中的函數,也可做爲數組對象的實例方法
In [27]: x.dot(y)
Out[27]:
array([[19., 22.],
       [43., 50.]])

In [28]: np.dot(x,y)
Out[28]:
array([[19., 22.],
       [43., 50.]])

NumPy爲在數組上執行計算提供了許多有用的函數,其中最有用的函數之一是SUM

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

In [31]: np.sum(x)
Out[31]: 10

In [32]: np.sum(x,axis=0) 
Out[32]: array([4, 6])

In [33]: np.sum(x,axis=1)
Out[33]: array([3, 7])

除了使用數組計算數學函數外,咱們常常須要對數組中的數據進行整形或其餘操做,這種操做的最簡單的例子就是轉置一個矩陣。要轉置一個矩陣,只須要使用一個數組對象的T屬性:

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

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

In [35]: x.T
Out[35]:
array([[1, 3],
       [2, 4]])

除了上面提到的函數外,NumPy還提供了許多操做數組的函數,你能夠在這篇文檔中看到完整的列表。

廣播(Broadcasting)

廣播是一種強大的機制,它容許numpy在執行算術運算時使用不一樣形狀的數組。

將兩個數組一塊兒廣播遵循如下規則:

  1. 若是數組具備不一樣的rank,則將較低等級數組的形狀添加1,知道兩個形狀具備相同的長度。
  2. 若是兩個數組在維度上具備相同的大小,或者若是其中一個數組在該維度中的大小爲1,則稱這兩個數組在維度上是兼容的。
  3. 若是數組在全部維度上兼容,則能夠一塊兒廣播。
  4. 廣播以後,每一個陣列的行爲就好像它的形狀等於兩個輸入數組的形狀的元素最大值。
  5. 在一個數組的大小爲1且另外一個數組的大小大於1的任何維度中,第一個數組的行爲就像沿着該維度複製同樣。