自從跟導(dǎo)師吹了波牛之后,開始將自己的研究重心轉(zhuǎn)為NLP方向。那么RNN就成了必須要了解的一個(gè)DL模型(導(dǎo)師暑假去了趟西安,學(xué)習(xí)一波DL,回來神神叨叨地說CNN到瓶頸期了,別瞎折騰了)。對(duì)于RNN,我就默認(rèn)大家都懂得其中的原理,有不明白的可以去看NG 的視頻教學(xué):https://mooc.study.163.com/smartSpec/detail/1001319001.htm。話不多說,開搞開搞?。?!
Step1 搭建環(huán)境
系統(tǒng):Windows7+TensorFlow1.9.0(cpu)+Python3.6
Step2 加載數(shù)據(jù)集
MNIST是一個(gè)手寫數(shù)字?jǐn)?shù)據(jù)庫(kù),它有55000個(gè)訓(xùn)練樣本集和10000個(gè)測(cè)試樣本集。它是MNIST數(shù)據(jù)庫(kù)的一個(gè)子集。其中每張圖片固定大小為28×28的黑白圖片。如下圖所示:

使用Tensorflow加載內(nèi)置的MNIST數(shù)據(jù)集,具體方法展示如下。

加載完成后,打印訓(xùn)練樣本數(shù)(ntrain),測(cè)試樣本數(shù)(ntest),樣本 總維度(dim)以及分類數(shù)(nlasses)

Step3 RNN模型
接下來我們就需要去看看,我們所要搭建的RNN模型到底長(zhǎng)啥樣。

這是從NG那邊搞來的圖,相信大家都能明白其中的奧秘吧。但當(dāng)時(shí)我在學(xué)的時(shí)候很困惑,這東西實(shí)際中咋用,搞成這副鬼樣子,真有那么神?em...下面這張圖就是利用MNIST數(shù)據(jù)集來做的一個(gè)實(shí)驗(yàn)。

簡(jiǎn)單敘述下該模型的建立過程,每一個(gè)樣本都可以看出是一個(gè)[28,28]的矩陣,那么將矩陣的每一行作為一個(gè)輸入向量,大小為[1,28],那么整個(gè)模型就擁有28個(gè)輸入神經(jīng)元,這28個(gè)神經(jīng)元我們將其統(tǒng)稱為輸入層。完成后我再輸入層與RNN層之間增加一個(gè)含有128個(gè)神經(jīng)元的隱藏層,用于對(duì)輸入層進(jìn)行特征 提取,形成一個(gè)[1,128]的向量傳入RNN中。RNN中的內(nèi)部構(gòu)造參見LSTM,形成兩個(gè)向量分別為L(zhǎng)STM_O,LSTM_S,大小都為[1,128]。其中LSTM_O為RNN模型的輸出,LSTM_S為RNN模型的內(nèi)部記憶向量,傳遞到下一個(gè)RNN神經(jīng)元。最后對(duì)LSTM_O進(jìn)行Softmax處理,通過概率分析出該樣本的類別。
接下來我們對(duì)模型中所涉及的權(quán)重、偏置以及各層神經(jīng)元數(shù)量的設(shè)置。其中W["h1"]為輸入層到隱藏層的權(quán)重,大小為[28,128],W["h2"]為隱藏層到RNN的權(quán)重,大小為[128,10]。b["b1"]與b["b2"]同理。

Step4 創(chuàng)建RNN模型(關(guān)鍵步驟)

42~43行:對(duì)輸入數(shù)據(jù)進(jìn)行預(yù)處理操作。這里涉及到batch_size的問題,在訓(xùn)練時(shí)我們通常是將一批數(shù)據(jù)導(dǎo)入模型來提高模型的效率,那么批次的大小就是batch_size。即我們可以理解為我們是將一個(gè)batch_size*28*28的三維矩陣導(dǎo)入了我們的RNN模型,那么我們就要對(duì)該矩陣進(jìn)行變換從而滿足我們[None,28]的要求。
44~45行:隱藏層處理好輸入數(shù)據(jù)后形成一個(gè)[None,128]的矩陣。然后對(duì)該矩陣進(jìn)行切割,我們的RNN一共有28個(gè)輸入單元,那就切成28個(gè)咯。
46~50行:將切好的矩陣依次傳入RNN中。接下來是對(duì)RNN內(nèi)部的設(shè)置,這邊使用的是LSTM(tf.nn.rnn_cell.BasicLSTMCell()),當(dāng)然tf.nn也為我們實(shí)現(xiàn)好了其他的內(nèi)部設(shè)置方便我們調(diào)用。
Step5 超參數(shù)的定義(損,優(yōu),學(xué),準(zhǔn),初)
該步驟定義模型中我們所需要的一些超參數(shù)。Tensorflow擁有現(xiàn)成的方法,方便我們調(diào)用。
學(xué)習(xí)率:leraning_rate
損失:cost
優(yōu)化方法:optm
參數(shù)初始化:init

Step6 訓(xùn)練測(cè)試
最后一步,設(shè)置好迭代次數(shù)(training_epoch)、批次大?。╞atch_size)等后,將MNIST的數(shù)據(jù)集加載到Step5中設(shè)置好的X、Y中,完成訓(xùn)練測(cè)試。沒什么好多說的,我每個(gè)模型最后的訓(xùn)練測(cè)試都這樣,照著寫吧。

Step7 結(jié)果展示
總共迭代了5次,電腦跑太慢了...
準(zhǔn)確率達(dá)到93.9%,還彳亍 口 巴!

附上所有代碼:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.contrib import rnn
# 加載數(shù)據(jù)
mnist = input_data.read_data_sets("MNIST_data",one_hot=True)
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]
#print(ntrain, ntest, dim, nclasses)
print ("MNIST loaded")
#設(shè)置參數(shù),權(quán)重,偏置
diminput = 28
dimhidden = 128
dimoutput = nclasses
nsteps = 28
W = {"h1" : tf.Variable(tf.random_normal([diminput,dimhidden])),
? ? "h2" : tf.Variable(tf.random_normal([dimhidden,dimoutput]))}
b = {"b1" : tf.Variable(tf.random_normal([dimhidden])),
? ? "b2" : tf.Variable(tf.random_normal([dimoutput]))}
# 創(chuàng)建模型
def RNN(X,W,b,nsteps):
? ? X = tf.transpose(X,[1,0,2])
? ? X = tf.reshape(X,[-1,diminput])
? ? H_1 = tf.matmul(X,W["h1"])+b["b1"]
? ? H_1 = tf.split(H_1,nsteps,0)
? ? lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(dimhidden,forget_bias=1.0)
? ? LSTM_O,LSTM_S = rnn.static_rnn(lstm_cell,H_1,dtype=tf.float32)
? ? O = tf.matmul(LSTM_O[-1],W["h2"])+b["b2"]
? ? return {"X":X,"H_1":H_1,"LSTM_O":LSTM_O,"LSTM_S":LSTM_S,"O":O}?
print ("Network ready")
# 設(shè)置損失,優(yōu)化,學(xué)習(xí)率,準(zhǔn)確率,參數(shù)初始化
learning_rate = 0.001
x? ? ? = tf.placeholder("float", [None, nsteps, diminput])
y? ? ? = tf.placeholder("float", [None, dimoutput])
myrnn? = RNN(x, W, b, nsteps)
pred? = myrnn['O']
cost? = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=pred))
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()
print ("Network Ready!")
# 訓(xùn)練,測(cè)試
#所有樣本迭代(epoch)5次
training_epochs = 5
#每進(jìn)行一次迭代選擇的樣本數(shù)
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 = int(mnist.train.num_examples/batch_size)
? ? #total_batch = 100
? ? # Loop over all batches
? ? 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))
? ? ? ? # Fit training using batch data
? ? ? ? feeds = {x: batch_xs, y: batch_ys}
? ? ? ? sess.run(optm, feed_dict=feeds)
? ? ? ? # Compute average loss
? ? ? ? avg_cost += sess.run(cost, feed_dict=feeds)/total_batch
? ? # Display logs per epoch step
? ? 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}
? ? ? ? test_acc = sess.run(accr, feed_dict=feeds)
? ? ? ? print (" Test accuracy: %.3f" % (test_acc))
print ("Optimization Finished.")