卷積(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的圖片,被捨棄
#如果還是不太清楚,可以看我另一個文章