在MNIST資料集上用Tensorflow實作AlexNet
- 前言
- 需要下載下傳的東西(資料和代碼)
- 代碼講解
前言
MNIST是一個被廣泛使用的資料集,科研領域中也時常使用到它。
MNIST資料集,是一個在科研界都被廣泛使用的資料集,其由Yann LeCun, Courant Institute, NYU、Corinna Cortes, Google Labs, New York和Christopher J.C. Burges, Microsoft Research, Redmond共同維護,該資料集比較适合用來練習卷積神經網絡以及其它各種神經網絡,官網網址為:MNIST官網,上面有不同文章不同算法得到的對于MNIST的最優的結果。
若想看更為基礎的在MNIST資料集上用Tensorflow實作多層神經網絡算法,請點選右側超連結:請點我。
該代碼是AlexNet神經網絡用于MNIST資料集的一個複現,其中對應于MNIST,調整了一些參數使得網絡性能更好,若想了解AlexNet,請點選:AlexNet論文解說部落格
全連接配接層層都加入了dropout,若想了解dropout,請點選dropout解說部落格
下述代碼中除了縮減了卷積的通道數和卷積核的大小外,還将原文使用的帶動量的小批量梯度下降算法給換成了RMSProp算法,由于技術問題,還不會往裡面增加原文中的權重衰減。全連接配接層方面由于輸出隻有10個類别,是以将全連接配接層從原始AlexNet的4096變成了1024。
需要下載下傳的東西(資料和代碼)
訓練集、測試集以及相關代碼都在如下的百度雲盤中:
連結:https://pan.baidu.com/s/1vC9SjqwaDr9dYg6W9ZVwxA
提取碼:5o92
代碼講解
首先先導入必要的庫
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
import tensorflow as tf
import numpy as np
調參時固定随機種子
# 調參時固定随機種子
seed = 1
tf.set_random_seed(seed)
np.random.seed(seed)
定義權值和偏差的函數
#權值和偏差
# 定義變量函數 (weights and bias)
def init_weight(shape, st_dev):
weight = tf.Variable(tf.truncated_normal(shape, stddev=st_dev))
return(weight)
def init_bias(shape, st_dev):
bias = tf.Variable(tf.truncated_normal(shape, stddev=st_dev))
return(bias)
建立輸入資料的占位符(placeholder)
# 建立輸入資料的占位符(placeholder)
x_data = tf.placeholder(shape=[None, 784], dtype=tf.float32)
y_target = tf.placeholder(shape=[None, 10], dtype=tf.float32)
預處理資料集以使其次元比對
# 預處理資料集以使其次元比對
x_image = tf.reshape(x_data,[-1,28,28,1])
建構3層卷積加2層全連接配接層的神經網絡
# 建構AlexNet
p_keep_hidden=tf.placeholder('float')
rand_st_dev=0.01
w=init_weight([3,3,1,32], st_dev=rand_st_dev)
w2=init_weight([3,3,32,64], st_dev=rand_st_dev)
w3=init_weight([3,3,64,128], st_dev=rand_st_dev)
w4=init_weight([1,1,128,128], st_dev=rand_st_dev)
w5=init_weight([1,1,128,64], st_dev=rand_st_dev)
w6=init_weight([64*4*4,64*4*4], st_dev=rand_st_dev)
w7=init_weight([64*4*4,1024], st_dev=rand_st_dev)
w_o=init_weight([1024,10], st_dev=rand_st_dev)
#定義第一組卷積層和池化層,最後dropout掉一些神經元
l1a=tf.nn.relu(tf.nn.conv2d(x_image,w,strides=[1,1,1,1],padding='SAME'))
l1=tf.nn.max_pool(l1a,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#定義第二組卷積層和池化層,最後dropout掉一些神經元
l2a=tf.nn.relu(tf.nn.conv2d(l1,w2,strides=[1,1,1,1],padding='SAME'))
l2=tf.nn.max_pool(l2a,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#定義第三組卷積層和池化層,最後dropout掉一些神經元
l3=tf.nn.relu(tf.nn.conv2d(l2,w3,strides=[1,1,1,1],padding='SAME'))
#定義第四組卷積層和池化層,最後dropout掉一些神經元
l4=tf.nn.relu(tf.nn.conv2d(l3,w4,strides=[1,1,1,1],padding='SAME'))
#定義第五組卷積層和池化層,最後dropout掉一些神經元
l5a=tf.nn.relu(tf.nn.conv2d(l4,w5,strides=[1,1,1,1],padding='SAME'))
l5=tf.nn.max_pool(l5a,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
l5=tf.reshape(l5,[-1,w6.get_shape().as_list()[0]])
#第一個全連接配接層,最後dropout掉一些神經元
l6=tf.nn.relu(tf.matmul(l5,w6))
l6=tf.nn.dropout(l6,p_keep_hidden)
#第二個全連接配接層,最後dropout掉一些神經元
l7=tf.nn.relu(tf.matmul(l6,w7))
l7=tf.nn.dropout(l7,p_keep_hidden)
#輸出層
final_output=tf.matmul(l7,w_o)
loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=final_output,labels=y_target))
train_step=tf.train.RMSPropOptimizer(0.001,0.9).minimize(loss)
y = tf.nn.softmax(final_output)
定義計算準确度的op
# 定義計算準确度的op
correct_prediction_op = tf.equal(tf.argmax(y,1), tf.argmax(y_target,1))
accuracy_op=tf.reduce_mean(tf.cast(correct_prediction_op, tf.float32))
初始化變量
# Session
sess = tf.InteractiveSession()
#初始化變量
tf.global_variables_initializer().run()
訓練模型,訓練10000次
#訓練模型,訓練20000次
for i in range(20000):
batch_xs, batch_ys = mnist.train.next_batch(128)
sess.run(train_step, feed_dict={x_data: batch_xs, y_target: batch_ys,
p_keep_hidden:0.5})
## 顯存不夠用時請使用這段被注釋的代碼代替下方的正确率計算代碼
# if (i+1)%1000==0:
# # 計算測試集的正确率
# accuracy_sum=0;
# # 為了限制顯存的使用,是以将測試集也分為小批次來計算然後求和再求平均
# for j in range(50):
# batch_xs_test, batch_ys_test = mnist.test.next_batch(200)
# accuracy = sess.run(accuracy_op,feed_dict={x_data: batch_xs_test,
# y_target: batch_ys_test,
# p_keep_hidden:1.0})
# accuracy_sum=accuracy_sum+accuracy
#
# accuracy_sum=accuracy_sum/(j+1)
# print("第"+str(i)+"次疊代時,在測試集上的準确率為:"+str(accuracy_sum))
if (i+1)%1000==0:
# 計算測試集的正确率
accuracy = sess.run(accuracy_op,feed_dict={x_data: mnist.test.images,
y_target: mnist.test.labels,
p_keep_hidden:1.0})
print("第"+str(i)+"次疊代時,在測試集上的準确率為:"+str(accuracy))
sess.close()
結果輸出如下所示:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxycG5WZ1g3VjZDbzwEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYfRHelRHLwEzX39GZhh2css2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3Pn5GcuIzM5ITOzcDM1ATOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
最好的結果出現在第8999次疊代時,此時在測試集上的準确率為:0.9924,即 99.24 % 99.24\% 99.24%。