計算機視覺基礎系列(python與opencv的操作與運用/tensorflow的基礎介紹)(二十六)---手寫數字識別之CNN(2)

首先我們需要知道池化層的作用,上一篇博客有說明,可以點擊這裏查看

import tensorflow as tf
import numpy as np
import random
from tensorflow.examples.tutorials.mnist import input_data      # 將input_data用來讀取圖片
# 1.數據裝載
minst = input_data.read_data_sets('minst_data/', one_hot=True)
# 兩個參數,第一個是minst文件夾的路徑,第二個參數是one-hot,它是布爾類型,對於一個數組來說,這個數組定義爲one-hot,那麼這個數組中的元素,有一個元素爲1的話,那麼其他元素全爲0
# 接下來就是搭建神經網絡,要明確我們的輸入,第一是圖片的輸入,第二要完成標籤的輸入
imageInput = tf.placeholder(tf.float32, [None, 784])         # 28*28的,所以是784,第一個維度是輸入的圖片的個數
labelInput = tf.placeholder(tf.float32, [None, 10])         # 第一個是圖片的個數,第二個參數是0-9,所以是10
# 對當前的維度進行重新調整
imageInputReshape = tf.reshape(imageInput, [-1, 28, 28, 1])      # 數據維度的調整 data reshape 由[None,784]-->M*28*28*1 即2維轉換成4維
# 完成維度的調整,將一個n行乘以一個784維的調整成一個m行乘以28行乘以28列一個通道的數據,所以將一個兩維的數據轉化成一個4維的數據
# 28*28表示圖片的寬高信息,後謎案的1代表的是顏色通道,這裏是灰度圖,所以這裏的channel是1,m是這樣經過這樣經過轉換之後的剩餘的這些元素共同構成的這樣的一個m
# 數據準備完之後,接下來就可以準備進行卷積運算
# 神經網絡其實第一步完成的就是卷積運算
# 實現卷積運算,首先需要定義幾個參數:
w0 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1))
# Variable定義一個變量,生成一個滿足正態分佈的數據,在tesorflow中有一個方法是truncated_normal,其中的參數是生成數據的維度,第二個參數是期望和方差stddev
# 這裏我們想生成的w0是進行卷積運算的內核,那麼這個內核是多大呢,我們將它的大小設置爲5*5,另外輸入的維度爲1,可以看做當前通道的個數channel,因爲是灰度圖,輸出爲32維度
b0 = tf.Variable(tf.constant(0.1, shape=[32]))        # 定義偏置,定義爲一個常量,定義爲32維,實際上是改變的是最後的一個維度
# 接下來就是實現卷積層
# 第一層是激勵函數+乘加運算
layer1 = tf.nn.relu(tf.nn.conv2d(imageInputReshape, w0, strides=[1, 1, 1, 1], padding='SAME')+b0)
# 在當前的卷積運算中,包含以下數據,
# 1.輸入數據(imageInputReshape),它是[M,28, 28, 1]的維度 2.w0是一個[5, 5, 1, 32]這個維度,3,pandding步長:每次用的步長,SAME表明卷積核可以停留在圖像的邊緣
# 卷積神經網絡在每一層的計算完之後是多一個池化層的,不像普通的神經網絡,卷積完之後就是直接作爲下一層的輸入了
# pool 下采樣,數據量減少很多,如何進行減小呢:這裏的ksize的[1, 4, 4, 1]以此與數據量的四維進行相除,即爲M*28*28*32 ===>M*7*7*32,後面的strides爲步長,padding爲邊緣
layer1_pool = tf.nn.max_pool(layer1, ksize=[1, 4, 4, 1], strides=[1, 4, 4, 1], padding='SAME')
# max_pool 的作用是防止過擬合
# 普通的神經網絡的輸出層是:激勵函數加上乘加運算即可,在這裏,卷積神經網絡的輸出是:(激勵函數+乘加運算)的一個softmax函數
w1 = tf.Variable(tf.truncated_normal([7*7*32, 1024], stddev=0.1))
# 從截斷的正態分佈中輸出隨機值。[7*7*32, 1024]截取的維度,stddev爲方差
# 生成的值服從具有指定平均值和標準偏差的正態分佈,如果生成的值大於平均值2個標準偏差的值則丟棄重新選擇。
# tf.random_normal是從正態分佈中輸出隨機值。
b1 = tf.Variable(tf.constant(0.1, shape=[1024]))
# 完成維度的轉換,之前的layer1_pool是一個M*7*7*32的四維的數據,這裏我們需要轉換成一個二維的數據
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)
# 上面的運算結果作爲輸入帶入到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代表10張圖片在0-9上分佈的概率
# N*10(概率)
loss0 = labelInput*tf.log(pred)          # 把當前的數據範圍儘可能的壓縮,
loss1 = 0
for m in range(0, 100):
	for n in range(0,10):
		loss1 = loss1 + loss0[m,n]
loss = loss1/100

# train 訓練
train = tf.train.GradientDescentOptimizer(0.01).minimize(loss)       # 梯度下降法,每一次下降0.01,目的是縮小loss,減小誤差

# run 運行
with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())      # 完成所有參數的初始化
	for i in range(100):    # 運用循環讀取和訓練圖片
		images,labels = minst.train.next_batch(500)        # 每次讀取500張圖片分別存在圖片和標籤數組中進行訓練
		sess.run(train,feed_dict={imageInput:images,labelInput:labels})     # run當前的數據,喂入數據,完成訓練

		pred_test = sess.run(pred,feed_dict={imageInput:minst.test.images,labelInput:labels})
        # 最終的 預測結果,最終的預測結果是一個十維的,我們之前的label標籤也是 10維的,所以我們需要判斷一下它們中最大值是否相等,爲什麼要判斷它們的最大值是否相等呢:
        # 因爲pred_test得到的是當前的某一張圖片它進行預測完之後,0-9出現的概率,概率最大的就是我們認爲的那個數字,所以我們需要用最大值進行判斷
		acc = tf.equal(tf.arg_max(pred_test,1),tf.arg_max(minst.test.labels,1))
		acc_float = tf.reduce_mean(tf.cast(acc,tf.float32))        # 完成當前均值的計算
		acc_result = sess.run(acc_float,feed_dict={imageInput:minst.test.images,labelInput:minst.test.labels})
		print(acc_result)

輸出結果爲:

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