網站首頁 編程語言 正文
一、Python的矩陣傳播機制(Broadcasting)
我們知道在深度學習中經常要操作各種矩陣(matrix)?。回想一下,我們在操作數組(list)的時候,經常習慣于用**for循環(for-loop)**來對數組的每一個元素進行操作。例如:
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]]
實際上,上面的做法是十分的低效的!數據量小的話還不明顯,如果數據量大了,尤其是深度學習中我們處理的矩陣往往巨大,那用for循環去跑一個矩陣,可能要你幾個小時甚至幾天。
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
運行結果:
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)
運行結果:
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有感覺了。
用一個圖來示意一下:
所謂“傳播”,就是把一個數或者一個向量進行“復制”,從而作用到矩陣的每一個元素上。
有了這種機制,那進行向量和矩陣的運算,就太方便了!理解了傳播機制,就可以隨心所欲地對矩陣進行各種便捷的操作了。
三、利用numpy的內置函數對矩陣進行操作
numpy內置了很多的數學函數,例如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]])
再比如深度學習中常用的ReLU激活函數,就是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數學函數,可以參見文檔
四、定義自己的函數來處理矩陣
其實這才是我寫下本文的目的。。。前面扯了這么多,只是做個鋪墊(?/ω\)
我昨天遇到個問題,就是我要對ReLU函數求導,易知,y=max(0,x)的導函數是:y’ = 0 if x<0 y’ = 1 if x>0 但是這個y’(x)numpy里面沒有定義,需要自己構建。即,我需要將矩陣X中的小于0的元素變為0,大于0的元素變為1。搞了好久沒弄出來,后來在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]]
**居然這么簡潔就出來了!!!**ミ?Д?彡 (?Д?#)
這個函數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]相當于一個“選擇器”,把滿足條件的元素選出來,然后直接全部賦值。
用這種方法,我們便可以定義各種各樣我們需要的函數,然后對矩陣整體進行更新操作了!
五、總結
可以看出,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!")
運行結果:
249765.8415288075
for?loop?version:627.4442672729492ms
249765.84152880745
vectorization?version:1.5032291412353516ms
vectorization?is?faster?than?for?loop?by?417.39762093576525?times!
可見,用for方法和向量化方法,計算結果是一樣,但是后者比前者快了400多倍!
因此,在計算量很大的時候,我們要盡可能想辦法對數據進行Vectorizing,即“向量化”?,以便讓計算機進行矩陣運算。
原文鏈接:https://juejin.cn/post/7087396875187257358
相關推薦
- 2022-08-06 C語言繪制簡單時鐘小程序_C 語言
- 2022-05-13 Headless Chrom自動化工具詳解
- 2022-08-10 Oracle數據庫如何使用exp和imp方式導數據_oracle
- 2024-04-05 idea使用docker生成鏡像(打包鏡像,導入鏡像,導出鏡像)
- 2022-04-25 C#使用NPOI設置Excel下拉選項_C#教程
- 2022-04-01 helm install Error: timed out waiting for the cond
- 2022-07-21 CUICatalog: Invalid asset name supplied: ‘‘
- 2022-05-17 bat批處理之字符串操作的實現_DOS/BAT
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支