- 飛槳PaddlePaddle深度學(xué)習(xí)實(shí)戰(zhàn)
- 劉祥龍等編著
- 2243字
- 2020-09-28 17:21:30
1.3.1 NumPy操作
NumPy(Numerical Python extension)是一個(gè)第三方的Python包,用于科學(xué)計(jì)算。這個(gè)庫(kù)的前身是1995年就開(kāi)始開(kāi)發(fā)的一個(gè)用于數(shù)組運(yùn)算的庫(kù)。經(jīng)過(guò)了長(zhǎng)時(shí)間的發(fā)展,它基本上成為絕大部分Python科學(xué)計(jì)算的基礎(chǔ)包,當(dāng)然也包括所有提供Python接口的深度學(xué)習(xí)框架。
1.基本模塊
(1)array模塊
數(shù)組(Array)是NumPy中最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)。其最關(guān)鍵的屬性是維度和元素類(lèi)型,在NumPy中,可以非常方便地創(chuàng)建各種不同類(lèi)型的多維數(shù)組,并且執(zhí)行一些基本操作。在深度學(xué)習(xí)中,如果神經(jīng)元之間的連接關(guān)系涉及的參數(shù)是數(shù)組,便可利用array模塊進(jìn)行設(shè)定,如代碼清單1-1所示。
代碼清單1-1 array的基本操作
import numpy as np a = [1, 2, 3, 4] # a是python中的list類(lèi)型 b = np.array(a) # 數(shù)組化之后b的類(lèi)型變?yōu)?array type(b) # b的類(lèi)型 <type 'numpy.ndarray'> b.shape # shape參數(shù)表示array的大小,這里是4 b.argmax() # 調(diào)用arg max()函數(shù)可以求得array中的最大值的索引,這里是3 b.max() # 調(diào)用max()函數(shù)可以求得array中的最大值,這里是4 b.mean() # 調(diào)用mean()函數(shù)可以求得array中的平均值,這里是2.5
注意到在導(dǎo)入NumPy的時(shí)候,代碼中將np作為NumPy的別名。這是一種習(xí)慣性的用法,后面的章節(jié)中也默認(rèn)這么使用。在機(jī)器學(xué)習(xí)中常用到的矩陣的轉(zhuǎn)置操作可以首先通過(guò)matrix構(gòu)建矩陣,再用transpose函數(shù)來(lái)實(shí)現(xiàn)轉(zhuǎn)置,如代碼清單1-2所示。
代碼清單1-2 NumPy中實(shí)現(xiàn)矩陣轉(zhuǎn)置
import numpy as np x=np.array(np.arange(12).reshape((3,4))) ''' [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] ''' t = x.transpose() ''' [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]] '''
對(duì)于一維的array,array支持所有Python列表(List)支持的下標(biāo)操作方法,所以在此沒(méi)有特別列出,如代碼清單1-3所示。
代碼清單1-3 NumPy基礎(chǔ)數(shù)學(xué)運(yùn)算
import numpy as np # 絕對(duì)值,1 a = np.abs(-1) # sin函數(shù),1.0 b = np.sin(np.pi/2) # tanh逆函數(shù),0.50000107157840523 c = np.arctanh(0.462118) # e為底的指數(shù)函數(shù),20.085536923187668 d = np.exp(3) # 2的3次方,8 f = np.power(2, 3) # 點(diǎn)積,1*3+2*4=11 g = np.dot([1, 2], [3, 4]) # 開(kāi)方,5 h = np.sqrt(25) # 求和,10 l = np.sum([1, 2, 3, 4]) # 平均值,5.5 m = np.mean([4, 5, 6, 7]) # 標(biāo)準(zhǔn)差,0.96824583655185426 p = np.std([1, 2, 3, 2, 1, 3, 2, 0])
(2)random模塊
NumPy中的隨機(jī)模塊包含了與隨機(jī)數(shù)產(chǎn)生和統(tǒng)計(jì)分布相關(guān)的基本函數(shù)。Python本身也有隨機(jī)模塊random,不過(guò)NumPy的random功能更豐富,隨機(jī)模塊一般會(huì)用于深度學(xué)習(xí)中一些隨機(jī)數(shù)的生成、seed的生成以及初始值的設(shè)定,具體的用法請(qǐng)看代碼清單1-4。
代碼清單1-4 random模塊相關(guān)操作
import numpy as np # 設(shè)置隨機(jī)數(shù)種子 np.random.seed(42) # 產(chǎn)生一個(gè)1x3,[0,1)之間的浮點(diǎn)型隨機(jī)數(shù) # array([[ 0.37454012, 0.95071431, 0.73199394]]) # 后面的例子就不在注釋中給出具體結(jié)果了 np.random.rand(1, 3) # 產(chǎn)生一個(gè)[0,1]之間的浮點(diǎn)型隨機(jī)數(shù) np.random.random() # 從a中有放回地隨機(jī)采樣7個(gè) a = np.array([1, 2, 3, 4, 5, 6, 7]) np.random.choice(a, 7) # 從a中無(wú)放回地隨機(jī)采樣7個(gè) np.random.choice(a, 7, replace=False) # 對(duì)a進(jìn)行亂序并返回一個(gè)新的array b = np.random.permutation(a) # 生成一個(gè)長(zhǎng)度為9的隨機(jī)bytes序列并作為str返回 # '\x96\x9d\xd1?\xe6\x18\xbb\x9a\xec' np.random.bytes(9)
隨機(jī)模塊可以很方便地做一些快速模擬去驗(yàn)證結(jié)論,在神經(jīng)網(wǎng)絡(luò)中也能夠做一些快速的網(wǎng)絡(luò)構(gòu)造。如考慮一個(gè)非常違反直覺(jué)的概率題:一個(gè)選手去參加一個(gè)TV秀,有三扇門(mén),其中一扇門(mén)后有獎(jiǎng)品,這扇門(mén)只有主持人知道。選手先隨機(jī)選一扇門(mén),但并不打開(kāi),主持人看到后,會(huì)打開(kāi)其余兩扇門(mén)中沒(méi)有獎(jiǎng)品的一扇門(mén)。然后主持人問(wèn)選手:是否要改變一開(kāi)始的選擇?
這個(gè)問(wèn)題的答案是應(yīng)該改變一開(kāi)始的選擇。在第一次選擇的時(shí)候,選錯(cuò)的概率是2/3,選對(duì)的概率是1/3。第一次選擇之后,主持人相當(dāng)于幫忙剔除了一個(gè)錯(cuò)誤答案,所以如果一開(kāi)始選的是錯(cuò)的,這時(shí)候換掉就對(duì)了;而如果一開(kāi)始就選對(duì)了,則這時(shí)候換掉就錯(cuò)了。根據(jù)以上分析,一開(kāi)始選錯(cuò)的概率就是換掉之后選對(duì)的概率(2/3),這個(gè)概率大于一開(kāi)始就選對(duì)的概率(1/3),所以應(yīng)該換。雖然道理上是這樣的,但是通過(guò)推理仍不明白怎么辦?沒(méi)關(guān)系,用隨機(jī)模擬就可以輕松得到答案。
這一部分請(qǐng)讀者作為練習(xí)自行完成。
2.廣播機(jī)制
對(duì)于array,默認(rèn)執(zhí)行對(duì)位運(yùn)算。涉及多個(gè)array的對(duì)位運(yùn)算需要array的維度一致,如果一個(gè)array的維度與另一個(gè)array的維度不一致,則在沒(méi)有對(duì)齊的維度上分別執(zhí)行對(duì)位運(yùn)算,這種機(jī)制稱(chēng)為廣播(Broadcasting),具體通過(guò)代碼清單1-5理解。
代碼清單1-5 廣播機(jī)制的理解
import numpy as np a = np.array([ [1, 2, 3], [4, 5, 6] ]) b = np.array([ [1, 2, 3], [1, 2, 3] ]) ''' 維度一樣的array,對(duì)位計(jì)算 array([[2, 4, 6], [5, 7, 9]]) ''' a + b c = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]) d = np.array([2, 2, 2]) ''' 廣播機(jī)制讓計(jì)算的表達(dá)式保持簡(jiǎn)潔 d和c的每一行分別進(jìn)行運(yùn)算 array([[ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11], [12, 13, 14]]) ''' c + d
3.向量化
讀者在1.2.1節(jié)已經(jīng)初步了解到,向量化在深度學(xué)習(xí)中的應(yīng)用十分廣泛,它是提升計(jì)算效率的主要手段之一,對(duì)于在機(jī)器學(xué)習(xí)中縮短每次訓(xùn)練的時(shí)間具有重要意義,當(dāng)可用工作時(shí)間不變的情況下,更短的單次訓(xùn)練時(shí)間可以讓程序員有更多的測(cè)試機(jī)會(huì),進(jìn)而更快、更好地調(diào)整神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)和參數(shù)。代碼清單1-6~1-8通過(guò)一個(gè)矩陣相乘的例子展示了向量化對(duì)于代碼計(jì)算速度的提升效果。
在代碼清單1-6中首先導(dǎo)入了numpy和time庫(kù),它們分別被用于數(shù)學(xué)計(jì)算和統(tǒng)計(jì)運(yùn)行時(shí)間。然后準(zhǔn)備數(shù)據(jù),這里初始化兩個(gè)1000000維的隨機(jī)向量v1和v2,v作為計(jì)算結(jié)果初始化為零。
代碼清單1-6 導(dǎo)入庫(kù)和數(shù)據(jù)初始化
import numpy as np import time #初始化兩個(gè)1000000維的隨機(jī)向量v1,v2用于矩陣相乘計(jì)算 v1 = np.random.rand(1000000) v2 = np.random.rand(1000000) v = 0
在代碼清單1-7中,設(shè)置變量tic和toc分別為計(jì)算開(kāi)始和結(jié)束時(shí)間。在非向量化版本中,兩個(gè)向量相乘的計(jì)算過(guò)程使用for循環(huán)實(shí)現(xiàn)。
代碼清單1-7 矩陣相乘(非向量化版本)
#矩陣相乘-非向量化版本 tic = time.time() for i in range(1000000): v += v1[i] * v2[i] toc = time.time() print("非向量化-計(jì)算時(shí)間:" + str((toc - tic)*1000)+"ms"+"\n")
在代碼清單1-8中,同樣使用變量tic和toc記錄計(jì)算開(kāi)始和結(jié)束時(shí)間。向量化版本使用NumPy庫(kù)的numpy.dot()計(jì)算矩陣相乘。
代碼清單1-8 矩陣相乘(向量化版本)
#矩陣相乘-向量化版本 tic = time.time() v = np.dot(v1, v2) toc = time.time() print("向量化-計(jì)算時(shí)間:" + str((toc - tic)*1000)+"ms")
為了保證計(jì)算結(jié)果相同,我們輸出了二者的計(jì)算結(jié)果,確保計(jì)算無(wú)誤。最后的輸出結(jié)果為“非向量化-計(jì)算時(shí)間為578.0208ms,向量化-計(jì)算時(shí)間為1.1038ms”。可以觀(guān)察到效率提升效果十分顯著。非向量化版本計(jì)算時(shí)間約為向量化版本計(jì)算時(shí)間的500倍。可見(jiàn)向量化對(duì)于計(jì)算速度的提升非常顯著,尤其在長(zhǎng)時(shí)間的深度學(xué)習(xí)訓(xùn)練中,向量化可以幫助開(kāi)發(fā)者節(jié)省更多時(shí)間。
- Python快樂(lè)編程:人工智能深度學(xué)習(xí)基礎(chǔ)
- R語(yǔ)言經(jīng)典實(shí)例(原書(shū)第2版)
- 算法零基礎(chǔ)一本通(Python版)
- 深入理解Django:框架內(nèi)幕與實(shí)現(xiàn)原理
- Visual C++數(shù)字圖像模式識(shí)別技術(shù)詳解
- Python 3網(wǎng)絡(luò)爬蟲(chóng)實(shí)戰(zhàn)
- Python程序設(shè)計(jì)
- Python機(jī)器學(xué)習(xí)實(shí)戰(zhàn)
- Elasticsearch for Hadoop
- C語(yǔ)言程序設(shè)計(jì)上機(jī)指導(dǎo)與習(xí)題解答(第2版)
- 劍指大數(shù)據(jù):企業(yè)級(jí)數(shù)據(jù)倉(cāng)庫(kù)項(xiàng)目實(shí)戰(zhàn)(在線(xiàn)教育版)
- C++ Application Development with Code:Blocks
- 從零開(kāi)始:C語(yǔ)言快速入門(mén)教程
- 關(guān)系數(shù)據(jù)庫(kù)與SQL Server 2012(第3版)
- Pandas 1.x Cookbook