MNIST資料集全連線神經網路python實現
阿新 • • 發佈:2020-12-15
技術標籤:演算法的程式碼實現TensorFlow深度學習演算法原理與程式設計實戰讀書筆記pythontensorflow機器學習
# coding: utf-8
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 注意這裡的one_hot=True 否則label不會以向量的形式給出
mnist = input_data.read_data_sets\
("************", one_hot=True) # 請輸入你要儲存的位置
# 以下資訊用於檢視資料資訊
# print("Training data and label size:")
# print(mnist.train.images.shape, mnist.train.labels.shape)
# print("Testing data and label size:")
# print(mnist.test.images.shape, mnist.test.labels.shape)
# print("Validation data and label size:")
# print(mnist.validation.images.shape, mnist.validation.labels.shape)
# 檢視真實資料例項,其中0表示白色背景,0~1表示有字跡區域
# print("Example training data:", mnist.train.images[0])
# print("Example training label:", mnist.train.labels[0])
# 超引數設定
batch_size = 100 # 設定每一輪訓練的Batch大小
learning_rate = 0.8 # 初始學習率
learning_rate_decay = 0.999 # 學習率的衰減
max_steps = 30000 #最大訓練步數
# 定義儲存訓練輪數的變數,在使用Tensorflow訓練神經網路時,
# 一般會將代表訓練輪數的變數通過trainable引數設定為不可訓練的
training_step = tf.Variable(0, trainable=False)
# 實現單隱藏層全連線網路,ReLU函式作為啟用函式
def hidden_layer(input_tensor, weights1, biases1, weights2, biases2, layer_name):
layer1 = tf.nn.relu(tf.matmul(input_tensor, weights1) + biases1)
return tf.nn.relu(tf.matmul(layer1, weights2) + biases2)
x = tf.placeholder(tf.float32, [None, 784], name="x-input")
y_=tf.placeholder(tf.float32, [None, 10], name="y-output")
# 生成隱藏層引數,其中weights1包含了784*500=39200個引數
weights1 = tf.Variable(tf.truncated_normal([784, 500], stddev=0.1))
biases1 = tf.Variable(tf.constant(0.1, shape=[500])) # shape引數 都是要用[*]賦值的
# 生成輸出層引數,其中weights2包含了500*10=500個引數
weights2 = tf.Variable(tf.truncated_normal([500, 10], stddev=0.1))
biases2 = tf.Variable(tf.constant(0.1, shape=[10])) # shape引數 都是要用[*]賦值的
# 計算經過神經網路前向傳播後得到的y值
y = hidden_layer(x, weights1, biases1, weights2, biases2, 'y')
# 將平滑平均的方法應用到引數上
# 初始化一個平滑平均類,衰減率為0.99
# 為了使模型訓練前期可以更新的更快,這裡提供了了num_updates引數,並設定為當前網路的訓練輪數
averages_class = tf.train.ExponentialMovingAverage(0.99, training_step)
# 定義一個更新變數平滑平均值的操作需要向平滑平均類的apply()函式提供一個引數列表
# train_variables()函式返回集合上Graph.TRAINABLE_BARIABLES中的元素,
# 這個集合的元素就是所有沒有指定trainable_variable_variables=False的引數
averages_op = averages_class.apply(tf.trainable_variables())
# 前向計算y
average_y = hidden_layer(x, averages_class.average(weights1),
averages_class.average(biases1),
averages_class.average(weights2),
averages_class.average(biases2),'average_y')
# 計算交叉熵損失
# 函式原型為sparse_softmax_cross_entropy_with_logits() 適用於樣本只能被劃分為一類,即每個類別互相獨立互斥
# tf.argmax()函式的解釋:https://blog.csdn.net/Jiaach/article/details/78874704?utm_medium=distribute.pc_relevant_t0.
# none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.
# none-task-blog-BlogCommendFromMachineLearnPai2-1.control
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))# 返回按行查詢最大值下標
# 正則化損失函式
regularizer = tf.contrib.layers.l2_regularizer(0.0001)
regularization = regularizer(weights1) + regularizer(weights2)
loss = tf.reduce_mean(cross_entropy) + regularization
# 用指數衰減法設定學習率,這裡staircase引數採用預設的False,即學習率連續衰減
learning_rate = tf.train.exponential_decay(learning_rate, training_step,
mnist.train.num_examples/batch_size, learning_rate_decay)
# 使用GradientDescentOptimizer優化演算法來優化交叉熵損失函式和正則化損失
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=training_step)
# 在訓練模型的時候,每過一邊資料即需要反向傳播來更新神經網路的中的引數,又需要更新每一個引數的平滑平均值
# 等價程式碼: train_op = tf.group(train_step, averages_op)
with tf.control_dependencies([train_step, averages_op]):
train_op = tf.no_op(name="train")
# 檢查使用了滑動平均值模型的神經網路,向前傳播結果是否正確
# equal()用於判斷兩個張量的每一是否相等,相等返回True 否則False
crorent_predicition = tf.equal(tf.argmax(average_y, 1), tf.argmax(y_, 1))
# cast() 函式原型為cast(x, DstT, name),在這裡用於將一個布林型的資料轉換為float32型別
# 之後對得到的float32型別的資料求平均值,這個平均值就是模型在這一組資料上的正確率
accuracy = tf.reduce_mean(tf.cast(crorent_predicition, tf.float32))
# 開始會話
with tf.Session() as sess:
tf.global_variables_initializer().run()
# 準備驗證資料
validate_feed = {x:mnist.validation.images, y_:mnist.validation.labels}
# 準備測試資料
test_feed = {x:mnist.test.images, y_:mnist.test.labels}
for i in range(max_steps):
if i%1000 == 0:
# 計算滑動平均模型在驗證資料上的結果
# 為了能得到百分數輸出,需要將得到的validate_accuracy擴大了100倍
validate_accuracy = sess.run(accuracy, feed_dict=validate_feed)
print("After %d trainging step(s), validation accuracy"
"using average model is %g%%" %(i, validate_accuracy*100))
# 產生這一輪使用一個batch的訓練資料,並進行訓練
# input_data.read_data_sets()函式生成的類提供train.next_batch()函式
xs, ys = mnist.train.next_batch(batch_size=100)
sess.run(train_op, feed_dict={x:xs, y_:ys})
# 使用測試資料集檢驗神經網路訓練之後的最終正確率
# 為了能得到百分數的輸出,需要將得到的test_accuracy擴大100倍
test_accuracy = sess.run(accuracy, feed_dict=test_feed)
print("After %d trainging step(s), test_accuracy using average"
"model is %g%%" %(max_steps, test_accuracy*100))
參考文獻:《TensorFlow 深度學習演算法原理與程式設計實戰》