最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2020年05月22日 10:36:31   作者:huachao1001  
這篇文章主要介紹了Tensorflow卷積實現(xiàn)原理+手寫python代碼實現(xiàn)卷積教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

從一個通道的圖片進行卷積生成新的單通道圖的過程很容易理解,對于多個通道卷積后生成多個通道的圖理解起來有點抽象。本文以通俗易懂的方式講述卷積,并輔以圖片解釋,能快速理解卷積的實現(xiàn)原理。最后手寫python代碼實現(xiàn)卷積過程,讓Tensorflow卷積在我們面前不再是黑箱子!

注意:

本文只針對batch_size=1,padding='SAME',stride=[1,1,1,1]進行實驗和解釋,其他如果不是這個參數(shù)設(shè)置,原理也是一樣。

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

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

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

接下來,我們以輸入為2個通道寬高分別為5的輸入、3*3的卷積核、1個通道寬高分別為5的輸出,作為一個例子展開。

2個通道,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]],
 
  ]

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

#卷積核,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ù),在接下來的計算對應(yīng)關(guān)系將按下圖所描述的方式進行。

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

def get_shape(tensor):
 [s1,s2,s3]= tensor.get_shape() 
 s1=int(s1)
 s2=int(s2)
 s3=int(s3)
 return s1,s2,s3

def chw2hwc(chw_tensor): 
 [c,h,w]=get_shape(chw_tensor) 
 cols=[]
 
 for i in range(c):
 #每個通道里面的二維數(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使用卷積核的時候,使用的格式是[k,k,in_c,out_c]。而我們在定義卷積核的時候,是按[in_c,k,k]的方式定義的,這里需要將[in_c,k,k]轉(zhuǎn)為[k,k,in_c],由于為了簡化工作量,我們規(guī)定輸出為1個通道,即out_c=1。所以這里我們可以直接簡單地對weights_data調(diào)用chw2hwc,再在第3維度擴充一下即可。

接下來,貼出完整的代碼:

import tensorflow as tf
import numpy as np
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]],
 
  ]
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,s3

def chw2hwc(chw_tensor): 
 [c,h,w]=get_shape(chw_tensor) 
 cols=[]
 
 for i in range(c):
 #每個通道里面的二維數(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

def 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 input

def tf_conv2d(input,weights):
 conv = tf.nn.conv2d(input, weights, strides=[1, 1, 1, 1], padding='SAME')
 return conv

def 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()

上面代碼有幾個地方需要提一下,

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

輸入完成chw轉(zhuǎn)hwc后,記得在第0維擴充維數(shù),因為卷積要求輸入為[n,h,w,c]

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

執(zhí)行上面代碼,運行結(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.]]

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

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

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

import numpy as np
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]] 
  ]
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)
 #保存計算結(jié)果
 rs=np.zeros([h,w],np.float32)
 #將輸入在指定該區(qū)域賦值,即除了4個邊界后,剩下的區(qū)域
 padding_fm[1:h+1,1:w+1]=fm 
 #對每個點為中心的區(qū)域遍歷
 for i in range(1,h+1):
 for j in range(1,w+1): 
  #取出當前點為中心的k*k區(qū)域
  roi=padding_fm[i-r:i+r+1,j-r:j+r+1]
  #計算當前點的卷積,對k*k個點點乘后求和
  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)

 #對每個feature map遍歷,從而對每個feature map進行卷積
 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 outputs

def 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() 

代碼無須太多解釋,直接看注釋。然后跑出來的結(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.]]

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

3 小結(jié)

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

以上這篇Tensorflow卷積實現(xiàn)原理+手寫python代碼實現(xiàn)卷積教程就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • flask 使用 flask_apscheduler 做定時循環(huán)任務(wù)的實現(xiàn)

    flask 使用 flask_apscheduler 做定時循環(huán)任務(wù)的實現(xiàn)

    這篇文章主要介紹了flask 使用 flask_apscheduler 做定時循環(huán)任務(wù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • python接口自動化(十七)--Json 數(shù)據(jù)處理---一次爬坑記(詳解)

    python接口自動化(十七)--Json 數(shù)據(jù)處理---一次爬坑記(詳解)

    這篇文章主要介紹了python Json 數(shù)據(jù)處理,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • python實現(xiàn)excel讀寫數(shù)據(jù)

    python實現(xiàn)excel讀寫數(shù)據(jù)

    這篇文章主要為大家詳細介紹了python操作EXCEL讀數(shù)據(jù)、寫數(shù)據(jù)的實例源碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • python中kmeans聚類實現(xiàn)代碼

    python中kmeans聚類實現(xiàn)代碼

    這篇文章主要為大家詳細介紹了python中kmeans聚類的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • Python實現(xiàn)繪制置信區(qū)間

    Python實現(xiàn)繪制置信區(qū)間

    置信區(qū)間是從觀測數(shù)據(jù)的統(tǒng)計量計算的一種估計值,它給出了一個可能包含具有特定置信水平的總體參數(shù)的值范圍,下面我們就來看看如何使用Python繪制置信區(qū)間吧
    2024-02-02
  • python保留小數(shù)位的三種實現(xiàn)方法

    python保留小數(shù)位的三種實現(xiàn)方法

    本文給大家分享python保留小數(shù)位的三種方法,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • Python實現(xiàn)位圖分割的效果

    Python實現(xiàn)位圖分割的效果

    目前網(wǎng)絡(luò)上大多為用C++或者Matlab編寫實現(xiàn)位圖分割,所以本文將使用Python實現(xiàn)位圖分割這一效果,代碼簡單易懂,感興趣的小伙伴可以關(guān)注一下
    2021-11-11
  • Python實現(xiàn)將圖片批量轉(zhuǎn)為PDF

    Python實現(xiàn)將圖片批量轉(zhuǎn)為PDF

    在日常辦公和處理圖片時,我們常常需要將多張圖片合并成一個PDF文件,所以本文為大家介紹了如何使用Python實現(xiàn)圖片批量轉(zhuǎn)為PDF,感興趣的可以了解下
    2024-12-12
  • 利用Pycharm連接服務(wù)器的全過程記錄

    利用Pycharm連接服務(wù)器的全過程記錄

    平時在遠程連接服務(wù)器,大多數(shù)都是使用 Xshell,其實對于經(jīng)常寫python的小伙伴,我們還有一個使用起來更加方便,就是常用的python集成IED工具Pycharm,這篇文章主要給大家介紹了關(guān)于如何利用Pycharm連接服務(wù)器的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • django表單中的按鈕獲取數(shù)據(jù)的實例分析

    django表單中的按鈕獲取數(shù)據(jù)的實例分析

    在本篇文章里小編給大家詳解了關(guān)于django表單中的按鈕獲取數(shù)據(jù)的內(nèi)容,需要的朋友們可以參考下。
    2020-07-07

最新評論

遵义市| 涡阳县| 临高县| 襄城县| 宿迁市| 嘉义市| 嘉禾县| 绥中县| 高青县| 靖州| 孟州市| 涞水县| 全南县| 扎赉特旗| 乃东县| 锡林浩特市| 桐梓县| 兰州市| 巴林左旗| 洞头县| 松阳县| 巨野县| 彭泽县| 扎鲁特旗| 福清市| 沧州市| 屯门区| 克拉玛依市| 含山县| 山东| 安仁县| 博野县| 陆丰市| 成武县| 青海省| 山阳县| 雅江县| 沂南县| 灵寿县| 淳安县| 苍山县|