RNN入門(一)識別MNIST數據集


RNN介紹

  在讀本文之前,讀者應該對全連接神經網絡(Fully Connected Neural Network, FCNN)和卷積神經網絡( Convolutional Neural Network, CNN)有一定的了解。對於FCNN和CNN來說,他們能解決很多實際問題,但是它們都只能單獨的取處理一個個的輸入,前一個輸入和后一個輸入是完全沒有關系的 。而在現實生活中,我們輸入的向量往往存在着前后聯系,即前一個輸入和后一個輸入是有關聯的,比如文本,語音,視頻等,因此,我們需要了解深度學習中的另一類重要的神經網絡,那就是循環神經網絡(Recurrent Neural Network,RNN).
  循環神經網絡(Recurrent Neural Network,RNN)依賴於一個重要的概念:序列(Sequence),即輸入的向量是一個序列,存在着前后聯系。簡單RNN的結構示意圖如下:


相比於之前的FCNN,RNN的結構中多出了一個自循環部分,即W所在的圓圈,這是RNN的精華所在,它展開后的結構如下:


對於t時刻的輸出向量\(o_{t}\),它的輸出不僅僅依賴於t時刻的輸入向量\(x_{t}\),還依賴於t-1時刻的隱藏層向量\(s_{t-1}\),以下是輸出向量\(o_{t}\)的計算公式:

\[s_{t}=f(Ux_{t}+Ws_{t-1}) \]

\[o_{t}=g(Vs_{t}) \]

其中,第二個式子為輸出層的計算公式,輸出層為全連接層,V為權重矩陣,g為激活函數。第一個式子中,U是輸入x的權重矩陣,W是上一次隱藏層值s的輸入權重矩陣,f為激活函數。注意到,RNN的所有權重矩陣U,V,W是共享的,這樣可以減少計算量。
  本文將會用TensorFlow中已經幫我們實現好的RNN基本函數tf.contrib.rnn.BasicRNNCell(), tf.nn.dynamic_rnn()來實現簡單RNN,並且用該RNN來識別MNIST數據集。

MNIST數據集

  MNIST數據集是深度學習的經典入門demo,它是由6萬張訓練圖片和1萬張測試圖片構成的,每張圖片都是28*28大小(如下圖),而且都是黑白色構成(這里的黑色是一個0-1的浮點數,黑色越深表示數值越靠近1),這些圖片是采集的不同的人手寫從0到9的數字。

在這里插入圖片描述
  在TensorFlow中,已經內嵌了MNIST數據集,筆者已經下載下來了,如下:


  接下來本文將要用MNIST數據集作為RNN應用的一個demo.

RNN大戰MNIST數據集

  用CNN來識別MNIST數據集,我們好理解,這是利用了圖片的空間信息。可是,RNN要求輸入的向量是序列,那么,如何把圖片看成是序列呢?
  圖片的大小為28*28,我們把每一列向量看成是某一時刻的向量,那么每張圖片就是一個序列,里面含有28個向量,每個向量含有28個元素,如下:

將圖片看成是序列
  下面給出如何利用TensorFlow來搭建簡單RNN,用來識別MNIST數據集,完整的Python代碼如下:

# -*- coding: utf-8 -*-
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 獲取MNIST數據
mnist = input_data.read_data_sets(r"./MNIST_data", one_hot=True)

# 設置RNN結構
element_size = 28
time_steps = 28
num_classes = 10
batch_size = 128
hidden_layer_size = 150

# 輸入向量和輸出向量
_inputs = tf.placeholder(tf.float32, shape=[None, time_steps, element_size], name='inputs')
y = tf.placeholder(tf.float32, shape=[None, num_classes], name='inputs')

# 利用TensorFlow的內置函數BasicRNNCell, dynamic_rnn來構建RNN的基本模塊
rnn_cell = tf.contrib.rnn.BasicRNNCell(hidden_layer_size)
outputs, _ = tf.nn.dynamic_rnn(rnn_cell, _inputs, dtype=tf.float32)
Wl = tf.Variable(tf.truncated_normal([hidden_layer_size, num_classes], mean=0,stddev=.01))
bl = tf.Variable(tf.truncated_normal([num_classes],mean=0,stddev=.01))

def get_linear_layer(vector):
    return tf.matmul(vector, Wl) + bl

# 取輸出的向量outputs中的最后一個向量最為最終輸出
last_rnn_output = outputs[:,-1,:]
final_output = get_linear_layer(last_rnn_output)

# 定義損失函數並用RMSPropOptimizer優化
softmax = tf.nn.softmax_cross_entropy_with_logits(logits=final_output, labels=y)
cross_entropy = tf.reduce_mean(softmax)
train_step = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cross_entropy)

# 統計准確率
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(final_output,1))
accuracy = (tf.reduce_mean(tf.cast(correct_prediction, tf.float32)))*100

sess=tf.InteractiveSession()
sess.run(tf.global_variables_initializer())
# 測試集
test_data = mnist.test.images[:batch_size].reshape((-1, time_steps, element_size))
test_label = mnist.test.labels[:batch_size]

# 每次訓練batch_size張圖片,一共訓練3000次
for i in range(3001):
    batch_x, batch_y = mnist.train.next_batch(batch_size)
    batch_x = batch_x.reshape((batch_size, time_steps, element_size))
    sess.run(train_step, feed_dict={_inputs:batch_x, y:batch_y})
    if i % 100 == 0:
        loss = sess.run(cross_entropy, feed_dict={_inputs: batch_x, y: batch_y})
        acc = sess.run(accuracy, feed_dict={_inputs:batch_x, y: batch_y})
        print ("Iter " + str(i) + ", Minibatch Loss= " + \
               "{:.6f}".format(loss) + ", Training Accuracy= " + \
               "{:.5f}".format(acc))

# 在測試集上的准確率
print("Testing Accuracy:", sess.run(accuracy, feed_dict={_inputs:test_data, y:test_label}))

  運行上述代碼,輸出的結果如下:

Extracting ./MNIST_data\train-images-idx3-ubyte.gz
Extracting ./MNIST_data\train-labels-idx1-ubyte.gz
Extracting ./MNIST_data\t10k-images-idx3-ubyte.gz
Extracting ./MNIST_data\t10k-labels-idx1-ubyte.gz
Iter 0, Minibatch Loss= 2.301171, Training Accuracy= 11.71875
Iter 100, Minibatch Loss= 1.718483, Training Accuracy= 47.65625
Iter 200, Minibatch Loss= 0.862968, Training Accuracy= 71.09375
Iter 300, Minibatch Loss= 0.513068, Training Accuracy= 86.71875
Iter 400, Minibatch Loss= 0.570475, Training Accuracy= 83.59375
Iter 500, Minibatch Loss= 0.254566, Training Accuracy= 92.96875
Iter 600, Minibatch Loss= 0.457989, Training Accuracy= 85.93750
Iter 700, Minibatch Loss= 0.151181, Training Accuracy= 96.87500
Iter 800, Minibatch Loss= 0.171168, Training Accuracy= 94.53125
Iter 900, Minibatch Loss= 0.142494, Training Accuracy= 94.53125
Iter 1000, Minibatch Loss= 0.155114, Training Accuracy= 97.65625
Iter 1100, Minibatch Loss= 0.096007, Training Accuracy= 96.87500
Iter 1200, Minibatch Loss= 0.341476, Training Accuracy= 88.28125
Iter 1300, Minibatch Loss= 0.133509, Training Accuracy= 96.87500
Iter 1400, Minibatch Loss= 0.076408, Training Accuracy= 98.43750
Iter 1500, Minibatch Loss= 0.122228, Training Accuracy= 98.43750
Iter 1600, Minibatch Loss= 0.099382, Training Accuracy= 96.87500
Iter 1700, Minibatch Loss= 0.084686, Training Accuracy= 97.65625
Iter 1800, Minibatch Loss= 0.067009, Training Accuracy= 98.43750
Iter 1900, Minibatch Loss= 0.189703, Training Accuracy= 94.53125
Iter 2000, Minibatch Loss= 0.116077, Training Accuracy= 96.09375
Iter 2100, Minibatch Loss= 0.028867, Training Accuracy= 100.00000
Iter 2200, Minibatch Loss= 0.064198, Training Accuracy= 99.21875
Iter 2300, Minibatch Loss= 0.078259, Training Accuracy= 97.65625
Iter 2400, Minibatch Loss= 0.106613, Training Accuracy= 97.65625
Iter 2500, Minibatch Loss= 0.078722, Training Accuracy= 98.43750
Iter 2600, Minibatch Loss= 0.045871, Training Accuracy= 98.43750
Iter 2700, Minibatch Loss= 0.030953, Training Accuracy= 99.21875
Iter 2800, Minibatch Loss= 0.062823, Training Accuracy= 96.87500
Iter 2900, Minibatch Loss= 0.040367, Training Accuracy= 99.21875
Iter 3000, Minibatch Loss= 0.017787, Training Accuracy= 100.00000
Testing Accuracy: 97.6563

可以看到,用簡單RNN來識別MNIST數據集,也能取得很好的效果!

  本次分享到此結束,歡迎大家交流~

注意:本人現已開通微信公眾號: 輕松學會Python爬蟲(微信號為:easy_web_scrape), 歡迎大家關注哦~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM