import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import pandas as pd
#導入mnist數據
mnist = pd.read_data_sets("data/", one_hot=True)#one_hot=True 表示 數據的標簽是one_hot編碼的,即數據標簽為1*10的數組
#讀取訓練數據,訓練標簽,測試數據,測試標簽
trainimgs, trainlabels, testimgs, testlabels \
= mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels
#獲取訓練數據個數,測試集數據個數,圖像維度和類別數
ntrain, ntest, dim, nclasses \
= trainimgs.shape[0], testimgs.shape[0], trainimgs.shape[1], trainlabels.shape[1]
#輸入數據維度,沒一個RNN輸入一個1*28的tensor
diminput = 28
#隱藏層大小
dimhidden = 128
#輸出結果的維度
dimoutput = nclasses
#一共28個RNN結構
nsteps = 28
#權重
weights = {
'hidden':tf.Variable(tf.random_normal([diminput,dimhidden])), #28*128全連接的網絡參數
'out':tf.Variable(tf.random_normal([dimhidden,dimoutput])) #128*10全連接輸出網格
}
#偏置
biases = {
'hidden':tf.Variable(tf.random_normal([dimhidden])),
'out':tf.Variable(tf.random_normal([dimoutput]))
}
def _RNN(_X,_W,_b,_nsteps,_name):
# 1. Permute input from [batchsize, nsteps, diminput]
# => [nsteps, batchsize, diminput]
# 因為輸入的數據維度為batch_size*28*28,而每一個LSTM運算的輸入為batch_size*28,因此對數據進行轉換為28*16*28,即第一個塊是16個圖像的第一行,第二個塊是16個圖像的第二行,以此類推
_X = tf.transpose(_X,[1,0,2])
# 2. Reshape input to [nsteps*batchsize, diminput]
# 將數據reshape,得到(28*16)*28
_X = tf.reshape(_X,[-1,diminput])
_H = tf.matmul(_X,_W['hidden']+_b['hidden'])
# 將計算的結果進行划分,也可先划分,然后分別計算,把(28*16)*28的數據划分為
_Hsplit = tf.split(0,_nsteps,_H)
with tf.variable_scope(_name) as scope:
# 變量共享,多次創建的變量是同一個東西
scope.reuse_variables()
#創建LSTM
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(dimhidden,forget_bias=1.0)
#計算以此得到的每一次輸出
_LSTM_O,_LSTM_S = tf.nn.rnn(lstm_cell,_Hsplit,dtype = tf.float32)
_O = tf.matmul(_LSTM_O[-1],_W['out'])+_b['out']
return {
'X':_X,'H':_H,'Hsplit':_Hsplit,
'LSTM_O':_LSTM_O,'LSTM_S':_LSTM_S,'O':_O
}
#設置優化算法和損失函數
#學習率
learning_rate = 0.001
#訓練集輸入數據與標記
x = tf.placeholder('float',[None,nsteps,diminput])
y = tf.placeholder('float',[None,dimoutput])
#定義RNN
myrnn = _RNN(x,weights,biases,nsteps,'basic')
#預測結果是myrnn['O']中最后一個
pred = myrnn['O']
#損失函數交叉熵
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(pred,y))
#梯度下降優化
optm = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
#計算機准確率
accr = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(pred,1),tf.argmax(y,1),tf.float32)))
init = tf.global_variables_initializer()
#開始訓練
#循環次數
training_epochs = 5
#一次訓練輸入圖像的個數,即輸入為28*28*16
batch_size = 16
#每循環一次輸出一次結果
display_step = 1
sess = tf.Session()
#初始化
sess.run(init)
print('Start optimization')
for epoch in range(training_epochs):
avg_cost = 0
total_batch = 100
for i in range(total_batch):
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
batch_xs = batch_xs.reshape((batch_size,nsteps,diminput))
feeds = {x:batch_xs,y:batch_ys}
sess.run(optm,feed_dict=feeds)
avg_cost += sess.run(cost,feed_dict=feeds)/total_batch
if epoch%display_step==0:
print("Epoch: %03d/%03d cost: %.9f" % (epoch, training_epochs, avg_cost))
feeds = {x:batch_xs,y:batch_ys}
train_acc = sess.run(accr,feed_dict=feeds)
print(" Training accuracy: %.3f" % (train_acc))
testimgs = testimgs.reshape((ntest,nsteps,diminput))
feeds = {x: testimgs, y: testlabels, istate: np.zeros((ntest, 2 * dimhidden))}
test_acc = sess.run(accr, feed_dict=feeds)
print(" Test accuracy: %.3f" % (test_acc))
print("Optimization Finished.")