1. 程式人生 > >Python NumPy學習

Python NumPy學習

  NumPy是Python語言的一個擴充程式庫。支援高階大量的維度陣列與矩陣運算,此外也針對陣列運算提供大量的數學函式庫。Numpy內部解除了Python的GIL(全域性直譯器鎖),執行效率極好,是大量機器學習框架的基礎庫!      關於GIL請參考部落格:http://www.cnblogs.com/wj-1314/p/9056555.html      NumPy的全名為Numeric Python,是一個開源的Python科學計算庫,它包括:      一個強大的N維陣列物件ndrray;      比較成熟的(廣播)函式庫;      用於整合C/C++和Fortran程式碼的工具包;      實用的線性代數、傅立葉變換和隨機數生成函式      1.1  NumPy的優點:      對於同樣的數值計算任務,使用NumPy要比直接編寫Python程式碼便捷得多;      NumPy中的陣列的儲存效率和輸入輸出效能均遠遠優於Python中等價的基本資料結構,且其能夠提升的效能是與陣列中的元素成比例的;      NumPy的大部分程式碼都是用C語言寫的,其底層演算法在設計時就有著優異的效能,這使得NumPy比純Python程式碼高效得多      當然,NumPy也有其不足之處,由於NumPy使用記憶體對映檔案以達到最優的資料讀寫效能,而記憶體的大小限制了其對TB級大檔案的處理;此外,NumPy陣列的通用性不及Python提供的list容器。因此,在科學計算之外的領域,NumPy的優勢也就不那麼明顯。      二、陣列ndarray      NumPy最重要的一個特點就是其N維陣列物件(即ndarray),該物件是一個快速而靈活的大資料集容器,該物件由兩部分組成:      實際的資料;      描述這些資料的元資料;      Numpy中定義的最重要的物件是成為ndarray的N維陣列型別。它描述相同型別的元素集合。可以使用基於零的索引訪問集合中的專案。      ndarray中的每個元素在記憶體中使用相同大小的塊。ndarray中每個元素是資料型別物件的物件(稱為dtype)      大部分的陣列操作僅僅是修改元資料部分,而不改變其底層的實際資料。陣列的維數稱為秩,簡單來說就是如果你需要獲取陣列中一個特定元素所需的座標數,如a是一個2×3×4的矩陣,你索引其中的一個元素必須給定三個座標a[x,y,z],故它的維數就是3。而軸可以理解為一種對陣列空間的分割,以陣列a為例,如果我們以0為軸,那麼a可以看成是一個由兩個元素構成的陣列,其中每個元素都是一個3×4的陣列。      我們可以直接將陣列看作一種新的資料型別,就像list、tuple、dict一樣,但陣列中所有元素的型別必須是一致的,Python支援的資料型別有整型、浮點型以及複數型,但這些型別不足以滿足科學計算的需求,因此NumPy中添加了許多其他的資料型別,如bool、inti、int64、float32、complex64等。同時,它也有許多其特有的屬性和方法。      官方解釋:      + View Code      2.1   常用ndarray屬性:      dtype        描述陣列元素的型別      shape       以tuple表示的陣列形狀      ndim         陣列的維度      size           陣列中元素的個數      itemsize    陣列中的元素在記憶體所佔位元組數      T               陣列的轉置      flat            返回一個數組的迭代器,對flat賦值將導致整個陣列的元素被覆蓋      real/imag  給出複數陣列的實部/虛部      import numpy as np      # 建立簡單的列表      a = [1,2,3,4,5,6]      # 講列表轉換為陣列      b = np.array(a)      # Numpy檢視陣列屬性      print(b.size)      #6      # 陣列形狀      print(b.shape)      # (6,)      # 陣列維度      print(b.ndim)      # 1      # 陣列元素型別      print(b.dtype)      # int32      import numpy as np      a = np.array([1,2,3])      print(a)      # [1 2 3]      # 多於一個維度      a = np.array([[1,  2],  [3,  4]])      print(a)      # [[1 2]      #  [3 4]]      # 最小維度      a = np.array([1,  2,  3,4,5], ndmin =  2)      print(a)      # [[1 2 3 4 5]]      # dtype 引數      a = np.array([1,  2,  3], dtype = complex)      print(a)      # [1.+0.j 2.+0.j 3.+0.j]        ndarray 物件由計算機記憶體中的一維連續區域組成,帶有將每個元素對映到記憶體塊中某個位置的索引方案。 記憶體塊以按行(C 風格)或按列(FORTRAN 或 MatLab 風格)的方式儲存元素。      2.2  常用ndarray方法:      reshape(…)                                 返回一個給定shape的陣列的副本      resize(…)                                    返回給定shape的陣列,原陣列shape發生改變      flatten()/ravel()                            返回展平陣列,原陣列不改變      astype(dtype)                              返回指定元素型別的陣列副本      fill()                                              將陣列元素全部設定為一個標量值      sum/Prod()                                  計算所有陣列元素的和/積      mean()/var()/std()                        返回陣列元素的均值/方差/標準差      max()/min()/ptp()/median()          返回陣列元素的最大值/最小值/取值範圍/中位數      argmax()/argmin()                       返回最大值/最小值的索引      sort()                                           對陣列進行排序,axis指定排序的軸;kind指定排序演算法,預設是快速排序      view()/copy()                               view創造一個新的陣列物件指向同一資料;copy是深複製      tolist()                                          將陣列完全轉為列表,注意與直接使用list(array)的區別      compress()                                  返回滿足條件的元素構成的陣列      numpy.reshape:      import numpy as np      a = np.arange(8)      print('原始陣列:')      print(a)      print('\n')      b = a.reshape(4,2)      print('修改後的陣列:')      print(b)      '''結果      原始陣列:      [0 1 2 3 4 5 6 7]      修改後的陣列:      [[0 1]      [2 3]      [4 5]      [6 7]]      '''      numpy.ndarray.flatten:      import numpy as np      a = np.arange(8).reshape(2,4)      print('原陣列:')      print(a)      print('\n')      # default is column-major      print('展開的陣列:')      print(a.flatten())      print('\n')      print('以 F 風格順序展開的陣列:')      print(a.flatten(order = 'F'))      '''結果:      原陣列:      [[0 1 2 3]      [4 5 6 7]]      展開的陣列:      [0 1 2 3 4 5 6 7]      以 F 風格順序展開的陣列:      [0 4 1 5 2 6 3 7]      '''      numpy.ravel:      import numpy as np      a = np.arange(8).reshape(2,4)      print('原陣列:')      print(a)      print('\n')      print('呼叫 ravel 函式之後:')      print(a.ravel())      print('\n')      print('以 F 風格順序呼叫 ravel 函式之後:')      print(a.ravel(order = 'F'))      '''結果:      原陣列:      [[0 1 2 3]      [4 5 6 7]]      呼叫 ravel 函式之後:      [0 1 2 3 4 5 6 7]      以 F 風格順序呼叫 ravel 函式之後:      [0 4 1 5 2 6 3 7]'''      2.3 陣列的建立      numpy中使用array()函式建立陣列,array的首個引數一定是一個序列,可以是元組也可以是列表。      2.3.1  一維陣列的建立      可以使用numpy中的arange()函式建立一維有序陣列,它是內建函式range的擴充套件版。      In [1]: import numpy as np      In [2]: ls1 = range(www.dfgjpt.com/ 10)      In [3]: list(ls1)      Out[3]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      In [4]: type(ls1)      Out[4]: range      In [5]: ls2 = np.arange(10)      In [6]: list(ls2)      Out[6]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      In [7]: type(ls2)      Out[7]: numpy.ndarray        通過arange生成的序列就不是簡簡單單的列表型別了,而是一個一維陣列。      如果一維陣列不是一個規律的有序元素,而是人為的輸入,就需要array()函式建立了。      In [8]: arr1 = np.array((1,20,13,28,22))      In [9]: arr1      Out[9]: array([ 1, 20, 13, 28, 22])      In [10]: type(arr1)      Out[10]: numpy.ndarray        上面是由元組序列構成的一維陣列。      In [11]: arr2 = np.array([1,1,2,3,5,8,13,21])      In [12]: arr2      Out[12]: array([ 1,  1,  2,  3,  5,  8, 13, 21])      In [13]: type(arr2)      Out[13]: numpy.ndarray        上面是由列表序列構成的一維陣列。      2.3.2  二維陣列的建立      二維陣列的建立,其實在就是列表套列表或元組套元組。      In [14]: arr3 = np.array(((1,1,2,3),(5,8,13,21),(34,55,89,144)))      In [15]: arr3      Out[15]:      array([[  1,   1,   2,   3],      [  5,   8,  13,  21],      [ 34,  55,  89, 144]])        上面使用元組套元組的方式。      In [16]: arr4 = np.array(www.yongshiyule178.com [[1,2,3,4],[5,6,7,8],[9,10,11,12]])      In [17]: arr4      Out[17]:      array([[ 1,  2,  3,  4],      [ 5,  6,  7,  8],      [ 9, 10, 11, 12]])        上面使用列表套列表的方式。      對於高維陣列在將來的資料分析中用的比較少,這裡關於高維陣列的建立就不贅述了,構建方法仍然是套的方式。        上面所介紹的都是人為設定的一維、二維或高維陣列,numpy中也提供了幾種特殊的陣列,它們是:      In [18]: np.ones(3)  #返回一維元素全為1的陣列      Out[18]: array([ 1.,  1.,  1.])      In [19]: np.ones([3,4])  #返回元素全為1的3×4二維陣列      Out[19]:      array([[ 1.,  1.,  1.,  1.],      [ 1.,  1.,  1.,  1.],      [ 1.,  1.,  1.,  1.]])      In [20]: np.zeros(3) #返回一維元素全為0的陣列      Out[20]: array([ 0.,  0.,  0.])      In [21]: np.zeros([3,4]) #返回元素全為0的3×4二維陣列      Out[21]:      array([[ 0.,  0.,  0.,  0.],      [ 0.,  0.,  0.,  0.],      [ 0.,  0.,  0.,  0.]])      In [22]: np.empty(3) #返回一維空陣列      Out[22]: array(www.00534.cn[ 0.,  0.,  0.])      In [23]: np.empty([3,4]) #返回3×4二維空陣列      Out[23]:      array([[ 0.,  0.,  0.,  0.],      [ 0.,  0.,  0.,  0.],      [ 0.,  0.,  0.,  0.]])      2.3.3  ones函式      返回特定大小,以1填充的新陣列      >>> import numpy as np      >>> a=np.ones(3);a      array([ 1.,  1.,  1.])      >>> b=np.ones(www.06640.cn(3,2));b      array([[ 1.,  1.],      [ 1.,  1.],      [ 1.,  1.]])      2.3.4  zeros函式      返回特定大小,以0填充的新陣列。      官方庫的解釋:      def zeros(shape, dtype=None, order='C'): # real signature unknown; restored from __doc__      """      zeros(shape, dtype=float, order='C')      Return a new array of given shape and type, filled with zeros.      Parameters      ----------      shape : int or tuple of ints      Shape of the new www.tianzunyule178.com array, e.g., ``(2, 3)`` or ``2``.      dtype : data-type, optional      The desired data-type for the array, e.g., `numpy.int8`.  Default is      `numpy.float64`.      order : {'C', 'F'}, optional, default: 'C'      Whether to store multi-dimensional data in row-major      (C-style) or column-major (Fortran-style) order in      memory.      Returns      -------      out : ndarray      Array of zeros with the given shape, dtype, and order.      See Also      --------      zeros_like : Return an array of zeros with shape and type of input.      empty : Return a new uninitialized array.      ones : Return a new array setting values to one.      full : Return a new array of given shape filled with value.      Examples      --------      >>> np.zeros(5)      array([ 0.,  0.,  0.,  0.,  0.])      >>> np.zeros((5,), dtype=int)      array([0, 0, 0, 0, 0])      >>> np.zeros((2, 1))      array([[ 0.],      [ 0.]])      >>> s = (2,2)      >>> np.zeros(s)      array([[ 0.,  0.],      [ 0.,  0.]])      >>> np.zeros((2,), dtype=[('x', 'i4'), ('y', 'i4')]) # custom dtype      array([(0, 0), (0, 0)],      dtype=[('x', '<i4'), ('y', '<i4')])      """      pass      numpy.zeros(shape, dtype=float, order=’C’)      引數:      shape:int或ints序列      新陣列的形狀,例如(2,3 )或2。      dtype:資料型別,可選      陣列的所需資料型別,例如numpy.int8。預設值為 numpy.float64。      order:{'C','F'},可選      是否在儲存器中以C或Fortran連續(按行或列方式)儲存多維資料。      返回:      1      2      out:ndarray      具有給定形狀,資料型別和順序的零陣列。      >>> c=np.zeros(3)      >>> c      array([ 0.,  0.,  0.])      >>> d=np.zeros((2,3));d      array([[ 0.,  0.,  0.],      [ 0.,  0.,  0.]])      #d=np.zeros(2,3)會報錯,d=np.zeros(3,dtype=int)來改變預設的資料型別      2.3.5  eye&identity函式      >>> e=np.eye(3);e      array([[ 1.,  0.,  0.],      [ 0.,  1.,  0.],      [ 0.,  0.,  1.]])      >>> e=np.eye(3,2);e      array([[ 1.,  0.],      [ 0.,  1.],      [ 0.,  0.]])      >>> e=np.eye(3,1);e      array([[ 1.],      [ 0.],      [ 0.]])      >>> e=np.eye(3,3);e      array([[ 1.,  0.,  0.],      [ 0.,  1.,  0.],      [ 0.,  0.,  1.]])      >>> e=np.eye(3,3,1);e      array([[ 0.,  1.,  0.],      [ 0.,  0.,  1.],      [ 0.,  0.,  0.]])      e=np.eye(3,3,2);e      array([[ 0.,  0.,  1.],      [ 0.,  0.,  0.],      [ 0.,  0.,  0.]])      >>> e=np.eye(3,3,3);e      array([[ 0.,  0.,  0.],      [ 0.,  0.,  0.],      [ 0.,  0.,  0.]])      >>> e=np.eye(3,3,4);e      array([[ 0.,  0.,  0.],      [ 0.,  0.,  0.],      [ 0.,  0.,  0.]])      >>> p=np.identity(4);p      array([[ 1.,  0.,  0.,  0.],      [ 0.,  1.,  0.,  0.],      [ 0.,  0.,  1.,  0.],      [ 0.,  0.,  0.,  1.]])      >>> p=np.identity(4,3);p  #會報錯      >>> p=np.identity((4,3));p  #會報錯      2.3.6 empty函式      它建立指定形狀和dtype的未初始化陣列。它使用以下建構函式:      1      numpy.empty(shape, dtype = float, order = 'C')        注意:陣列為隨機值,因為他們未初始化。      import numpy as np      x = np.empty([3,2], dtype =  int)      print(x)      # [[1762    0]      #  [   0    0]      #  [   0    0]]      >>> a=np.empty(3);a      array([  1.60091154e-163,   1.12069303e-258,   3.23790862e-318])      >>> a=np.empty((3,3));a      array([[  1.57741456e-284,   1.57680914e-284,   1.56735002e-163],      [  1.56205068e-163,   1.62511438e-163,   1.21880041e+171],      [  1.57757869e-052,   7.34292780e+223,   4.71235856e+257]])      2.3.7 ones_like  zero_like   empy_like函式      >>> a=np.array([[[1,2],[1,2]],[[1,2],[1,2]],[[1,2],[1,2]]])      >>> a.shape      (3, 2, 2)      >>> b=np.ones_like(a)      >>> b      array([[[1, 1],      [1, 1]],      [[1, 1],      [1, 1]],      [[1, 1],      [1, 1]]])      >>> b=np.zeros_like(a);b      array([[[0, 0],      [0, 0]],      [[0, 0],      [0, 0]],      [[0, 0],      [0, 0]]])      >>> a=np.array([[[1,2],[1,2]],[[1,2],[1,2]],[[1,2],[1,2]]])      >>> b=np.empty_like(a);b      array([[[39125057, 40012256],      [81313824, 81313856]],      [[       0,        0],      [       0,        0]],      [[       0,        0],      [       0,        0]]])      #注意,shape和dtype均複製      三,Numpy資料型別      NumPy 支援比 Python 更多種類的數值型別。 下表顯示了 NumPy 中定義的不同標量資料型別。      序號    資料型別及描述      1.    bool_儲存為一個位元組的布林值(真或假)      2.    int_預設整數,相當於 C 的long,通常為int32或int64      3.    intc相當於 C 的int,通常為int32或int64      4.    intp用於索引的整數,相當於 C 的size_t,通常為int32或int64      5.    int8位元組(-128 ~ 127)      6.    int1616 位整數(-32768 ~ 32767)      7.    int3232 位整數(-2147483648 ~ 2147483647)      8.    int6464 位整數(-9223372036854775808 ~ 9223372036854775807)      9.    uint88 位無符號整數(0 ~ 255)      10.    uint1616 位無符號整數(0 ~ 65535)      11.    uint3232 位無符號整數(0 ~ 4294967295)      12.    uint6464 位無符號整數(0 ~ 18446744073709551615)      13.    float_float64的簡寫      14.    float16半精度浮點:符號位,5 位指數,10 位尾數      15.    float32單精度浮點:符號位,8 位指數,23 位尾數      16.    float64雙精度浮點:符號位,11 位指數,52 位尾數      17.    complex_complex128的簡寫      18.    complex64複數,由兩個 32 位浮點表示(實部和虛部)      19.    complex128複數,由兩個 64 位浮點表示(實部和虛部)      NumPy 數字型別是dtype(資料型別)物件的例項,每個物件具有唯一的特徵。 這些型別可以是np.bool_,np.float32等。      3.1 資料型別物件(dtype)      資料型別物件描述了對應於陣列的固定記憶體塊的解釋,取決於以下方面:      資料型別(整數、浮點或者 Python 物件)      資料大小      位元組序(小端或大端)      在結構化型別的情況下,欄位的名稱,每個欄位的資料型別,和每個欄位佔用的記憶體塊部分。      如果資料型別是子序列,它的形狀和資料型別。      位元組順序取決於資料型別的字首<或>。<意味著編碼是小端(最小有效位元組儲存在最小地址中)。>意味著編碼是大端(最大有效位元組儲存在最小地址中)。      dtype語法構造:      1      numpy.dtype(object, align, copy)      引數為:      Object:被轉換為資料型別的物件。      Align:如果為true,則向欄位新增間隔,使其類似 C 的結構體。      Copy: 生成dtype物件的新副本,如果為flase,結果是內建資料型別物件的引用。      示例:      # 使用陣列標量型別      import numpy as np      dt = np.dtype(np.int32)      print(dt)      # int32      # int8,int16,int32,int64 可替換為等價的字串 'i1','i2','i4',以及其他。      dt = np.dtype('i4')      print(dt)      # int32      # 使用端記號      dt = np.dtype('>i4')      print(dt)      # >i4      # 首先建立結構化資料型別。      dt = np.dtype([('age',np.int8)])      print(dt)      # [('age', 'i1')]      # 現在將其應用於 ndarray 物件      dt = np.dtype([('age',np.int8)])      a = np.array([(10,),(20,),(30,)], dtype = dt)      print(a)      # [(10,) (20,) (30,)]      # 檔名稱可用於訪問 age 列的內容      dt = np.dtype([('age',np.int8)])      a = np.array([(10,),(20,),(30,)], dtype = dt)      print(a['age'])      # [10 20 30]      四,Numpy 切片和索引      ndarray物件的內容可以通過索引或切片來訪問和修改,就像python的內建容器物件一樣。      nadarray 物件中的元素遵循基於零的索引,有三種可用的索引方法型別:欄位訪問,基礎切片和高階索引。      基本切片是Python中基本切片概念到n維的擴充套件,通過start,stop和step引數提供給內建函式的slice函式來構造一個Python slice物件,此slice物件被傳遞給陣列來提取陣列的一部分。      練習:      import numpy as np      a = np.arange(10)      print(a)      # [0 1 2 3 4 5 6 7 8 9]      s = slice(2,7,2)      print(s)      # slice(2, 7, 2)      print(a[s])      # [2 4 6]      b = a[2:7:2]      print(b)      # [2 4 6]      # 對單個元素進行切片      b = a[5]      print(b)      # 5      # 對始於索引的元素進行切片      print(a[2:])      # [2 3 4 5 6 7 8 9]      # 對索引之間的元素進行切片      print(a[2:5])      # [2 3 4]      # 二維陣列      # 最開始的陣列      import numpy as np      a = np.array([[1,2,3],[3,4,5],[4,5,6]])      print('我們的陣列是:')      print(a)      print ('\n')      # 這會返回第二列元素的陣列:      print ('第二列的元素是:')      print(a[...,1])      print('\n')      # 現在我們從第二行切片所有元素:      print ('第二行的元素是:')      print(a[1,...])      print( '\n')      # 現在我們從第二列向後切片所有元素:      print ('第二列及其剩餘元素是:')      print(a[...,1:])      '''      我們的陣列是:      [[1 2 3]      [3 4 5]      [4 5 6]]      第二列的元素是:      [2 4 5]      第二行的元素是:      [3 4 5]      第二列及其剩餘元素是:      [[2 3]      [4 5]      [5 6]]'''      五,Numpy-IO      ndarray物件可以儲存到磁碟檔案並從磁碟檔案載入,可用的IO功能有:      load()和save() 函式處理Numpy 二進位制檔案(帶npy副檔名)。      loadtxt() 和savetxt() 函式處理正常的文字檔案。      Numpy為ndarray物件引入了一個簡單的檔案格式,這個npy檔案在磁碟檔案中,儲存重建ndarray所需的資料,圖形,dtype和其他資訊,以便正確獲取陣列,即使該檔案在具有不同架構的一臺機器上。      numpy.save()      此函式是講檔案輸入陣列儲存在具有npy副檔名的磁碟檔案中。      1      2      3      import numpy as np      a = np.array([1,2,3,4,5])      np.save('outfile',a)      為了從outfile.npy重建陣列,請使用load()函式。      1      2      3      4      import numpy as np      b = np.load('outfile.npy')      print(b)      # [1 2 3 4 5]      save()和load()函式接受一個附加的布林引數allow_pickles。Python中的pickle用在儲存到磁碟檔案或者從磁碟檔案讀取之前,對物件進行序列化和反序列化。      savetxt()      以簡單文字檔案格式儲存和獲取陣列資料,通過savetxt()和loadtxt()函式來完成的。      import numpy as np      a = np.array([1,2,3,4,5])      np.savetxt('out.txt',a)      b = np.loadtxt('out.txt')      print(b)      # [1. 2. 3. 4. 5.]        savetxt()和loadtxt()函式接受附加的可選引數,例如頁首,頁尾和分隔符。      六,numpy中的ndarray與array的區別、不同      答:Well, np.array is just a convenience function to create an ndarray, it is not a class itself.      (嗯,np.array只是一個便捷的函式,用來建立一個ndarray,它本身不是一個類)      You can also create an array using np.ndarray, but it is not the recommended way. From the docstring of np.ndarray:      (你也能夠用np.ndarray來建立,但這不是推薦的方式。來自np.ndarray的文件:)