網(wǎng)站首頁 編程語言 正文
一、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,即“向量化”?,以便讓計算機進行矩陣運算。
原文鏈接:https://juejin.cn/post/7087396875187257358
相關(guān)推薦
- 2022-05-25 使用Python繪制三種概率曲線詳解_python
- 2023-10-14 uniapp 將base64字符串保存為圖片、Word、Excel、音頻、視頻等文件
- 2022-12-09 Flutter?CustomPaint自定義繪畫示例詳解_IOS
- 2022-02-26 小程序使用AntV F2自定義圖表和legend交互
- 2024-03-22 springboot 中 Getmapping獲取參數(shù)的方式
- 2023-03-27 python中的正則表達式,貪婪匹配與非貪婪匹配方式_python
- 2023-06-13 C++?ncnn模型驗證精度實現(xiàn)代碼_C 語言
- 2022-07-28 Go語言反射reflect.Value實現(xiàn)方法的調(diào)用_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支