學機器學習,不會數據處理怎么行?—— 一、NumPy詳解


最近學習強化學習和機器學習,意識到數據分析的重要性,就開始補Python的幾個科學計算庫,並總結到博客中。本篇博客中用到的代碼在這里下載。

什么是Numpy?

  NumPy是Python數值計算最重要的基礎包,支持高級大量的維度數組與矩陣運算,大多數提供科學計算的包都是使用Numpy的數組作為構建基礎。Numpy內部解除了Python的PIL(全局解釋器鎖),運算效率極好,是大量機器學習框架的基礎庫!

  其部分功能如下:

  • ndarray,一個具有矢量算術運算和復雜廣播能力的快速且節省空間的多維數組。
  • 用於對整組數據進行快速運算的標准數學函數(無需編寫循環)。
  • 用於讀寫磁盤數據的工具以及用於操作內存映射文件的工具。
  • 線性代數、隨機數生成以及傅里葉變換功能
  • 用於集成由C、C++、Fortran等語言編寫的代碼的工具

  需要一提的是,NumPy本身沒有提供那么多高級的數據分析功能,但理解NumPy數組,以及面向數組的計算將有助於更加高效地使用諸如pandas之類的工具。當然,如果只是想用pandas簡單處理下數據,可以跳過NumPy的學習,直接學習pandas。

  對於大部分數據分析應用而言,需要關注的功能主要集中在:

  • 用於數據整理和清理、子集構造和過濾、轉換等快速的矢量化數組運算。
  • 常用的數組算法,如排序、唯一化、集合運算等。
  • 高效地描述統計和數據聚合/摘要運算。
  • 用於異構數據集的合並/連接運算的數據對齊和關系型數據運算。
  • 將條件邏輯表述為數組表達式(而不是帶有if-elif-else分支的循環)。
  • 數據的分組運算(聚合、轉換、函數應用等)。

為什么要使用NumPy?

  NumPy數組在數值運算方面的效率優於Python提供的list容器。使用NumPy可以在代碼中省去很多循環語句,因此其代碼比等價的Python代碼更為簡潔。

  NumPy數組一般是同質的(但有一種特殊的數組類型例外,它是異質的),即數組中的所有元素類型必須是一致的。這樣有一個好處:如果我們知道數組中的元素均為同一類型,該數組所需的存儲空間就很容易確定下來。

  NumPy是在一個連續的內存塊中儲存數據,獨立於其他Python內置對象,比起Python的內置序列,Numpy數組使用的內存更少。

  Numpy可以在整個數組上執行復雜的計算,而不需要for循環。

執行下面代碼進行驗證

1 import numpy as np 2 my_arr = np.arange(1000000) 3 my_list = list(range(1000000)) 4 %time for _ in range(10): my_arr2 = my_arr * 2 5 %time for _ in range(10): my_list2 = [x * 2 for x in my_list]

  很明顯,基於NumPy的算法要比純Python快10到100倍(甚至更快),並且使用的內存更少。

Numpy的ndarray:一種多維數組對象

1.什么是ndarry

  NumPy最重要的一個特點就是其N維數組對象(即ndarray),該對象是一個快速而靈活的大數據集容器。你可以利用這種數組對整塊數據執行一些數學運算,其語法跟標量元素之間的運算一樣。

進行數學運算:

這里可以很清晰的看出NumPy數組對整組數組的計算操作的簡便之處。

  注:一般在import時都是使用 import numpy as np。當然,也可以使用 for numpy import * ,但不建議這么做,因為numpy的命名空間很大,包含很多函數,其中一些的名字與Python的內置函數重名(如min和max)。

  ndarray是一個通用的同構數據多維容器,也就是說,其中的所有元素必須是相同類型的。每個數組都有一個shape(一個表示各維度大小的元組)和一個dtype(一個用於說明數組數據類型的對象):

2.創建ndarray

  創建數組最簡單的辦法就是使用array函數。它接受一切序列型的對象(包括其他數組),然后產生一個新的含有傳入數據的Numpy數組。

  除np.array之外,還有一些函數也可以新建數組。比如,zeros和ones分別可以創建指定長度或形狀的全0或全1數組。empty可以創建一個沒有任何具體值的數組。要用這些方法創建多維數組,只需傳入一個表示形狀的元組即可。

 

注:認為np.empty會返回全0數組的想法是不安全的。很多情況下(如前所示),它返回的都是一些未初始化的垃圾值。

arrange是Python內置函數的數組版:

3.ndarray的數據類型

  dtype(數據類型)是一個特殊的對象,它含有ndarray將一塊內存解釋為特定數據類型所需的信息。是NumPy靈活交互其它系統的源泉之一。多數情況下,它們直接映射到相應的機器表示,這使得“讀寫磁盤上的二進制數據流”以及“集成低級語言代碼(如C、Fortran)”等工作變得更加簡單。數值型dtype的命名方式相同:一個類型名(如float或int),后面跟一個用於表示各元素位長的數字。標准的雙精度浮點值(即Python中的float對象)需要占用8字節(即64位)。因此,該類型在NumPy中就記作float64。下表列出了NumPy所支持的全部數據類型。

 
你可以通過ndarray的astype方法明確地將一個數組從一個dtype轉換成另一個dtype:
 
 

NumPy計算

  這里將介紹Numpy的一些基本計算

1.條件運算

  

2.統計運算

  求最大值

  

  求最小值

  

  平均值

  方差

3.線性代數

    轉置是重塑的一種特殊形式,它返回的是源數據的視圖(不會進行任何復制操作)。數組不僅有transpose方法,還有一個特殊的T屬性

在進行矩陣計算時,經常需要用到該操作,比如利用np.dot計算矩陣內積

 

對於高維數組,我們可以使用transpose進行轉置操作(有點難懂)

 

在這里,如果我們使用arr.shape(),則會返回(2,2,4),第一個2表示兩組,第二個則表示每組都有兩行,4則表示4列。而這三個數字由一個元組(0,1,2)進行索引,所以使用arr.transpose((1, 0, 2))時,則表示將第一位數與第二位數交換位置。最終會得到圖中所示結果。

 當然,我們也可以使用.T進行操作,不過.T進行的只是軸對換而已。

 ndarray還有一個swapaxes方法,它需要接受一對軸編號

矩陣拼接

  • 水平拼接

  

  • 垂直拼接

 

基本索引和切片

1.一維數組

  NumPy數組的索引是一個內容豐富的主題,因為選取數據子集或單個元素的方式有很多。一維數組很簡單。從表面上看,它們跟Python列表的功能差不多

  如上所示,當你將一個標量值賦值給一個切片時(如arr[5:8]=12),該值會自動傳播到整個選區。跟列表最重要的區別在於,數組切片是原始數組的視圖。這意味着數據不會被復制,視圖上的任何修改都會直接反映到源數組上。

  先創建一個arr的切片

  修改其中的值,會發現數組arr中的值也會改變

  切片[ : ]會給數組中所有的值賦值

2.高維數組

  對於高維度數組,能做的事情更多。在一個二維數組中,各索引位置上的元素不再是標量而是一維數組

 

  索引方式

  在多維數組中,如果省略了后面的索引,則返回對象會是一個維度低一點的ndarray(它含有高一級維度上的所有數據),且標量值和數組都可用於賦值。

切片索引

  ndarray的切片語法跟Python列表這樣的一維對象差不多。對於之前的二維數組arr2d,其切片方式稍顯不同

  可以看出,它是沿着第0軸(即第一個軸)切片的。也就是說,切片是沿着一個軸向選取元素的。表達式arr2d[:2]可以被認為是“選取arr2d的前兩行”。

  當然,也可以一次傳入多個切片,像傳入多個索引那樣

 像這樣進行切片時,只能得到相同維數的數組視圖。通過將整數索引和切片混合,可以得到低維度的切片。

 

布爾型索引

  來看這樣一個例子,假設我們有一個用於存儲數據的數組以及一個存儲姓名的數組(含有重復項)。在這里,我將使用numpy.random中的randn函數(上面表格中漏了這個)生成一些正態分布的隨機數據:

  假設每個名字都對應data數組中的一行,而我們想要選出對應於名字"Bob"的所有行。跟算術運算一樣,數組的比較運算(如==)也是矢量化的。因此,對names和字符串"Bob"的比較運算將會產生一個布爾型數組,這個布爾型數組課用於數組索引

注:布爾型數組的長度必須跟被索引的軸長度一致,如果布爾型數組的長度不對,布爾型選擇就會出錯。

  此外,我們還可以將布爾型數組跟切片、整數(或整數序列)混合使用

 

  如果我們要選取多個名字,則組合應用多個布爾條件,使用 &、| 之類的布爾算術運算符即可

 

 注:通過布爾型索引選取數組中的數據,將總是創建數據的副本,即使返回一模一樣的數組也是如此。

 花式索引

花式索引(Fancy indexing)是一個NumPy術語,它指的是利用整數數組進行索引。假設我們有一個8×4數組

array([[ 0.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  1.], [ 2., 2., 2., 2.], [ 3., 3., 3., 3.], [ 4., 4., 4., 4.], [ 5., 5., 5., 5.], [ 6., 6., 6., 6.], [ 7., 7., 7., 7.]]) 

為了以特定順序選取行子集,只需傳入一個用於指定順序的整數列表或ndarray即可

使用負數索引將會從末尾開始選取行

一次傳入多個索引數組會返回一個一維數組,其中的元素對應各個索引元組

注:花式索引跟切片不一樣,它總是將數據復制到新數組中。

隨機數 

1.偽隨機數生成

  NumPy可生成隨機數,這些隨機數是通過算法基於隨機數生成器種子,在確定性條件下生成的,是偽隨機數。我們可以使用normal來得到標准正態分布的樣本數組,並且,在需要產生大量隨機數時,NumPy的隨機數生成速度比Python內置的random快了不止一個數量級

 

同時,我們可以用NumPy的np.random.seed更改隨機數生成種子

np.random.seed(1234)

numpy.random的數據生成函數使用了全局的隨機種子。要避免全局狀態,我們可以使用numpy.random.RandomState,創建一個與其它隔離的隨機數生成器

rng = np.random.RandomState(1234)
rng.randn(10)

Out: 
array([ 0.4714, -1.191 ,  1.4327, -0.3127, -0.7206,  0.8872,  0.8596,
       -0.6365,  0.0157, -2.2427])

下圖給出了numpy.random中的部分函數

 


 

下面屬於補充了

2.實例:隨機漫步

我們可以通過模擬隨機漫步來說明如何運用數組運算。先來看一個簡單的隨機漫步的例子:從0開始,步長1和-1出現的概率相等。

這提示就是隨機漫步中各步的累計和,可以用一個數組運算來實現。因此,我用np.random模塊一次性隨機產生1000個“擲硬幣”結果(即兩個數中任選一個),將其分別設為1或-1,然后計算累計和

有了這些數據之后,我們就可以沿着漫步路徑做一些統計工作了,比如求取最大值和最小值等

1 walk.min()
2 
3 walk.max()

再看一個復雜點的統計任務——首次穿越時間,即隨機漫步過程中第一次到達某個特定值的時間。假設我們想要知道本次隨機漫步需要多久才能距離初始0點至少10步遠(任一方向均可)。np.abs(walk)>=10可以得到一個布爾型數組,它表示的是距離是否達到或超過10,而我們想要知道的是第一個10或-10的索引。可以用argmax來解決這個問題,它返回的是該布爾型數組第一個最大值的索引(True就是最大值):

In [103]:
(np.abs(walk) >= 10).argmax()

Out[103]:
57

一次模擬多個隨機漫步

如果你希望模擬多個隨機漫步過程(比如5000個),只需對上面的代碼做一點點修改即可生成所有的隨機漫步過程。只要給numpy.random的函數傳入一個二元元組就可以產生一個二維數組,然后我們就可以一次性計算5000個隨機漫步過程的累計和了:

 

In [105]:
nwalks = 5000
nsteps = 1000
draws = np.random.randint(0, 2, size=(nwalks, nsteps))
steps = np.where(draws > 0, 1 , -1)
walks = steps.cumsum(1)
walks

Out[105]:
array([[-1,  0, -1, ..., 12, 11, 10],
       [ 1,  2,  3, ..., -2, -1,  0],
       [-1,  0,  1, ..., 34, 35, 36],
       ...,
       [ 1,  0, -1, ..., 32, 33, 32],
       [ 1,  0,  1, ..., 20, 21, 22],
       [-1,  0, -1, ..., 18, 19, 18]], dtype=int32)

 

剩下的數據處理就由你們自行發揮了。

結尾

上面只介紹了NumPy的部分內容,剩下的如歸一化操作,排序,文件輸入輸出(大部分人都用pandas加載文本或表格數據)等等都沒寫入,但都在代碼中給出了示例。頭一回博客寫這么長(雖說圖片居多),中間還幾次頁面錯誤沒保存。。。如有錯誤,歡迎大家指正。

 

參考博客:

https://www.jianshu.com/p/a380222a3292

https://www.jianshu.com/p/83c8ef18a1e8

https://blog.csdn.net/qq351469076/article/details/78817378

參考書籍:

《利用Python進行數據分析·第2版》

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM