久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Tensorflow卷積實(shí)現(xiàn)原理+手寫(xiě)python代碼實(shí)現(xiàn)卷積教程

瀏覽:56日期:2022-07-24 17:57:19

從一個(gè)通道的圖片進(jìn)行卷積生成新的單通道圖的過(guò)程很容易理解,對(duì)于多個(gè)通道卷積后生成多個(gè)通道的圖理解起來(lái)有點(diǎn)抽象。本文以通俗易懂的方式講述卷積,并輔以圖片解釋?zhuān)芸焖倮斫饩矸e的實(shí)現(xiàn)原理。最后手寫(xiě)python代碼實(shí)現(xiàn)卷積過(guò)程,讓Tensorflow卷積在我們面前不再是黑箱子!

注意:

本文只針對(duì)batch_size=1,padding=’SAME’,stride=[1,1,1,1]進(jìn)行實(shí)驗(yàn)和解釋?zhuān)渌绻皇沁@個(gè)參數(shù)設(shè)置,原理也是一樣。

1 Tensorflow卷積實(shí)現(xiàn)原理

先看一下卷積實(shí)現(xiàn)原理,對(duì)于in_c個(gè)通道的輸入圖,如果需要經(jīng)過(guò)卷積后輸出out_c個(gè)通道圖,那么總共需要in_c * out_c個(gè)卷積核參與運(yùn)算。參考下圖:

Tensorflow卷積實(shí)現(xiàn)原理+手寫(xiě)python代碼實(shí)現(xiàn)卷積教程

如上圖,輸入為[h:5,w:5,c:4],那么對(duì)應(yīng)輸出的每個(gè)通道,需要4個(gè)卷積核。上圖中,輸出為3個(gè)通道,所以總共需要3*4=12個(gè)卷積核。對(duì)于單個(gè)輸出通道中的每個(gè)點(diǎn),取值為對(duì)應(yīng)的一組4個(gè)不同的卷積核經(jīng)過(guò)卷積計(jì)算后的和。

接下來(lái),我們以輸入為2個(gè)通道寬高分別為5的輸入、3*3的卷積核、1個(gè)通道寬高分別為5的輸出,作為一個(gè)例子展開(kāi)。

2個(gè)通道,5*5的輸入定義如下:

#輸入,shape=[c,h,w]input_data=[ [[1,0,1,2,1], [0,2,1,0,1], [1,1,0,2,0], [2,2,1,1,0], [2,0,1,2,0]], [[2,0,2,1,1], [0,1,0,0,2], [1,0,0,2,1], [1,1,2,1,0], [1,0,1,1,1]], ]

對(duì)于輸出為1通道m(xù)ap,根據(jù)前面計(jì)算方法,需要2*1個(gè)卷積核。定義卷積核如下:

#卷積核,shape=[in_c,k,k]=[2,3,3]weights_data=[ [[ 1, 0, 1], [-1, 1, 0], [ 0,-1, 0]], [[-1, 0, 1], [ 0, 0, 1], [ 1, 1, 1]] ]

上面定義的數(shù)據(jù),在接下來(lái)的計(jì)算對(duì)應(yīng)關(guān)系將按下圖所描述的方式進(jìn)行。

Tensorflow卷積實(shí)現(xiàn)原理+手寫(xiě)python代碼實(shí)現(xiàn)卷積教程

由于Tensorflow定義的tensor的shape為[n,h,w,c],這里我們可以直接把n設(shè)為1,即batch size為1。還有一個(gè)問(wèn)題,就是我們剛才定義的輸入為[c,h,w],所以需要將[c,h,w]轉(zhuǎn)為[h,w,c]。轉(zhuǎn)換方式如下,注釋已經(jīng)解釋很詳細(xì),這里不再解釋。

def get_shape(tensor): [s1,s2,s3]= tensor.get_shape() s1=int(s1) s2=int(s2) s3=int(s3) return s1,s2,s3def chw2hwc(chw_tensor): [c,h,w]=get_shape(chw_tensor) cols=[] for i in range(c): #每個(gè)通道里面的二維數(shù)組轉(zhuǎn)為[w*h,1]即1列 line = tf.reshape(chw_tensor[i],[h*w,1]) cols.append(line) #橫向連接,即將所有豎直數(shù)組橫向排列連接 input = tf.concat(cols,1)#[w*h,c] #[w*h,c]-->[h,w,c] input = tf.reshape(input,[h,w,c]) return input

同理,Tensorflow使用卷積核的時(shí)候,使用的格式是[k,k,in_c,out_c]。而我們?cè)诙x卷積核的時(shí)候,是按[in_c,k,k]的方式定義的,這里需要將[in_c,k,k]轉(zhuǎn)為[k,k,in_c],由于為了簡(jiǎn)化工作量,我們規(guī)定輸出為1個(gè)通道,即out_c=1。所以這里我們可以直接簡(jiǎn)單地對(duì)weights_data調(diào)用chw2hwc,再在第3維度擴(kuò)充一下即可。

接下來(lái),貼出完整的代碼:

import tensorflow as tfimport numpy as npinput_data=[ [[1,0,1,2,1], [0,2,1,0,1], [1,1,0,2,0], [2,2,1,1,0], [2,0,1,2,0]], [[2,0,2,1,1], [0,1,0,0,2], [1,0,0,2,1], [1,1,2,1,0], [1,0,1,1,1]], ]weights_data=[ [[ 1, 0, 1], [-1, 1, 0], [ 0,-1, 0]], [[-1, 0, 1], [ 0, 0, 1], [ 1, 1, 1]] ]def get_shape(tensor): [s1,s2,s3]= tensor.get_shape() s1=int(s1) s2=int(s2) s3=int(s3) return s1,s2,s3def chw2hwc(chw_tensor): [c,h,w]=get_shape(chw_tensor) cols=[] for i in range(c): #每個(gè)通道里面的二維數(shù)組轉(zhuǎn)為[w*h,1]即1列 line = tf.reshape(chw_tensor[i],[h*w,1]) cols.append(line) #橫向連接,即將所有豎直數(shù)組橫向排列連接 input = tf.concat(cols,1)#[w*h,c] #[w*h,c]-->[h,w,c] input = tf.reshape(input,[h,w,c]) return inputdef hwc2chw(hwc_tensor): [h,w,c]=get_shape(hwc_tensor) cs=[] for i in range(c): #[h,w]-->[1,h,w] channel=tf.expand_dims(hwc_tensor[:,:,i],0) cs.append(channel) #[1,h,w]...[1,h,w]---->[c,h,w] input = tf.concat(cs,0)#[c,h,w] return inputdef tf_conv2d(input,weights): conv = tf.nn.conv2d(input, weights, strides=[1, 1, 1, 1], padding=’SAME’) return convdef main(): const_input = tf.constant(input_data , tf.float32) const_weights = tf.constant(weights_data , tf.float32 ) input = tf.Variable(const_input,name='input') #[2,5,5]------>[5,5,2] input=chw2hwc(input) #[5,5,2]------>[1,5,5,2] input=tf.expand_dims(input,0) weights = tf.Variable(const_weights,name='weights') #[2,3,3]-->[3,3,2] weights=chw2hwc(weights) #[3,3,2]-->[3,3,2,1] weights=tf.expand_dims(weights,3) #[b,h,w,c] conv=tf_conv2d(input,weights) rs=hwc2chw(conv[0]) init=tf.global_variables_initializer() sess=tf.Session() sess.run(init) conv_val = sess.run(rs) print(conv_val[0]) if __name__==’__main__’: main()

上面代碼有幾個(gè)地方需要提一下,

由于輸出通道為1,因此可以對(duì)卷積核數(shù)據(jù)轉(zhuǎn)換的時(shí)候直接調(diào)用chw2hwc,如果輸入通道不為1,則不能這樣完成轉(zhuǎn)換。

輸入完成chw轉(zhuǎn)hwc后,記得在第0維擴(kuò)充維數(shù),因?yàn)榫矸e要求輸入為[n,h,w,c]

為了方便我們查看結(jié)果,記得將hwc的shape轉(zhuǎn)為chw

執(zhí)行上面代碼,運(yùn)行結(jié)果如下:

[[ 2. 0. 2. 4. 0.] [ 1. 4. 4. 3. 5.] [ 4. 3. 5. 9. -1.] [ 3. 4. 6. 2. 1.] [ 5. 3. 5. 1. -2.]]

這個(gè)計(jì)算結(jié)果是怎么計(jì)算出來(lái)的?為了讓大家更清晰的學(xué)習(xí)其中細(xì)節(jié),我特地制作了一個(gè)GIF圖,看完這個(gè)圖后,如果你還看不懂卷積的計(jì)算過(guò)程,你可以來(lái)打我。。。。

Tensorflow卷積實(shí)現(xiàn)原理+手寫(xiě)python代碼實(shí)現(xiàn)卷積教程

2 手寫(xiě)Python代碼實(shí)現(xiàn)卷積

自己實(shí)現(xiàn)卷積時(shí),就無(wú)須將定義的數(shù)據(jù)[c,h,w]轉(zhuǎn)為[h,w,c]了。

import numpy as npinput_data=[ [[1,0,1,2,1], [0,2,1,0,1], [1,1,0,2,0], [2,2,1,1,0], [2,0,1,2,0]], [[2,0,2,1,1], [0,1,0,0,2], [1,0,0,2,1], [1,1,2,1,0], [1,0,1,1,1]] ]weights_data=[ [[ 1, 0, 1], [-1, 1, 0], [ 0,-1, 0]], [[-1, 0, 1], [ 0, 0, 1], [ 1, 1, 1]] ]#fm:[h,w]#kernel:[k,k]#return rs:[h,w] def compute_conv(fm,kernel): [h,w]=fm.shape [k,_]=kernel.shape r=int(k/2) #定義邊界填充0后的map padding_fm=np.zeros([h+2,w+2],np.float32) #保存計(jì)算結(jié)果 rs=np.zeros([h,w],np.float32) #將輸入在指定該區(qū)域賦值,即除了4個(gè)邊界后,剩下的區(qū)域 padding_fm[1:h+1,1:w+1]=fm #對(duì)每個(gè)點(diǎn)為中心的區(qū)域遍歷 for i in range(1,h+1): for j in range(1,w+1): #取出當(dāng)前點(diǎn)為中心的k*k區(qū)域 roi=padding_fm[i-r:i+r+1,j-r:j+r+1] #計(jì)算當(dāng)前點(diǎn)的卷積,對(duì)k*k個(gè)點(diǎn)點(diǎn)乘后求和 rs[i-1][j-1]=np.sum(roi*kernel) return rs def my_conv2d(input,weights): [c,h,w]=input.shape [_,k,_]=weights.shape outputs=np.zeros([h,w],np.float32) #對(duì)每個(gè)feature map遍歷,從而對(duì)每個(gè)feature map進(jìn)行卷積 for i in range(c): #feature map==>[h,w] f_map=input[i] #kernel ==>[k,k] w=weights[i] rs =compute_conv(f_map,w) outputs=outputs+rs return outputsdef main(): #shape=[c,h,w] input = np.asarray(input_data,np.float32) #shape=[in_c,k,k] weights = np.asarray(weights_data,np.float32) rs=my_conv2d(input,weights) print(rs) if __name__==’__main__’: main()

代碼無(wú)須太多解釋?zhuān)苯涌醋⑨尅H缓笈艹鰜?lái)的結(jié)果如下:

[[ 2. 0. 2. 4. 0.] [ 1. 4. 4. 3. 5.] [ 4. 3. 5. 9. -1.] [ 3. 4. 6. 2. 1.] [ 5. 3. 5. 1. -2.]]

對(duì)比發(fā)現(xiàn),跟Tensorflow的卷積結(jié)果是一樣的。

3 小結(jié)

本文中,我們學(xué)習(xí)了Tensorflow的卷積實(shí)現(xiàn)原理,通過(guò)也通過(guò)python代碼實(shí)現(xiàn)了輸出通道為1的卷積,其實(shí)輸出通道數(shù)不影響我們學(xué)習(xí)卷積原理。后面如果有機(jī)會(huì)的話,我們?nèi)?shí)現(xiàn)一個(gè)更加健全,完整的卷積。

以上這篇Tensorflow卷積實(shí)現(xiàn)原理+手寫(xiě)python代碼實(shí)現(xiàn)卷積教程就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 古典武侠第一页久久777 | 99re在线播放视频 | 9久久婷婷国产综合精品性色 | 亚洲国产激情 | 欧美日韩免费在线 | 成人欧美一区二区三区视频xxx | 国产在线播 | 在线一区二区三区 | 午夜精品网站 | 久久精品久久久 | 日韩视频中文字幕 | 午夜国产精品视频 | 国产精品国产精品国产专区不片 | 国产小视频在线播放 | 久久综合一区二区三区 | 亚洲免费一区二区 | 一级毛片,一级毛片 | 国产精品国产精品国产专区不片 | 亚洲男人的天堂在线 | 久久久精品免费观看 | 成人欧美一区二区三区 | 精品久久久久久久久久 | 精品国产不卡一区二区三区 | 玖玖国产精品视频 | 一区二区三区免费av | 亚洲国产天堂久久综合 | 亚洲一区二区 | 久久久久久久 | 精品影院| 亚洲精品电影网在线观看 | 午夜视频在线观看免费视频 | 狠狠躁日日躁夜夜躁东南亚 | 欧美成在线视频 | 天堂一区二区三区 | 日本黄色大片免费 | 天天干欧美| 日韩在线欧美 | 黄色免费在线观看 | zzz444成人天堂7777 | 精品久久久久久亚洲综合网 | 成人亚洲精品久久久久软件 |