卷積神經網絡之手寫數字識別應用MNISTCNN

一、TensorFlow環境安裝,及準備(ubuntu 環境)

1、安裝python、pip

#sudo apt-get install python-pip python-dev

2、臨時更換pip源,使用國內源保證下載速度

#sudo pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tensorflow

3、查看pip安裝列表

#sudo pip list

4、圖像處理模塊

import PIL.Image as Image

二、模型創建,及詳細解說

1、首先粘出模型創建代碼

# -*- ecoding:utf-8 -*-

import tensorflow as tf

class model():
    def __init__(self):
	self.x_image = tf.placeholder(tf.float32, [None, 784])
	self.ylabel = tf.placeholder(tf.float32, [None, 10])
	self.x = tf.reshape(self.x_image, [-1,28,28,1])
	#first layer
	with tf.name_scope('conv1'):
		self.W_conv1 = tf.Variable(tf.truncated_normal([5,5,1,32], stddev=0.1))
		self.b_conv1 = tf.Variable(tf.constant(0.1, shape=[32]))

		#Converlution
		self.h_conv1 = tf.nn.conv2d(self.x, self.W_conv1, strides=[1,1,1,1], padding='SAME') + self.b_conv1
		self.h_convRelu1 = tf.nn.relu(self.h_conv1)
		#pooling
	with tf.name_scope('pool1'):
		self.h_pool1 = tf.nn.max_pool(self.h_convRelu1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

	#second layer
	with tf.name_scope('conv2'):
		self.W_conv2 = tf.Variable(tf.truncated_normal([5,5,32,64], stddev=0.1))
		self.b_conv2 = tf.Variable(tf.constant(0.1, shape=[64]))

		#Converlution
		self.h_conv2 = tf.nn.conv2d(self.h_pool1, self.W_conv2, strides=[1,1,1,1], padding='SAME') + self.b_conv2
		self.h_convRelu2 = tf.nn.relu(self.h_conv2)
		#pooling
	with tf.name_scope('pool2'):
		self.h_pool2 = tf.nn.max_pool(self.h_convRelu2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

	#third layer full connected
	with tf.name_scope('fc1'):
		self.W_fc1 = tf.Variable(tf.truncated_normal([7*7*64, 1024], stddev=0.1))
		self.b_fc1 = tf.Variable(tf.constant(0.1,shape=[1024]))
		self.h_pool2_flat = tf.reshape(self.h_pool2, [-1,7*7*64])
		self.h_fc1 = tf.matmul(self.h_pool2_flat, self.W_fc1) + self.b_fc1
		self.h_fcRelu1 = tf.nn.relu(self.h_fc1)
	with tf.name_scope('dropout'):
		self.keep_prob = tf.placeholder(tf.float32)
		self.h_fcdrop1 = tf.nn.dropout(self.h_fcRelu1, self.keep_prob)
	with tf.name_scope('fc2'):
		self.W_fc2 = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1))
		self.b_fc2 = tf.Variable(tf.constant(0.1, shape=[10]))
		self.y_conv = tf.matmul(self.h_fcdrop1, self.W_fc2) + self.b_fc2
	with tf.name_scope('loss'):
		self.cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=self.ylabel, logits=self.y_conv)
		self.cross_entropy = tf.reduce_mean(self.cross_entropy)		
	with tf.name_scope('adam_optimizer'):
		self.train_step = tf.train.AdamOptimizer(1e-4).minimize(self.cross_entropy)
	with tf.name_scope('accuracy'):
		self.correct_prediction = tf.equal(tf.argmax(self.y_conv, 1), tf.argmax(self.ylabel,1))
		self.correct_prediction = tf.cast(self.correct_prediction, tf.float32)
		self.accuracy = tf.reduce_mean(self.correct_prediction)

2、詳細說明模型創建過程


卷積神經網絡(CNN)過程類似上圖的LeNet,只是輸入和參數不同。可以理解爲6層結構。

Layer1:輸入是28x28的灰度圖像,使用5*5單通道濾波器,輸出32張特徵圖,W_conv1是濾波器參數,生成符合標準正態分佈的初始化參數,接下來做relu操作,該操作負數變爲0.

	self.W_conv1 = tf.Variable(tf.truncated_normal([5,5,1,32], stddev=0.1))
	self.b_conv1 = tf.Variable(tf.constant(0.1, shape=[32]))

	#Converlution
	self.h_conv1 = tf.nn.conv2d(self.x, self.W_conv1, strides=[1,1,1,1], padding='SAME') + self.b_conv1
	self.h_convRelu1 = tf.nn.relu(self.h_conv1)

Layer2:做下采樣操作,相當於每2*2的窗口像素取最大值,輸出特徵圖爲原圖的二分之一

self.h_pool1 = tf.nn.max_pool(self.h_convRelu1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

Layer3: 卷積操作,輸入是14*14的圖,濾波器5*5,32通道,輸出是64張特徵圖,W_conv2是濾波器參數,生成符合標準正態分佈的初始化參數,接下來做relu操作,該操作負數變爲0.

	self.W_conv2 = tf.Variable(tf.truncated_normal([5,5,32,64], stddev=0.1))
	self.b_conv2 = tf.Variable(tf.constant(0.1, shape=[64]))

	#Converlution
	self.h_conv2 = tf.nn.conv2d(self.h_pool1, self.W_conv2, strides=[1,1,1,1], padding='SAME') + self.b_conv2
	self.h_convRelu2 = tf.nn.relu(self.h_conv2)

Layer4:做下采樣操作,相當於每2*2的窗口像素取最大值,輸出特徵圖爲原圖的二分之一

self.h_pool2 = tf.nn.max_pool(self.h_convRelu2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

Layer5:第一次全連接操作,該層輸入是7*7*64個像素,輸出是1024個單元,相當於做了降維操作,然後再來一次relu操作

	self.W_fc1 = tf.Variable(tf.truncated_normal([7*7*64, 1024], stddev=0.1))
	self.b_fc1 = tf.Variable(tf.constant(0.1,shape=[1024]))
	self.h_pool2_flat = tf.reshape(self.h_pool2, [-1,7*7*64])
	self.h_fc1 = tf.matmul(self.h_pool2_flat, self.W_fc1) + self.b_fc1
	self.h_fcRelu1 = tf.nn.relu(self.h_fc1)

接下來做了dropout操作,dropout(arg1, arg2),其中第二個參數是一個百分比,假如arg2=0.5,就是arg1將有50%的單元作用於後層:

	self.keep_prob = tf.placeholder(tf.float32)
	self.h_fcdrop1 = tf.nn.dropout(self.h_fcRelu1, self.keep_prob)

Layer6:第二次全連接操作,相當於做分類了,輸入是1024個單元,輸出時10個單元,輸出y_conv就是類別對應的概率(1X10的行向量)

	self.W_fc2 = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1))
	self.b_fc2 = tf.Variable(tf.constant(0.1, shape=[10]))
	self.y_conv = tf.matmul(self.h_fcdrop1, self.W_fc2) + self.b_fc2

最後是定義損失函數及優化方法

	with tf.name_scope('loss'):
		self.cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=self.ylabel, logits=self.y_conv)
		self.cross_entropy = tf.reduce_mean(self.cross_entropy)		
	with tf.name_scope('adam_optimizer'):
		self.train_step = tf.train.AdamOptimizer(1e-4).minimize(self.cross_entropy)
	with tf.name_scope('accuracy'):
		self.correct_prediction = tf.equal(tf.argmax(self.y_conv, 1), tf.argmax(self.ylabel,1))
		self.correct_prediction = tf.cast(self.correct_prediction, tf.float32)
		self.accuracy = tf.reduce_mean(self.correct_prediction)

三、模型訓練過程

import tensorflow as tf
import input_data
from model import model

class TrainCnn():
	def __init__(self):
		self.network = model()
		self.sess = tf.Session()
		self.data = input_data.read_data_sets('/tmp/data/', one_hot=True)
	def train(self):
		batch_size = 100
		self.sess.run(tf.global_variables_initializer())
		for i in range(20000):
			batch = self.data.train.next_batch(100)
			if i%1==0:
				realrate,cross = self.sess.run([self.network.accuracy, self.network.cross_entropy], feed_dict={self.network.x_image:batch[0], self.network.ylabel:batch[1], self.network.keep_prob:1.0})
				print ('step %d, training accuracy:%g ,cross_entropy:%g' %(i, realrate, cross))
			self.sess.run(self.network.train_step,feed_dict={self.network.x_image:batch[0], self.network.ylabel:batch[1], self.network.keep_prob:0.5})

if __name__ == '__main__':
    app = TrainCnn()
    app.train()

這裏是讀入已經下載好的mnist訓練及測試數據,tensorflow官網提供數據源,在訓練時首先啓動一個Session,然後初始化所有變量,tf.global_variables_initializer(),接下來就是傳值計算的過程:

self.sess.run([self.network.accuracy, self.network.cross_entropy], feed_dict={self.network.x_image:batch[0], self.network.ylabel:batch[1], self.network.keep_prob:1.0})
				print ('step %d, training accuracy:%g ,cross_entropy:%g' %(i, realrate, cross))

四、訓練結果:


五、說明,學習代碼之前建議看看TensorFlow相關教程,TensorFlow是一個圖爲計算單元,圖中添加計算節點,計算過程是通過啓動一個Session,通過run方法執行圖,本次試驗的相關代碼及試驗數據下載鏈接如下:

https://download.csdn.net/download/jiangyingfeng/10539757


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