Python?的矩陣傳播機制Broadcasting和矩陣運算
一、Python的矩陣傳播機制(Broadcasting)
我們知道在深度學(xué)習(xí)中經(jīng)常要操作各種矩陣(matrix) ?;叵胍幌拢覀冊诓僮鲾?shù)組(list)的時候,經(jīng)常習(xí)慣于用**for循環(huán)(for-loop)**來對數(shù)組的每一個元素進行操作。例如:
my_list?=?[1,2,3,4] new_list?=?[] for?each?in?my_list: ????new_list.append(each*2) print(new_list)??#?輸出?[2,3,4,5]
如果是矩陣呢:
my_matrix?=?[[1,2,3,4], ?????????????[5,6,7,8]] new_matrix?=?[[],[]] for?i?in?range(2):???? ????for?j?in?range(4): ????????new_matrix[i].append(my_matrix[i][j]*2) print(new_matrix)#?輸出?[[2,?4,?6,?8],?[10,?12,?14,?16]]
實際上,上面的做法是十分的低效的!數(shù)據(jù)量小的話還不明顯,如果數(shù)據(jù)量大了,尤其是深度學(xué)習(xí)中我們處理的矩陣往往巨大,那用for循環(huán)去跑一個矩陣,可能要你幾個小時甚至幾天。
Python考慮到了這一點,這也是本文主要想介紹的**“Python的broadcasting”即傳播機制**。
先說一句,python中定義矩陣、處理矩陣,我們一般都用numpy這個庫。
二、下面展示什么是python的傳播機制
import?numpy?as?np#?先定義一個3×3矩陣 A: A?=?np.array( ????[[1,2,3], ?????[4,5,6], ?????[7,8,9]])? print("A:\n",A) print("\nA*2:\n",A*2)?#?直接用A乘以2 print("\nA+10:\n",A+10)?#?直接用A加上10
運行結(jié)果:
A:
[[1 2 3]
[4 5 6]
[7 8 9]]A*2:
[[ 2 4 6]
[ 8 10 12]
[14 16 18]]A+10:
[[11 12 13]
[14 15 16]
[17 18 19]]
接著,再看看矩陣×(+)矩陣:
#定義一個3×1矩陣(此時也可叫向量了) B?=?np.array([[10], ??????????????[100], ??????????????[1000]])? print("\nB:\n",B) print("\nA+B:\n",A+B)? print("\nA*B:\n",A*B)
運行結(jié)果:
B:
[[ 10]
[ 100]
[1000]]A+B:
[[ 11 12 13]
[ 104 105 106]
[1007 1008 1009]]A*B:
[[ 10 20 30]
[ 400 500 600]
[7000 8000 9000]]
可見,雖然A和B的形狀不一樣,一個是3×3,一個是3×1,但是我們在python中可以直接相加、相乘,相減相除也可以。也許看到這,大家都對broadcasting有感覺了。
用一個圖來示意一下:
所謂“傳播”,就是把一個數(shù)或者一個向量進行“復(fù)制”,從而作用到矩陣的每一個元素上。
有了這種機制,那進行向量和矩陣的運算,就太方便了!理解了傳播機制,就可以隨心所欲地對矩陣進行各種便捷的操作了。
三、利用numpy的內(nèi)置函數(shù)對矩陣進行操作
numpy內(nèi)置了很多的數(shù)學(xué)函數(shù),例如np.log(),np.abs(),np.maximum()等等上百種。直接把矩陣丟進去,就可以算出新矩陣! 示例:
print(np.log(A))
輸出把A矩陣每一個元素求log后得到的新矩陣:
array([[0.????????,?0.69314718,?1.09861229], ???????[1.38629436,?1.60943791,?1.79175947], ???????[1.94591015,?2.07944154,?2.19722458]])
再比如深度學(xué)習(xí)中常用的ReLU激活函數(shù),就是y=max(0,x),
也可以對矩陣直接運算:
X?=?np.array([[1,-2,3,-4],??????????????[-9,4,5,6]])Y?=?np.maximum(0,X)print(Y)
得到:
[[1 0 3 0] [0 4 5 6]]
更多的numpy數(shù)學(xué)函數(shù),可以參見文檔
四、定義自己的函數(shù)來處理矩陣
其實這才是我寫下本文的目的。。。前面扯了這么多,只是做個鋪墊( /ω\)
我昨天遇到個問題,就是我要對ReLU函數(shù)求導(dǎo),易知,y=max(0,x)的導(dǎo)函數(shù)是:y’ = 0 if x<0 y’ = 1 if x>0 但是這個y’(x)numpy里面沒有定義,需要自己構(gòu)建。即,我需要將矩陣X中的小于0的元素變?yōu)?,大于0的元素變?yōu)?。搞了好久沒弄出來,后來在StackOverflow上看到了解決辦法:
def?relu_derivative(x): ????x[x<0]?=?0 ????x[x>0]?=?1 ????return?x X?=?np.array([[1,-2,3,-4], ??????????????[-9,4,5,6]]) print(relu_derivative(X))
輸出:
[[1 0 1 0]
[0 1 1 1]]
**居然這么簡潔就出來了!??!**ミ?Д?彡 (?Д?#)
這個函數(shù)relu_derivative中最難以理解的地方,就是**x[x>0]**了。于是我試了一下:
X?=?np.array([[1,-2,3,-4], ??????????????[-9,4,5,6]]) print(X[X>0]) print(X[X<0])
輸出:
[1 3 4 5 6]
[-2 -4 -9]
它直接把矩陣X中滿足條件的元素取了出來!原來python對矩陣還有這種操作!
所以可以這么理解,X[X>0]相當(dāng)于一個“選擇器”,把滿足條件的元素選出來,然后直接全部賦值。
用這種方法,我們便可以定義各種各樣我們需要的函數(shù),然后對矩陣整體進行更新操作了!
五、總結(jié)
可以看出,python以及numpy對矩陣的操作簡直神乎其神,方便快捷又實惠。其實上面忘了寫一點,那就是計算機進行矩陣運算的效率要遠遠高于用for-loop來運算,
不信可以用跑一跑:
#?vetorization?vs?for?loop #?define?two?arrays?a,?b: a?=?np.random.rand(1000000) b?=?np.random.rand(1000000) #?for?loop?version: t1?=?time.time() c?=?0 for?i?in?range(1000000): ????c?+=?a[i]*b[i] t2?=?time.time() print(c) print("for?loop?version:"+str(1000*(t2-t1))+"ms") time1?=?1000*(t2-t1) #?vectorization?version: t1?=?time.time() c?=?np.dot(a,b) t2?=?time.time() print(c) print("vectorization?version:"+str(1000*(t2-t1))+"ms") time2?=?1000*(t2-t1) print("vectorization?is?faster?than?for?loop?by?"+str(time1/time2)+"?times!")
運行結(jié)果:
249765.8415288075
for loop version:627.4442672729492ms
249765.84152880745
vectorization version:1.5032291412353516ms
vectorization is faster than for loop by 417.39762093576525 times!
可見,用for方法和向量化方法,計算結(jié)果是一樣,但是后者比前者快了400多倍!
因此,在計算量很大的時候,我們要盡可能想辦法對數(shù)據(jù)進行Vectorizing,即“向量化” ,以便讓計算機進行矩陣運算。
到此這篇關(guān)于Python 的矩陣傳播機制Broadcasting和矩陣運算的文章就介紹到這了,更多相關(guān)Python矩陣傳播內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pandas去重復(fù)行并分類匯總的實現(xiàn)方法
這篇文章主要介紹了pandas去重復(fù)行并分類匯總的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01表格梳理python內(nèi)置數(shù)學(xué)模塊math分析詳解
這篇文章主要為大家介紹了python內(nèi)置數(shù)學(xué)模塊math的分析詳解,文中通過表格梳理的方式以便讓大家在學(xué)習(xí)過程中一目望去清晰明了,有需要的朋友可以借鑒參考下2021-10-10解決Jupyter notebook中.py與.ipynb文件的import問題
這篇文章主要介紹了解決Jupyter notebook中.py與.ipynb文件的import問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04