終於講到這個主題了~ 相信大家都看過 Numpy 這個模組,但是應該都不是很熟悉(沒關係,大鳥大學的時候完全不會寫 Python)。Numpy 基本上是 Python 在做一些所謂 Data Science 運算的核心模組,它對於做高緯度(>3D)的陣列/矩陣運算非常便利。好,進入主題...
環境安裝
Python 裡沒有預設安裝 numpy 的模組。因此在開始寫之前,我們需要安裝這個模組;否則將出現以下錯誤訊息。
>>> import numpy as np
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'numpy'
各位可以到你們的指令介面直接下這個指令。
pip install numpy
numpy.array()
很有趣的一件事情是,雖然 Python 把陣列稱為 list,Numpy 還是把它稱為 array。我們先來講一下一些在敘述 numpy array 常用到的名詞。
- Rank: 維度(Dimension)
- Shape: 一個用來形容 Array 裡每個維度大小的 Tuple
首先,就是要 import
numpy 的模組;我們通常都會把它 alias 為 np
。我們可以直接透過 numpy.array()
宣告一個 numpy.ndarray
。而我們可以透過一些 numpy.ndarray
物件裡的一些 method 來獲取一些資訊。
import numpy as np
# 宣告一個 Numpy Array
a = np.array([1,2,3,4,5]) # rank 1 array / 1d array (size = (1,5))
b = np.array([[1,2,3],[4,5,6]]) # rank 2 array / 2d array / matrix (size=(2,3))
c = np.array([[[1,2],[3,4]], # rank 3 array / 3d array (size = (2,2,2))
[[5,6],[7,8]]])
print(type(a)) # <class 'numpy.ndarray'>
print(b.ndim) # 2
print(c.shape) # (2, 2, 2)
基本上我們人類在思考維度的時候,最多大概只能想像 3-4 維的時空。然而,我們在做深度學習的時候需要碰到更高維度(5、10、50 甚至上萬)。這時候 numpy 的這些 method 會很常派上用場。但是,今天只是在介紹 numpy 入門,我們還不是資料科學家,因此這篇文章不會提到高過三維的陣列;你們只要能夠大概想像多維度陣列大概會是這樣就好了...
當然,numpy 還有一些很便利的 method 可以用來呼叫一些特殊的矩陣哦~大家就自己玩玩看吧~
import numpy as np
a = np.zeros((2,2))
b = np.ones((1,2))
c = np.full((2,2), 7)
d = np.identity(3)
e = np.random.random((2,2))
f = np.arange(4,7)
Indexing,Slicing
如果我們想要獲取某一筆資料的值,基本上就跟普通的陣列一樣,我們可以對它的 index 獲取它的值。我們也可以對它做 slicing,把一塊資料取出來,變成另外一個陣列。
import numpy as np
arr = np.array([[11, 22, 33],
[44, 55, 66],
[77, 88, 99]])
print(arr[1,1]) # 55
print(arr[1][1]) # 55
print(arr[1:,:1]) # [[44],[77]]
print(arr[::1][1::]) # [[44 55 66],[77 88 99]]
np.reshape
如果我們想要對一個陣列做一些轉變,我們可以用 resize
來改變它的形狀;當然,是要在不影響陣列矩陣裡面的值為前提。這裡比較會亂的應該是 reshape
和 resize
兩個 method;這兩個不同的地方在於 reshape
只是在 stdout
輸出一個暫時的矩陣,而 resize
所回傳的是已經經過轉變的矩陣(resize
可以把矩陣的 shape 變大哦~)。transpose
是對矩陣裡的 row 和 column 顛倒。
import numpy as np
arr = np.array([[11, 22],
[33, 44],
[55, 66]])
print(arr.shape) # (3,2)
print(arr.reshape(2,3)) # output temporary array reshape
print(arr.resize(3,4)) # changes the array shape
print(arr.transpose) # (3,4) -> (4,3)
print(arr.resize(12,1)) # (4,3) -> (12,1)
np.add np.multiply np.dot
最後,我們來對這些矩陣做運算。這裡就要回到各位的高中數學啦(這句話是不是很熟悉?)當我們在做 add
的時候,如果矩陣大小不同的話,他會對陣列裡所有的值做運算,這叫做 broadcasting。要注意的事,就是如果矩陣的形不符合 broadcasting 的需求,就會跳出錯誤訊息。對 numpy array 做 +
運算也是可以哦~
import numpy as np
a = np.array([2])
b = np.array([1,2,3])
c = numpy.add(a,b)
print(c) # [3,4,5]
d = np.array([[1,2,3],[1,2,3]])
e = c + d
print(e) # [[4 6 8] [4 6 8]]
f = np.array([[1,2],[1,2]])
g = c + f
# ValueError: operands could not be broadcast together with shapes (3,) (2,2)
numpy.multiply
和 numpy.dot
是不一樣的東西。multiply
基本上是對 array 裡的所有值做一個 element-wise 的運算;換句話說如果我們有兩個矩陣 M,N 各 shape 為 (2,3),它會在對應的值做乘法,或者如果不同大小,就會做 broadcast。而 numpy.dot
則是對陣列做內積。若所輸入的矩陣 M,N 的 shape 為 (2,3) 和 (3,2),其輸出的值會為 (2,2)。
import numpy as np
a = np.array([1,2,3])
b = np.array([[1,2,3], [4,5,6]])
print(a*b)
# [[ 1 4 9]
# [ 4 10 18]]
c = np.array([[1, 2, 3], [4, 5, 6]])
d = np.array([[1, 2], [3, 4], [5, 6]])
print(np.dot(c,d))
# [[22 28]
# [49 64]]
這裡有提供給那些跟大鳥一樣數學很爛的人內積的運算式哦~感謝球哥大大幫忙開導 XDD