TensorFlow實例(5.2)--MNIST手寫數字進階算法(卷積神經網絡CNN) 之 卷積tf.nn.conv2d

在這個文章裏,將通過數據的變化,來演示卷積神經網絡中卷積(Convolution),
卷積(Convolution)是卷積神經網絡的第一步,而本文的目的僅僅只是爲了說明strides與padding參數

TensorFlow實例(5.1)--MNIST手寫數字進階算法(卷積神經網絡CNN) 文章中,

第一層經網絡用到下列句子

tf.nn.conv2d(p1 ,w2,strides=[1,1,1,1],padding="SAME"

關於strides步長建議參考
TensorFlow實例(5.3)--MNIST手寫數字進階算法(卷積神經網絡CNN) 之 最大池化tf.nn.max_pool

在那個文章裏,對strides有更詳細的說明,這篇章主要是演算卷積過程中的數據變化


# -*- coding: utf-8 -*-
import numpy as np
import tensorflow as tf

def createData(height,width):
    ''' 輔助函數一
    爲了能更清晰的演示,建立這個函數,目的創建數據,即第一個參數x
    因爲多張圖片的傳入量不好表示,batch值就固定爲1
    本文是爲了演示卷積,所以初始通道 channels也固定爲1
    返回值類型爲numpy.array  
    '''
    size = height * width
    tmp = np.arange(size) + 1
    tmp = np.array([tmp]).reshape(-1,height,width,1)
    return tmp

def printData(npArr,message=""):
    '''
    打印出圖片數據
    多通道圖片都是模排顯示,如果寬度及通道數太大,
    會每行寬度的原因自動換行,
    '''
    npArr = npArr[0]
    print("-" * 40 + " 開始:" + message)
    print("圖像信息:高:%d; 寬:%d; 通道:%d。以下爲圖像數據" % (len(npArr),len(npArr[0]),len(npArr[0][0])))
    print("")
    for i in npArr:
        tmp = i.T
        strtmp = ''
        for j in tmp:
            strItem = ''.join([x.rjust(4) for x in j.astype(np.str).tolist()])
            strtmp = strtmp + ("" if strtmp == '' else " |") + strItem
        print(strtmp)
    print("-" * 40 + " 結束:" + message)
    print("")


data = createData(7,7).astype(np.float32) #卷積參數的設置使用np.float32
print(data.shape)#(1, 7, 7, 1) 四維數組,分別表示(圖片數batch,圖片高height,圖片寬width,通道數channel)

printData(data.astype(np.int))
weight = np.ones([5,5,1,3])
printData(weight)
'''
關於weight
因爲卷積層的構建要 data * w,爲了保證卷積後數值不變化,我將weight全設爲1,
四維數組,分別表示
1、切割圖片高height    
2、切割圖片寬width,
3、輸入通道數Input_channel  這裏應該與Data的最後一個參數相同
4、輸出的通道數             在mnist中第一層的卷積爲32層,爲了後面顯示方便,我只設了3
'''
#卷積
con = tf.nn.conv2d(data,weight,strides=[1,1,1,1],padding="SAME")
result = tf.Session().run(con)

#對卷積後的數據做做些微調
print(result.shape)#(1, 7, 7, 4)
printData(result,"一開始生成的數據有點精度問題")
result = result.astype(np.int) #計算後有些精度的問題,我們取整就好了
printData(result,"取整後的數據,發現三個通道的數據完全一樣,")

'''
卷積後的數據的說明
千萬!千萬!千萬! 不要被通道完全一樣誤導,在Mnist的例子中weight初始是一個正態分佈的集合,我這裏全是1
我使用1是爲了說明weight=np.ones([5,5,1,3]) 中的高寬(5,5),及strides=[1,1,1,1],padding="SAME"
高寬(5,5)的意思就是某個點爲中間,切割出來的5*5的小圖片所有值的和
如 第三行第三列爲,在DATA中是17  ,在卷積後的是425

   1   2   3   4   5   
   8   9  10  11  12  
  15  16  17  18  19     這些數加起來就是 425
  22  23  24  25  26  
  29  30  31  32  33 

第一行第一列爲,在DATA中是1  因爲上面和左邊沒數字,所以在卷積後的是 

  1  2  3
  8  9 10   這些數加起來就是 81
 15 16 17
 '''

#strides的設置變化
con = tf.nn.conv2d(data,weight,strides=[1,2,2,1],padding="SAME")
result = tf.Session().run(con)
result = result.astype(np.int) #計算後有些精度的問題,我們取整就好了
printData(result,"strides步度設置數據")
#步長就是每隔幾位取一個數值,strides=[1,2,2,1],就是是取1,3,5,7行,與1,3,5,7列

#padding設置
con = tf.nn.conv2d(data,weight,strides=[1,1,1,1],padding="VALID")
result = tf.Session().run(con)
result = result.astype(np.int) #計算後有些精度的問題,我們取整就好了
printData(result,"padding步度設置數據")
#padding只能取SAME 或VALID
#VALID表示,取的數字,爲中心,無法切割出5*5則不計算,如本例1,2,6,7行與列的值都無法取到5*5的圖片,被捨棄
#如果還是不太清楚,可以看我另一個文章


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章