CNN卷積神經網絡的本質就是卷積運算
維度的調整:
tf.reshape(imageInput,[-1,28,28,1])
imageInput為[None,784],N行* 784維 調整為 M28行28列*1通道 即:二維轉化為四維數據
參數一:等價于運算結果M
參數二:28 28 表示圖片的寬高信息 1表示channel通道個數,因為當前讀取的是灰度圖故為1
定義變量:
tf.Variable(tf.truncated_normal([5,5,1,32],stddev = 0.1))
參數一:最終生成的維度,這里設置為5*5的卷積內核大小,輸入的維度;輸入的維度或當前通道數或imageInputReshape最后一位為1,輸出為32維
參數二:期望方差
layer1:激勵函數+卷積運算
imageInputReshape : w0:5,5,1,32
通過激勵函數,來完成當前的卷積運算
tf.nn.relu(tf.nn.conv2d(imageInputReshape,w0,strides=1,1,1,1],padding='SAME')+b0)
參數一:輸入圖像數據,imageInputReshape是一個M2828*1
參數二:權重矩陣 w0是一個5,5,1,32的維度
參數三:每次移動的步長,這里的步長是個四維的
參數四:SAME表示卷積核可以停留在圖像的邊緣
其實池化就等價于采樣
創建池化層,是得數據量大大減少;
tf.nn.max_pool(layer1,ksize=[1,4,4,1],strides=[1,4,4,1],padding='SAME')
參數一:layer1
參數二:ksize=[1,4,4,1] 表明輸入數據是一個M282832 這個數據與對應的ksize相除即M/1 28/4 28/4 32/1=M7732即為池化層的輸出結果
參數三:池化層的步長
參數四:池化層是否可以停留在圖像的邊緣
而max_pool即將[1 2 3 4]結果池化層后變為一維[4],即原來數組中最大的內容
#1 import 導包
import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
# 2 load data 加載數據
mnist = input_data.read_data_sets('E:\\Jupyter_workspace\\study\\DL\\MNIST_data',one_hot = True)
# 3 input
imageInput = tf.placeholder(tf.float32,[None,784]) # 輸入圖片為28*28=784維,圖片個數為None
labeInput = tf.placeholder(tf.float32,[None,10]) # 10表示標簽
# 4 data reshape 數據維度的調整
# [None,784]->M*28*28*1 2D->4D 28*28 wh 1 channel
imageInputReshape = tf.reshape(imageInput,[-1,28,28,1])
# 5 實現卷積運算 w0 : 卷積內核 5*5 out:32 in:1
w0 = tf.Variable(tf.truncated_normal([5,5,1,32],stddev = 0.1))#w0為權重矩陣,作為卷積的內核來使用,卷積核大小為5*5,輸出為32維 輸入為1維
b0 = tf.Variable(tf.constant(0.1,shape=[32]))#偏移矩陣一般放在卷積運算之后來進行相加,故相加的時候改變的只是最后一個維度,所以必須讓偏移矩陣和權重矩陣的最后一個維度保持一致,即32維
# 6 layer1:激勵函數+卷積運算
# imageInputReshape : M*28*28*1 w0:5,5,1,32
layer1 = tf.nn.relu(tf.nn.conv2d(imageInputReshape,w0,strides=[1,1,1,1],padding='SAME')+b0)#卷積運算
# M*28*28*32
# pool 采樣 數據量減少很多M*28*28*32 => M*7*7*32
layer1_pool = tf.nn.max_pool(layer1,ksize=[1,4,4,1],strides=[1,4,4,1],padding='SAME')#創建池化層
# [1 2 3 4]->[4]# 7 layer2 out : 激勵函數+乘加運算: softmax是一個回歸計算函數(激勵函數 + 乘加運算)
# [7*7*32,1024]
#實現第二層layer2輸出層out:(激勵函數+乘加運算)作為另外一個乘加運算的輸入內容,最后的計算結果是一個softmax回歸計算函數
w1 = tf.Variable(tf.truncated_normal([7*7*32,1024],stddev=0.1))#二維
b1 = tf.Variable(tf.constant(0.1,shape=[1024]))
h_reshape = tf.reshape(layer1_pool,[-1,7*7*32])# M*7*7*32 -> N*N1 維度轉換 將四維數據轉換維二維數據
# [N*7*7*32] [7*7*32,1024] = N*1024
h1 = tf.nn.relu(tf.matmul(h_reshape,w1)+b1)
# 7.1 softMax
w2 = tf.Variable(tf.truncated_normal([1024,10],stddev=0.1))
b2 = tf.Variable(tf.constant(0.1,shape=[10]))
pred = tf.nn.softmax(tf.matmul(h1,w2)+b2)# N*1024 1024*10 = N*10 最后的輸出結果維N*10 N表示N張圖片,10表示0-9這10個維度上分布的概率
# N*10( 概率 )N1【0.1 0.2 0.4 0.1 0.2 。。。】0.1表示0出現的概率 0.2表示1出現的概率 0.4表示2出現的概率依此類推
# label。 【0 0 0 0 1 0 0 0。。。】
loss0 = labeInput*tf.log(pred)
loss1 = 0
# 7.2
for m in range(0,500):#測試訓練時每次500張for n in range(0,10):#label標簽總共有10個維度,需要把這10個維度中的內容進行累加loss1 = loss1 - loss0[m,n]
loss = loss1/500#總共有500組數據# 8 train訓練過程,讓當前的誤差盡可能的減小
train = tf.train.GradientDescentOptimizer(0.01).minimize(loss)#梯度下降法,每次下降0.01,目標是盡可能的縮小當前loss的步長
# 9 run
with tf.Session() as sess:sess.run(tf.global_variables_initializer())#完成所以圖片的初始for i in range(100):images,labels = mnist.train.next_batch(500)#分別把圖片和標簽讀取出來,每次讀取500張圖片進行訓練sess.run(train,feed_dict={imageInput:images,labeInput:labels})#完成pred的獲取pred_test = sess.run(pred,feed_dict={imageInput:mnist.test.images,labeInput:labels})#獲得最終的預測結果,是10維的;與label標簽都一樣也都是10維的acc = tf.equal(tf.arg_max(pred_test,1),tf.arg_max(mnist.test.labels,1))#比較pred和label最大值是否相等acc_float = tf.reduce_mean(tf.cast(acc,tf.float32))#轉換均值為float浮點類型acc_result = sess.run(acc_float,feed_dict={imageInput:mnist.test.images,labeInput:mnist.test.labels})print(acc_result)