1. 程式人生 > >使用TensorFlow訓練神經網路識別MNIST資料程式碼

使用TensorFlow訓練神經網路識別MNIST資料程式碼

以下程式碼實現了使用TensorFlow搭建神經網路解決MNIST手寫體數字識別問題,此神經網路使用了啟用函式去線性化,本身為三層全連線結構,帶有指數衰減的學習率以及L2正則化損失函式,同時使用滑動平均模型進行優化。

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

INPUT_NODE = 784  #輸入層的節點數,圖片為28*28,為圖片的畫素
OUTPUT_NODE = 10   #輸出層的節點數,等於類別的數目,需要區分0-9,所以為10類

#配置神經網路的引數
LAYER1_NODE = 500
#隱藏層的節點數,此神經網路只有一層隱藏層 BATCH_SIZE = 100 #一個訓練batch中的訓練資料個數,數字越小,越接近隨機梯度下降,越大越接近梯度下降 LEARNING_RATE_BASE = 0.8 #基礎的學習率 LEARNING_RATE_DECAY = 0.99 #學習率的衰減率 REGULARIZATION_RATE = 0.0001 #描述網路複雜度的正則化向在損失函式中的係數 TRAINING_STEPS = 30000 #訓練輪數 MOVING_AVERAGE_DECAY = 0.99 #滑動平均衰減率 #給定神經網路的輸入和所有引數,計算神經網路的前向傳播結果,定義了一個使用ReLU的三層全連線神經網路,通過加入隱藏層實現了多層網路結構
def inference(input_tensor, avg_class, weights1, biases1, weights2, biases2): #若沒有提供滑動平均類,則直接使用引數當前的取值 if avg_class == None: #計算隱藏層的前向傳播結果,使用ReLU啟用函式 layer1 = tf.nn.relu(tf.matmul(input_tensor, weights1) + biases1) return tf.matmul(layer1, weights2)+biases2 else: #首先使用avg_class.average來計算得出變數的滑動平均值
#然後在計算相應的神經網路前向傳播結果 layer1 = tf.nn.relu(tf.matmul(input_tensor, avg_class.average(weights1)) + avg_class.average(biases1)) return tf.matmul(layer1, avg_class.average(weights2))+avg_class.average(biases2) #訓練網路的過程 def train(mnist): x = tf.placeholder(tf.float32, [None, INPUT_NODE], name='x-input') y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE], name='y-input') #使用截斷正態分佈生成隱藏層的引數 weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER1_NODE], stddev=0.1)) biases1 = tf.Variable(tf.constant(0.1, shape=[LAYER1_NODE])) #生成輸出層的引數 weights2 = tf.Variable(tf.truncated_normal([LAYER1_NODE, OUTPUT_NODE], stddev=0.1)) biases2 = tf.Variable(tf.constant(0.1, shape=[OUTPUT_NODE])) #計算在當前引數下神經網路前向傳播的結果,這裡的用於計算滑動平均的類為None,所以沒有使用滑動平均值 y = inference(x, None, weights1, biases1, weights2, biases2) #定義儲存訓練輪數的變數,這個變數不需要被訓練 global_step = tf.Variable(0, trainable=False) #初始化滑動平均類 variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step) #在所有代表神經網路引數的變數上使用滑動平均,需要被訓練的引數,variable_averages返回的就是GraphKeys.TRAINABLE_VARIABLES中的元素 variable_averages_op = variable_averages.apply(tf.trainable_variables()) #計算使用了滑動平均之後的前向傳播結果,滑動平均不會改變變數本身取值,會用一個影子變數來記錄 average_y = inference(x, variable_averages, weights1, biases1, weights2, biases2) #計算交叉熵,使用了sparse_softmax_cross_entropy_with_logits,當問題只有一個正確答案時,可以使用這個函式來加速交叉熵的計算。 #這個函式的第一個引數是神經網路不包括softmax層的前向傳播結果,第二個是訓練資料的正確答案,argmax返回最大值的位置 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1)) #計算在當前batch中所有樣例的交叉熵平均值 cross_entropy_mean = tf.reduce_mean(cross_entropy) #計算L2正則化損失 regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE) #計算網路的正則化損失 regularization = regularizer(weights1) + regularizer(weights2) #總損失為交叉熵損失和正則化損失之和 loss = cross_entropy_mean + regularization #設定指數衰減的學習率 learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE, global_step, mnist.train.num_examples/BATCH_SIZE, LEARNING_RATE_DECAY) #LEARNING_RATE_BASE為基礎學習率,global_step為當前迭代的次數 #mnist.train.num_examples/BATCH_SIZE為完整的過完所有的訓練資料需要的迭代次數 #LEARNING_RATE_DECAY為學習率衰減速度 #使用GradientDescentOptimizer優化演算法優化損失函式 train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step) #在訓練神經網路的時候,每過一遍資料都要通過反向傳播來更新引數以及其滑動平均值 # 為了一次完成多個操作,可以通過tf.control_dependencies和tf.group兩種機制來實現 # train_op = tf.group(train_step, variable_averages_op) #和下面程式碼功能一樣 with tf.control_dependencies([train_step, variable_averages_op]): train_op = tf.no_op(name = 'train') #檢驗使用了滑動平均模型的神經網路前向傳播結果是否正確 #f.argmax(average_y, 1)計算了每一個樣例的預測答案,得到的結果是一個長度為batch的一維陣列 #一維陣列中的值就表示了每一個樣例對應的數字識別結果 #tf.equal判斷兩個張量的每一維是否相等。如果相等返回True,反之返回False correct_prediction = tf.equal(tf.argmax(average_y, 1), tf.argmax(y_, 1)) #首先將一個布林型的陣列轉換為實數,然後計算平均值 #平均值就是網路在這一組資料上的正確率 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) #初始會話並開始訓練過程 with tf.Session() as sess: tf.global_variables_initializer().run() #引數初始化 #準備驗證資料,在神經網路的訓練過程中,會通過驗證資料來大致判斷停止的條件和評判訓練的效果 validate_data = {x: mnist.validation.images, y_:mnist.validation.labels} #準備測試資料 test_data = {x:mnist.test.images, y_:mnist.test.labels} #迭代的訓練神經網路 for i in range(TRAINING_STEPS): #每1000輪輸出一次在驗證資料集上的測試結果 if i%1000==0: #計算滑動平均模型在驗證資料上的結果,因為MNIST資料集較小,所以可以一次處理所有的驗證資料 validate_acc = sess.run(accuracy, feed_dict=validate_data) print("After %d training steps, validation accuracy using average model is %g" %(i, validate_acc)) # 產生訓練資料batch,開始訓練 xs, ys = mnist.train.next_batch(BATCH_SIZE) # xs為資料,ys為標籤 sess.run(train_op, feed_dict={x:xs, y_:ys}) test_acc = sess.run(accuracy, feed_dict=test_data) print("After %d training steps, validation accuracy using average model is %g" %(TRAINING_STEPS, test_acc)) #程式主入口 def main(argv=None): # 宣告處理MNIST資料集的類,one_hot=True將標籤表示為向量形式 mnist = input_data.read_data_sets("/tensorflow_google", one_hot=True) train(mnist) #TensorFlow提供程式主入口,tf.app.run會呼叫上面定義的main函式 if __name__ =='__main__': tf.app.run() >>After 0 training steps, validation accuracy using average model is 0.0934 After 1000 training steps, validation accuracy using average model is 0.978 After 2000 training steps, validation accuracy using average model is 0.982 After 3000 training steps, validation accuracy using average model is 0.983 After 4000 training steps, validation accuracy using average model is 0.9848 After 5000 training steps, validation accuracy using average model is 0.9836 . . . After 30000 training steps, validation accuracy using average model is 0.983