Python機器學習、深度學習:快速、完全的Numpy入門指南
NumPy是python的第三方科學計算包,全名稱為Numerical Python extensions。NumPy包含以下幾個功能元件:強大的N維陣列物件(可以操控多為陣列),優美巧妙的功能(廣播)函式,對於線性代數,傅立葉變換,隨機數的生成有著很好的支援。現在廣泛用於機器學習與深度學習之中。
基礎型別
NumPy中最基本的物件就是均勻多維陣列,包含一系列相同型別的變數(一般數字),類似於陣列,可以通過正整數來進行訪問。注意,在Numpy中維數(dimensions)稱之為axes。axes的數量就是rank(秩)。
舉個例子,在一個三維空間中的一個點的座標為[1, 3, 2]
,這是一個秩為1的陣列,因為它只含有一個軸(axis),軸的長度為3。
接下來的這個例子的rank為2,因為它有兩維。
(注意這裡的維數於向量中的維數不同,這裡的維數相當於C語言中陣列的維數,又稱軸數。另外這裡的rank不等同於矩陣中的秩,在python的語言中,維數的數量稱之為rank)
[[1, 0, 2],
[0, 2, 1]]
第一維(軸)的數量為2([1, 0, 2],[0 ,2, 1]),第二維的數量為3(如第一個陣列中的1,0,2)。
再來區別一下python中rank與矩陣中rank(秩)的區別,numpy中多維陣列其實就是矩陣,擁有和矩陣一樣的性質。以下講解中陣列一般為多維陣列。
>>> a =np.array([[1,2,3],[2,3,4],[3,4,5]]) #這裡定義了一個三行三列的多維陣列(可以理解為矩陣)
>>> a
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
>>> a.ndim #在numpy中ndarry.ndim返回這個陣列的rank,要注意,這裡的rank是2,但是在矩陣中rank應該為3
2
注意NumPy中的陣列類稱之為ndarray
,一般我們叫它的別名array
,其這個與python標準庫中的array.array
不同,python中的只可以處理一維陣列,功能上差很多。
基本定義方法
>>> import numpy as np
>>> a = np.array([1,2,3]) #定義一個一維陣列
>>> a.size #輸出a的容量
3
>>> a.shape #a的形狀,對於單個一維陣列來說 維數就是元素長度
(3,)
>>> b = np.array([[1,2,3],[2,3,4],[3,4,5]]) #定義一個二維陣列
>>> b.size #b的容量為元素的數量
9
>>> b.shape #b的形狀,這裡b是一個擁有三個陣列,每個陣列有三個元素
(3, 3)
>>> b.shape[0] #b中第一維的數量
3
>>> b.shape[1] #b重第二維的數量(即元素長度)
3
>>> c = np.arange(15).reshape(3, 5) #定義一個範圍從數量為15,第一維為3,第二維為5的陣列
>>> c
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
>>> c.shape #同上
(3, 5)
>>> c.ndim #陣列的秩
2
>>> c.dtype.name #陣列中元素的型別
'int64'
>>> c.itemsize #陣列中元素位元組數(大小) 這裡的8為(64/8)
8
>>> c.size #C中元素數量
15
>>> type(c) #型別
<type 'numpy.ndarray'>
>>> d = np.array([6, 7, 8])
>>> d
array([6, 7, 8])
>>> type(d)
<type 'numpy.ndarray'>
在平常的使用中,我們通常使用np做numpy的別名,這樣可以使程式更加簡潔便於閱讀。
下面例子也中展示了array的基本構造,注意,這樣初始化是錯誤的!
>>> a = np.array(1,2,3) # 錯的!
>>> a = np.array([1,2,3]) # 應該這樣
另外,還可以這樣構造
>>> a = np.array([[1,2],[3,4]], dtype=complex) #在後面通過函式引數指定型別
>>> a
array([[ 1.+0.j, 2.+0.j],
[ 3.+0.j, 4.+0.j]])
>>> b = np.zeros((3,3)) #構造全為0,(3,3)的陣列
>>> b
array([[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]])
>>> d = np.zeros((2,3,4), dtype=np.int16) #指定構造維數和元素型別
>>> d
array([[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]], dtype=int16)
>>> a = np.ones((3,4)) #單位陣列
>>> a
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
>>> e = np.arange(1, 10 ,2) #定義範圍為1-10,間隔為2的陣列
>>> e
array([1, 3, 5, 7, 9])
>>> f = np.arange(0, 2, 0.1) #也支援浮點型
>>> f
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ,
1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9])
>>> g = np.linspace(0,10,11) #定義0-10中,均勻取11個點的陣列
>>> g
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
基本操作
算術演算法操作同樣適合陣列,numpy可以方便地在陣列中進行操作。
>>> import numpy as np
>>> a = np.array([1,2,3])
>>> b = np.arange(3)
>>> b
array([0, 1, 2])
>>> c = a - b #對應元素相減
>>> c
array([1, 1, 1])
>>> b**2 #b中所有元素平方
array([0, 1, 4], dtype=int32)
>>> 10*np.sin(a) #a中所有元素通過sin函式乘於10
array([ 8.41470985, 9.09297427, 1.41120008])
>>> a < 2 #判斷a中的元素,返回bool型別
array([ True, False, False], dtype=bool)
注意,numpy中的乘法符號*對陣列中的每個元素也是同樣起作用的,這個與矩陣中的乘法不同(dot)
>>> A = np.array( [[1,1],
... [0,1]] )
>>> B = np.array( [[2,0],
... [3,4]] )
>>> A*B # 對應元素乘積
array([[2, 0],
[0, 4]])
>>> A.dot(B) # 矩陣乘法
array([[5, 4],
[3, 4]])
>>> np.dot(A, B) # 矩陣乘法
array([[5, 4],
[3, 4]])
numpy中也支援+=
和-+
運算,在原先存在的array中進行操作(不是新建立一個陣列)。
>>> import numpy as np
>>> a = np.array([[1,2,3],[2,3,4]])
>>> a
array([[1, 2, 3],
[2, 3, 4]])
>>> b = np.ones((2,3)) #預設型別為浮點型float64
>>> b
array([[ 1., 1., 1.],
[ 1., 1., 1.]])
>>> b += a #這裡整型int32被轉化為float64
>>> b
array([[ 2., 3., 4.],
[ 3., 4., 5.]])
>>> a += b
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int32') with casting rule 'same_kind'
上面的例子a+=b
出現錯誤,這是因為numpy在操作不同型別的資料時,會朝著更精確的資料型別進行轉化(類似於C語言中的向上轉型)。
>>> from numpy import pi #pi即PI,圓周率
>>> a = np.ones(3, dtype=np.int32)
>>> b = np.linspace(0,pi,3)
>>> b.dtype.name
'float64'
>>> c = a+b
>>> c
array([ 1. , 2.57079633, 4.14159265]) #轉型
>>> c.dtype.name
'float64'
>>> d = np.exp(c*1j)
>>> d
array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j,
-0.54030231-0.84147098j])
>>> d.dtype.name
'complex128' #複數型
numpy中可以使用很多“非陣列”操作符來對陣列進行操作,如求和sum
,取平均mean
。也可以通過設定axis
引數來對特定的軸進行操作。
>>> a = np.array([[1,2,3],[2,3,4]])
>>> a
array([[1, 2, 3],
[2, 3, 4]])
>>> a.sum() #求和
15
>>> a.min() #求最小
1
>>> a.max() #求最大
4
>>> a.sum(axis=0) #求每列的和
array([3, 5, 7])
>>> a.sum(axis=1) #求每行的和
array([6, 9])
>>> a.min(axis=1) #求每行的最小值
array([1, 2])
>>> a.cumsum(axis=1) #求每行的累積和
array([[1, 3, 6],
[2, 5, 9]], dtype=int32)
通用操作
numpy中也有我們常見的數學函式sin
、exp
等,但在numpy中這些函式是對陣列中所有元素進行全域性操作,與以往的函式不同,這裡輸入輸出都為陣列。
>>> a = np.arange(3)
>>> a
array([0, 1, 2])
>>> np.exp(a) #對其中每個元素進行exp操作
array([ 1. , 2.71828183, 7.3890561 ])
>>> np.sqrt(a) #對其中每個元素進行sqrt操作(平方根)
array([ 0. , 1. , 1.41421356])
>>> b = np.array([2., -1., 4.])
>>> np.add(a, b) #兩個陣列相加
array([ 2., 0., 6.])
numpy中的一維陣列也可以進行索引、切片和迭代,這個和python中的lists有著相似的功能。
>>> a = np.arange(10)**3 #陣列中0-9每個元素對其3次方
>>> a
array([ 0, 1, 8, 27, 64, 125, 216, 343, 512, 729])
>>> a[2] #取第2+1個元素
8
>>> a[2:5] #取第2+1到第5+1個元素
array([ 8, 27, 64])
>>> a[:6:2] = -1000 # 與 a[0:6:2] = -1000相同; 從開始到第6+1個位置, 每兩個元素設為-1000
>>> a
array([-1000, 1, -1000, 27, -1000, 125, 216, 343, 512, 729])
>>> a[ : :-1] # 翻轉 a
array([ 729, 512, 343, 216, 125, -1000, 27, -1000, 1, -1000])
>>> for i in a: #列印a中的元素(每個元素+1列印)
... print(i+1)
730
513
344
217
126
-999
28
-999
2
-999
對於多維的陣列,可以對其特定“軸”(axis)進行操作:
import numpy as np
>>> def f(x,y):
... return x+y
>>> a = np.fromfunction(f,(5,4),dtype=int) #通過函式構造二維陣列,函式引數為陣列的座標
>>> a
array([[0, 1, 2, 3],
[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6],
[4, 5, 6, 7]])
>>> a[2,3] #取第2+1行第3+1個元素
5
>>> a[1,:] #取第1+1行的元素
array([1, 2, 3, 4])
>>> a[:,2] #取第2+1列的元素
array([2, 3, 4, 5, 6])
>>> a[0:2,:] #取第1-3行(不包括3)的元素
array([[0, 1, 2, 3],
[1, 2, 3, 4]])
>>> a[-1] #取最後一行的元素
array([4, 5, 6, 7])
numpy中也有一種用法可以在多維陣列簡潔表示,使用dots(...
)來表示同樣數量的:
,比如:
x為秩為5的陣列(有5個axis)
x[1,2,...]
相當於x[1,2,:,:,:]
x[...,3]
相當於x[:,:,:,:,3]
x[4,...,5,:]
相當於x[4,:,:,5,:]
>>> c = np.array( [[[ 0, 1, 2], # 三維陣列(包括兩個二維陣列)
... [ 10, 12, 13]],
... [[100,101,102],
... [110,112,113]]])
>>> c.shape
(2, 2, 3)
>>> c[1,...] # 與 c[1,:,:] 或 c[1] 相同
array([[100, 101, 102],
[110, 112, 113]])
>>> c[...,2] # 等同於 c[:,:,2]
array([[ 2, 13],
[102, 113]])
在對多維陣列進行迭代時,預設對第一維進行迭代:
>>> a = np.array([[0, 1, 2, 3],
[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6],
[4, 5, 6, 7]])
>>>for row in a:
... print(row)
[0 1 2 3]
[1 2 3 4]
[2 3 4 5]
[3 4 5 6]
[4 5 6 7]
可以使用flat來對陣列中所有單個元素進行迭代:
>>>for element in a.flat:
... print(element)
0
1
2
3
1
2
3
4
2
3
4
5
3
4
5
6
4
5
6
7
形狀(shape)操作
每個陣列物件都有一個對應元素數量的形狀
>>> a = np.floor(10*np.random.random((3,4)))
>>> a
array([[ 2., 8., 0., 6.],
[ 4., 5., 1., 1.],
[ 8., 9., 3., 6.]])
>>> a.shape #這裡的a的形狀為(3,4)也就是三行四列
(3, 4)
陣列的形狀是可以通過不同的命令進行改變的
>>> a.ravel() #將陣列進行平鋪
array([ 2., 8., 0., 6., 4., 5., 1., 1., 8., 9., 3., 6.])
>>> a.reshape(6,2) # 返回一個改變形狀的陣列
array([[ 2., 8.],
[ 0., 6.],
[ 4., 5.],
[ 1., 1.],
[ 8., 9.],
[ 3., 6.]])
>>> a.T # 返回一個a的轉置
array([[ 2., 4., 8.],
[ 8., 5., 9.],
[ 0., 1., 3.],
[ 6., 1., 6.]])
>>> a.T.shape #a轉置的形狀
(4, 3)
>>> a.shape #a的形狀
(3, 4)
reshape
命令與resize
命令功能相同,只是resize
命令在自身上面進行改動
>>> a
array([[ 2., 8., 0., 6.],
[ 4., 5., 1., 1.],
[ 8., 9., 3., 6.]])
>>> a.resize((2,6))
>>> a #注意:a發生了變化
array([[ 2., 8., 0., 6., 4., 5.],
[ 1., 1., 8., 9., 3., 6.]])
如果reshape
中某個引數賦予-1時,則這個引數會根據另一個引數進行自動填充
>>> a.reshape(3,-1) #之前a.shape為(2,6),reshape(3,-1)相當於(3,4)
array([[ 2., 8., 0., 6.],
[ 4., 5., 1., 1.],
[ 8., 9., 3., 6.]])
陣列合並操作
陣列之間可以相互進行合併,通過合併軸(axis)來實現
>>> import numpy as np
>>> a = np.floor(10*np.random.random((2,2))) #產生2×2的陣列,元素通過floor函式去掉後面的小數點
>>> a
array([[ 1., 0.],
[ 3., 2.]])
>>> b = np.floor(10*np.random.random((2,2)))
>>> b
array([[ 1., 3.],
[ 1., 8.]])
>>> np.vstack((a,b)) #垂直疊加陣列
array([[ 1., 0.],
[ 3., 2.],
[ 1., 3.],
[ 1., 8.]])
>>> np.hstack((a,b)) #水平疊加陣列
array([[ 1., 0., 1., 3.],
[ 3., 2., 1., 8.]])
注意,在多於二維陣列的操作中,vstack
對陣列中的第二軸進行堆疊,而hstack
則對第一軸進行堆疊。
對多維陣列進行切片
使用hspit
函式可以對陣列在水平軸上進行切割,可以指定切割後有多少相似陣列數量,和切割後有多少列來進行切割。
>>> a = np.floor(10*np.random.random((2,12)))
>>> a
array([[ 9., 5., 6., 3., 6., 8., 0., 7., 9., 7., 2., 7.],
[ 1., 4., 9., 2., 2., 1., 0., 6., 2., 2., 4., 0.]])
>>> np.hsplit(a,3) # 切割成3個相似陣列
[array([[ 9., 5., 6., 3.],
[ 1., 4., 9., 2.]]), array([[ 6., 8., 0., 7.],
[ 2., 1., 0., 6.]]), array([[ 9., 7., 2., 7.],
[ 2., 2., 4., 0.]])]
>>> np.hsplit(a,(3,4)) # 在第三列和第四列分別開刀
[array([[ 9., 5., 6.],
[ 1., 4., 9.]]), array([[ 3.],
[ 2.]]), array([[ 6., 8., 0., 7., 9., 7., 2., 7.],
[ 2., 1., 0., 6., 2., 2., 4., 0.]])]
同樣的vsplit
可以對陣列進行垂直切割。
複製和賦值
當在運算元組的時候,賦值和複製操作是不同的,這裡需要注意。
>>> a = np.arange(12)
>>> b = a # 創造一個新的物件b,
>>> b is a # a和b指向同一個陣列,只是名稱不同
True
>>> b.shape = 3,4 # 改變b的形狀,a的形狀也隨之改變
>>> a.shape
(3, 4)
為什麼會這樣,因為python在傳遞時傳遞的是引用,類似於C++中的引用,上面的a和b其實是完全相同的,因為它們指向一個相同的物件,只是操作時的名稱不同。如果想複製一個新的物件而不是引用,則需要使用其他操作符。
>>> c = a.view()
>>> c is a
False
>>> c.base is a # c是擁有a裡面元素的一個模子
True
>>> c.flags.owndata
False
>>>
>>> c.shape = 2,6 # a的形狀並沒有改變
>>> a.shape
(3, 4)
>>> c[0,4] = 1234 # a的資料發生了改變
>>> a
array([[ 0, 1, 2, 3],
[1234, 5, 6, 7],
[ 8, 9, 10, 11]])
這裡view
只是模子,但其實資料還是公用的,接下來的copy
操作則實現了完全的複製
>>> d = a.copy() # d是一個新的物件,內容是a的複製品
>>> d is a
False
>>> d.base is a # d與a並不共享資料
False
>>> d[0,0] = 9999
>>> a # b改變,a不改變
array([[ 0, 10, 10, 3],
[1234, 10, 10, 7],
[ 8, 10, 10, 11]])
廣播
廣播是numpy一個非常強大的功能。你可以在一個陣列中對其所有元素同時進行相同的操作,也可以同時操作兩個及以上相同形狀的多維陣列,對其中的元素進行操作:
>>> a = np.array([1.0, 2.0, 3.0])
>>> b = np.array([2.0, 2.0, 2.0])
>>> a * b #注意,這裡是a,b相對應的每個元素進行了相乘
array([ 2., 4., 6.])
>>> a = np.array([1.0, 2.0, 3.0])
>>> b = 2.0 #同上
>>> a * b
array([ 2., 4., 6.])
關於廣播功能還有很多,這裡只進行簡單的介紹。
更多請看:https://docs.scipy.org/doc/numpy/user/quickstart.html
高階索引功能
numpy中除了通過特定的整數和切片進行訪問,還有很多高階的索引訪問功能:
>>> a = np.arange(12)**2 # 對前12個元素進行平方
>>> i = np.array( [ 1,1,3,8,5 ] ) # 建立一個“索引”陣列
>>> a[i] # 取出相應索引位置的元素
array([ 1, 1, 9, 64, 25])
>>>
>>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] ) # 二維“索引”陣列
>>> a[j] # 取出的元素陣列與j形狀相同
array([[ 9, 16],
[81, 49]])
再舉一個例子,下面這段程式模擬了從一個“著色板”裡面取出顏色匯成一個色彩影像。
>>> palette = np.array( [ [0,0,0], # 黑
... [255,0,0], # 紅
... [0,255,0], # 綠
... [0,0,255], # 藍
... [255,255,255] ] ) # 白
>>> image = np.array( [ [ 0, 1, 2, 0 ], # 每個值和顏色陣列對應
... [ 0, 3, 4, 0 ] ] )
>>> palette[image] # 彩色圖
array([[[ 0, 0, 0],
[255, 0, 0],
[ 0, 255, 0],
[ 0, 0, 0]],
[[ 0, 0, 0],
[ 0, 0, 255],
[255, 255, 255],
[ 0, 0, 0]]])
當然也可以對多維進行操作:
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> i = np.array( [ [0,1],
... [1,2] ] )
>>> j = np.array( [ [2,1],
... [3,3] ] )
>>>
>>> a[i,j]
array([[ 2, 5],
[ 7, 11]])
>>>
>>> a[i,2]
array([[ 2, 6],
[ 6, 10]])
>>>
>>> a[:,j]
array([[[ 2, 1],
[ 3, 3]],
[[ 6, 5],
[ 7, 7]],
[[10, 9],
[11, 11]]])
為了程式的美觀和效率,一般這樣使用:
>>> l = [i,j]
>>> a[l] # 相當於a[i,j]
array([[ 2, 5],
[ 7, 11]])
深度學習常用的幾個numpy函式
numpy.prod:返回陣列內元素的乘積
>>> np.prod([1.,2.]) # 返回一維陣列內元素的乘積
2.0
>>> np.prod([[1.,2.],[3.,4.]]) # 返回二維陣列裡面所有元素的乘積
24.0
>>> np.prod([[1.,2.],[3.,4.]], axis=1) # 將每列的元素進行乘積
array([ 2., 12.])
>>> x = np.array([1, 2, 3], dtype=np.uint8) #還可以指定元素型別
>>> np.prod(x).dtype == np.uint
True
>>> x = np.array([1, 2, 3], dtype=np.int8)
>>> np.prod(x).dtype == np.int
True
numpy.pad:將陣列(矩陣)周圍進行填充
>>> a = np.array([[1,2,3],[2,3,4],[3,4,5]])
>>>a
Out[4]:
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
>>> np.lib.pad(a,1,'constant',constant_values=0) #將a陣列周圍填充寬度為1的常數0
Out[5]:
array([[0, 0, 0, 0, 0],
[0, 1, 2, 3, 0],
[0, 2, 3, 4, 0],
[0, 3, 4, 5, 0],
[0, 0, 0, 0, 0]])
相關文章
- 給深度學習入門者的Python快速教程 - Numpy和Matplotlib篇深度學習Python
- Python入門深度學習完整指南Python深度學習
- 容器快速入門完全指南
- Python科學計算 - Numpy快速入門Python
- 機器學習和深度學習概念入門機器學習深度學習
- numpy入門指南
- Python學習手冊(入門&爬蟲&資料分析&機器學習&深度學習)Python爬蟲機器學習深度學習
- 【乾貨】機器學習和深度學習概念入門機器學習深度學習
- 給深度學習入門者的Python快速教程 - 基礎篇深度學習Python
- Python入門_給小白的學習指南Python
- 深度學習快速入門3本書組合深度學習
- SpringData 完全入門指南Spring
- 自學機器學習入門指南機器學習
- 機器學習PAI快速入門機器學習AI
- Python機器學習會應用到哪些庫?Python入門學習Python機器學習
- 深度學習框架新手快速上手指南深度學習框架
- 機器學習的最佳入門學習資源機器學習
- Python中的Numpy入門教程Python
- MySQL 不完全入門指南MySql
- 快速入門——深度學習理論解析與實戰應用深度學習
- KNIME快速入門指南
- Markdown快速入門指南
- Bash快速入門指南
- 深度學習、機器學習、python、C++視訊深度學習機器學習PythonC++
- 機器學習&深度學習之路機器學習深度學習
- Chatbot大牛推薦:AI、機器學習、深度學習必看9大入門視訊AI機器學習深度學習
- TypeScript入門完全指南(基礎篇)TypeScript
- 深度學習入門筆記——Transform的使用深度學習筆記ORM
- python_numPy學習Python
- Python之numpy學習Python
- 【機器學習】--Python機器學習庫之Numpy機器學習Python
- Go 入門指南學習筆記Go筆記
- React入門指南(學習筆記)React筆記
- Python 程式設計師的 Golang 學習指南(III): 入門篇Python程式設計師Golang
- 機器學習之numpy和matplotlib學習(四)機器學習
- numpy 基礎入門 - 30分鐘學會numpy
- Objective C 快速入門學習一Object
- Go 快速入門指南 - URLGo