Numpy快速入門

寫在前面

這篇博客是針對想入門機器學習和深度學習,或者數據分析的小白而寫,我們都知道機器學習和深度學習,數據分析的編程基礎就是Python編程,而最常用的一些庫,像numpy,pandas,matplotlib,sklearn等這些庫都必須熟記於心,如果學習深度學習的話,還必須有着深度學習基礎,掌握一些主流的TensorFlow,pytorch等框架才能在這條路上走下去。
而在信息發展很快的時代,原來在校的那種,學完理論,再去實戰的學習方式,其實已經不太適用,現在應該get到的一種新的學習技能其實應該是,邊用邊學,理論不需要總的學一遍再出發,而是掌握一些基本的理論,然後出發,遇到問題再返回來補充理論的這樣的一種邏輯。
所以如果想入門人工智能或者數據分析,千萬不要想着我Python學一遍,各種庫先學一遍這樣,不僅慢,有時候還會浪費很多時間,所以我根據之前整理的一些numpy,總結了一個numpy的快速入門(後續還有pandas,matplotlib的)有了這些知識,然後去通過項目實戰,然後再補充,應該會快速上手。如果想更深入的學習numpy,我後面也會給出一些鏈接,是我曾經學習時整理的筆記,希望有所幫助。
下面開始:

Numpy是什麼?

簡單的說,Numpy是Python中一個非常重要的第三庫,它不僅是 Python 中使用最多的第三方庫,而且還是 SciPy、Pandas 等數據科學的基礎庫。它所提供的數據結構比 Python 自身的“更高級、更高效”,可以這麼說,NumPy 所提供的數據結構是 Python 數據分析的基礎。

爲什麼要使用Numpy?

一句話:Numpy可以使得Python科學計算更高效。 Numpy中的數據結構比Python本身自帶的列表等這種內置結構更加有效,有下面幾個原因:

  • Python的list的元素在系統內存中是分散存儲,而Numpy中的數據存儲是一塊均勻連續的內存塊。這樣數組計算遍歷所有的元素,不像列表 list 還需要對內存地址進行查找,從而節省了計算資源。
  • 在內存訪問模式中,緩存會直接把字節塊從 RAM 加載到 CPU 寄存器中。因爲數據連續的存儲在內存中,NumPy 直接利用現代 CPU 的矢量化指令計算,加載寄存器中的多個連續浮點數。
  • NumPy 中的矩陣計算可以採用多線程的方式,充分利用多核 CPU 計算資源,大大提升了計算效率。

PS: 當然除了使用 NumPy外,你還需要一些技巧來提升內存和提高計算資源的利用率。一個重要的規則就是:避免採用隱式拷貝,而是採用就地操作的方式。舉個例子,如果我想讓一個數值 x 是原來的兩倍,可以直接寫成 x*=2,而不要寫成 y=x*2。前者可以快到2倍甚至更多。

如何快速掌握Numpy?

其實想快速掌握Numpy,掌握兩個重要的對象就可以了

  • ndarray(N-dimensional array object)解決了多維數組問題
  • ufunc(universal function object)則是解決對數組進行處理的函數

下面一一來看看。

ndarray對象

ndarray 實際上是多維數組的含義。在 NumPy 數組中,維數稱爲秩(rank),一維數組的秩爲 1,二維數組的秩爲 2,以此類推。在 NumPy 中,每一個線性的數組稱爲一個軸(axes),其實秩就是描述軸的數量。

首先,先來看看,ndarray對象是如何創建數組的,然後再來看看如何處理結構數組?

創建數組

創建數組前,你需要引用 NumPy 庫,可以直接通過 array 函數創建數組,如果是多重數組,比如示例裏的 b,那麼該怎麼做呢?你可以先把一個數組作爲一個元素,然後嵌套起來,比如示例 b 中的[1,2,3]就是一個元素,然後[4,5,6][7,8,9]也是作爲元素,然後把三個元素再放到[]數組裏,賦值給變量 b。
當然數組也是有屬性的,比如你可以通過函數 shape 屬性獲得數組的大小,通過 dtype 獲得元素的屬性。如果你想對數組裏的數值進行修改的話,直接賦值即可,注意下標是從 0 開始計的,所以如果你想對 b 數組,九宮格里的中間元素進行修改的話,下標應該是[1,1]。

import numpy as np   # 先導入

a = np.array([1, 2, 3])
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a.shape)
print(b.shape)
print(a.dtype)
b[1, 1] = 10
print(b)

結構數組

如果你想統計一個班級裏面學生的姓名、年齡,以及語文、英語、數學成績該怎麼辦?當然你可以用數組的下標來代表不同的字段,比如下標爲 0 的是姓名、下標爲 1 的是年齡等,但是這樣不顯性。實際上在 C 語言裏,可以定義結構數組,也就是通過 struct 定義結構類型,結構中的字段佔據連續的內存空間,每個結構體佔用的內存大小都相同,那在 NumPy 中是怎樣操作的呢?

import numpy as np
persontype = np.dtype({
    'names':['name', 'age', 'chinese', 'math', 'english'],
    'formats':['S32','i', 'i', 'i', 'f']})
peoples = np.array([("ZhangFei",32,75,100, 90),("GuanYu",24,85,96,88.5),
       ("ZhaoYun",28,85,92,96.5),("HuangZhong",29,65,85,100)],
    dtype=persontype)
ages = peoples[:]['age']
chineses = peoples[:]['chinese']
maths = peoples[:]['math']
englishs = peoples[:]['english']
print np.mean(ages)
print np.mean(chineses)
print np.mean(maths)
print np.mean(englishs)

首先在 NumPy 中是用 dtype 定義的結構類型,然後在定義數組的時候,用 array 中指定了結構數組的類型 dtype=persontype,這樣你就可以自由地使用自定義的 persontype 了。比如想知道每個人的語文成績,就可以用 chineses = peoples[:][‘chinese’],當然 NumPy 中還有一些自帶的數學運算,比如計算平均值使用 np.mean。
PS: 注意上面是Python2中的格式,Python3中,print不是語句了,是個函數,用括號括起來。

ufunc運算

ufunc 是 universal function 的縮寫,是不是聽起來就感覺功能非常強大?確如其名,它能對數組中每個元素進行函數操作。NumPy 中很多 ufunc 函數計算速度非常快,因爲都是採用 C 語言實現的。

連續數組的創建

NumPy 可以很方便地創建連續數組,比如我使用 arange 或 linspace 函數進行創建:

x1 = np.arange(1,11,2)
x2 = np.linspace(1,9,5)

np.arange 和 np.linspace 起到的作用是一樣的,都是創建等差數組。這兩個數組的結果 x1,x2 都是[1 3 5 7 9]。結果相同,但是你能看出來創建的方式是不同的。

  • arange() 類似內置函數 range(),通過指定初始值、終值、步長來創建等差數列的一維數組,默認是不包括終值的。
  • linspace 是 linear space 的縮寫,代表線性等分向量的含義。linspace() 通過指定初始值、終值、元素個數來創建等差數列的一維數組,默認是包括終值的。

算數運算

通過 NumPy 可以自由地創建等差數組,同時也可以進行加、減、乘、除、求 n 次方和取餘數。

x1 = np.arange(1,11,2)
x2 = np.linspace(1,9,5)
print np.add(x1, x2)
print np.subtract(x1, x2)
print np.multiply(x1, x2)
print np.divide(x1, x2)
print np.power(x1, x2)
print np.remainder(x1, x2)

以 x1, x2 數組爲例,求這兩個數組之間的加、減、乘、除、求 n 次方和取餘數。在 n 次方中,x2 數組中的元素實際上是次方的次數,x1 數組的元素爲基數。在取餘函數裏,你既可以用 np.remainder(x1, x2),也可以用 np.mod(x1, x2),結果是一樣的。

統計函數

如果你想要對一堆數據有更清晰的認識,就需要對這些數據進行描述性的統計分析,比如瞭解這些數據中的最大值、最小值、平均值,是否符合正態分佈,方差、標準差多少等等。它們可以讓你更清楚地對這組數據有認知。下面我來介紹下在 NumPy 中如何使用這些統計函數。

計數組 / 矩陣中的最大值函數 amax(),最小值函數 amin()

amin() 用於計算數組中的元素沿指定軸的最小值。對於一個二維數組 a,amin(a) 指的是數組中全部元素的最小值,amin(a,0) 是延着 axis=0 軸的最小值,axis=0 軸是把元素看成了[1,4,7], [2,5,8], [3,6,9]三個元素,所以最小值爲[1,2,3],amin(a,1) 是延着 axis=1 軸的最小值,axis=1 軸是把元素看成了[1,2,3], [4,5,6], [7,8,9]三個元素,所以最小值爲[1,4,7]。同理 amax() 是計算數組中元素沿指定軸的最大值。

import numpy as np
a = np.array([[1,2,3], [4,5,6], [7,8,9]])
print np.amin(a)
print np.amin(a,0)
print np.amin(a,1)
print np.amax(a)
print np.amax(a,0)
print np.amax(a,1)
統計最大值與最小值之差 ptp()

對於相同的數組 a,np.ptp(a) 可以統計數組中最大值與最小值的差,即 9-1=8。同樣 ptp(a,0) 統計的是沿着 axis=0 軸的最大值與最小值之差,即 7-1=6(當然 8-2=6,9-3=6,第三行減去第一行的 ptp 差均爲 6),ptp(a,1) 統計的是沿着 axis=1 軸的最大值與最小值之差,即 3-1=2(當然 6-4=2, 9-7=2,即第三列與第一列的 ptp 差均爲 2)。

a = np.array([[1,2,3], [4,5,6], [7,8,9]])
print np.ptp(a)
print np.ptp(a,0)
print np.ptp(a,1)
統計數組的百分位數 percentile()

percentile() 代表着第 p 個百分位數,這裏 p 的取值範圍是 0-100,如果 p=0,那麼就是求最小值,如果 p=50 就是求平均值,如果 p=100 就是求最大值。同樣你也可以求得在 axis=0 和 axis=1 兩個軸上的 p% 的百分位數。

a = np.array([[1,2,3], [4,5,6], [7,8,9]])
print np.percentile(a, 50)
print np.percentile(a, 50, axis=0)
print np.percentile(a, 50, axis=1)
統計數組中的中位數 median()、平均數 mean()

你可以用 median() 和 mean() 求數組的中位數、平均值,同樣也可以求得在 axis=0 和 1 兩個軸上的中位數、平均值

a = np.array([[1,2,3], [4,5,6], [7,8,9]])
#求中位數
print np.median(a)
print np.median(a, axis=0)
print np.median(a, axis=1)
#求平均數
print np.mean(a)
print np.mean(a, axis=0)
print np.mean(a, axis=1)
統計數組中的加權平均值 average()
a = np.array([1,2,3,4])
wts = np.array([1,2,3,4])
print np.average(a)
print np.average(a,weights=wts)

average() 函數可以求加權平均,加權平均的意思就是每個元素可以設置個權重,默認情況下每個元素的權重是相同的,所以 np.average(a)=(1+2+3+4)/4=2.5,你也可以指定權重數組 wts=[1,2,3,4],這樣加權平均 np.average(a,weights=wts)=(11+22+33+44)/(1+2+3+4)=3.0。

統計數組中的標準差 std()、方差 var()
a = np.array([1,2,3,4])
print np.std(a)
print np.var(a)

方差的計算是指每個數值與平均值之差的平方求和的平均值,即 mean((x - x.mean())** 2)。標準差是方差的算術平方根。在數學意義上,代表的是一組數據離平均值的分散程度。所以 np.var(a)=1.25, np.std(a)=1.118033988749895。

Numpy排序

排序算法在 NumPy 中實現起來其實非常簡單,一條語句就可以搞定。這裏你可以使用 sort 函數,sort(a, axis=-1, kind=‘quicksort’, order=None),默認情況下使用的是快速排序;在 kind 裏,可以指定 quicksort、mergesort、heapsort 分別表示快速排序、合併排序、堆排序。同樣 axis 默認是 -1,即沿着數組的最後一個軸進行排序,也可以取不同的 axis 軸,或者 axis=None 代表採用扁平化的方式作爲一個向量進行排序。另外 order 字段,對於結構化的數組可以指定按照某個字段進行排序。

a = np.array([[4,3,2],[2,4,1]])
print np.sort(a)
print np.sort(a, axis=None)
print np.sort(a, axis=0)  
print np.sort(a, axis=1)  

總結

在 NumPy 學習中,你重點要掌握的就是對數組的使用,因爲這是 NumPy 和標準 Python 最大的區別。在 NumPy 中重新對數組進行了定義,同時提供了算術和統計運算,你也可以使用 NumPy 自帶的排序功能,一句話就搞定各種排序算法。
當然要理解 NumPy 提供的數據結構爲什麼比 Python 自身的“更高級、更高效”,要從對數據指針的引用角度進行理解。
在這裏插入圖片描述

參考

發佈了78 篇原創文章 · 獲贊 83 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章