111
人物
送機器學習電子書——(TensorFlow)RNN入門
更多深度文章,請關注雲計算頻道:https://yq.aliyun.com/cloud
今天我們將研究一種名為循環神經網絡的神經網絡體係結構。它針對的不是自然語言數據,而是處理連續的時間數據,如股票市場價格。在本文結束之時,你將能夠對時間序列數據中的模式進行建模,以對未來的值進行預測。
1.上下文信息
回到學校,我的一個期中考試僅由真的或假的問題組成時。假設一半的答案是“真的”,而另一半則是“假的”。我想出了大部分問題的答案,剩下的是靠隨機猜測。我做了一件聰明的事情,也許你也可以嚐試一下這個策略。在計數了我的“真”的答案之後,我意識到它與“假”這個答案不成比例。於是我的大部分猜測是“假”的,這樣就可以平衡分配。
這竟然是有效的。在那一時刻我感覺到我是狡猾的。這是什麼樣的判斷力,使我們對自己的決定那麼有信心,我們又如何將這種判斷力給予神經網絡?
這個問題的一個答案是使用上下文來回答問題。語境提示是可以提高機器學習算法性能的重要信號。例如,假設你想檢查一個英文句子,並標記每個單詞的詞性。
傻傻的方法是將每個單詞單獨分類為“名詞”,“形容詞”等,而不確認其相鄰的單詞。單詞“努力”被用作動詞,但根據上下文,你也可以使用它作為一個形容詞,單純的詞性標注是一個需要努力的問題。
更好的方法是考慮上下文信息。為了向神經網絡提供上下文信息,我們可以使用稱為循環神經網絡的體係結構。
循環神經網絡(RNN)簡介
為了理解循環神經網絡(RNN),我們首先來看一下圖1所示的簡單架構。它將輸入向量X(t)作為輸入,並在某個時間(t)產生一個向量Y(t)的輸出。中間的圓圈表示網絡的隱藏層。
圖1分別具有標記為X(k)和Y(k)的輸入和輸出層的神經網絡
通過足夠的輸入/輸出示例,你可以在TensorFlow中了解網絡的參數。例如,我們將輸入權重稱為矩陣W in,輸出權重作為矩陣W out。假設有一個隱藏層,稱為向量Z(t)。
如圖2所示,神經網絡的前半部分的特征在於函數Z(t)= X(t)* W in,神經網絡的後半部分形式為Y(t)= Z(t)* W out。同樣,如果你願意,整個神經網絡可以是函數Y(t)=(X(t)* Win)* W out。
圖2神經網絡的隱藏層可以被認為是數據的隱藏,由其輸入權重編碼並輸出權重解碼。
在微調神經網絡後,你可能希望在現實世界的場景中開始使用你所學習的模型。通常,這意味著你將多次調用該模型,甚至可能連續反複調用,如圖3所示。
圖3通常,我們會運行相同的神經網絡多次,而不考慮關於先前運行的隱藏狀態。
在每個時間t,當調用學習模型時,這種體係結構不考慮關於以前運行的結果經驗。就像預測股市走勢一樣,隻看當前的數據。循環神經網絡(RNN)與傳統神經網絡不同,因為它引入了轉移權重W來跨越時間傳遞信息。圖4顯示了必須在RNN中學習的三個加權矩陣。
圖4循環神經網絡架構可以利用網絡的先前狀態來實現其優點。
理論上很好理解,但是你在這裏必須要親自動手做一下。讓我們來吧!接下來將介紹如何使用TensorFlow的內置RNN模型。我們將使用這個RNN在現實世界的時間數據來預測未來!
2.實施循環神經網絡
當我們實施RNN時,我們將使用TensorFlow。如圖4所示,你不需要手動構建網絡,因為TensorFlow庫中已經支持一些魯棒(robust)的RNN模型。
參考有關RNN的TensorFlow庫信息,請參見https://www.tensorflow.org/tutorials/recurrent。
RNN的一種類型模型被稱為長短期記憶網絡(LSTM)。我覺得這是一個有趣的名字。它聽起來也意味著:短期模式長期不會被遺忘。
LSTM的精確實現細節不在本文的範圍之內。相信我,如果隻學習LSTM模型會分散我們的注意力,因為它還沒有確定的標準。
進一步閱讀:為了了解如何從頭開始執行LSTM,我建議你閱讀以下的文章:https://apaszke.github.io/lstm-explained.html
我們現在開始我們的教程。首先從編寫我們的代碼開始,先創建一個新的文件,叫做simple_regression.py
。導入相關的庫,如步驟1所示。
步驟1:導入相關庫
import numpy as np
import tensorflow as tf
from tensorflow.contrib import rnn
接著,定義一個類叫做SeriesPredictor
。如步驟2所示,構造函數裏麵設置模型超參數,權重和成本函數。
步驟2:定義一個類及其構造函數
class SeriesPredictor:
def __init__(self, input_dim, seq_size, hidden_dim=10):
self.input_dim = input_dim //#A
self.seq_size = seq_size //#A
self.hidden_dim = hidden_dim //#A
self.W_out = tf.Variable(tf.random_normal([hidden_dim, 1]),name='W_out') //#B
self.b_out = tf.Variable(tf.random_normal([1]), name='b_out') //#B
self.x = tf.placeholder(tf.float32, [None, seq_size, input_dim]) //#B
self.y = tf.placeholder(tf.float32, [None, seq_size]) //#B
self.cost = tf.reduce_mean(tf.square(self.model() - self.y)) //#C
self.train_op = tf.train.AdamOptimizer().minimize(self.cost) //#C
self.saver = tf.train.Saver() //#D
#A超參數。
#B權重變量和輸入占位符。
#C成本優化器(cost optimizer)。
#D輔助操作。
接下來,我們使用TensorFlow的內置RNN模型,名為BasicLSTMCell。LSTM單元的隱藏維度是通過時間的隱藏狀態的維度。我們可以使用該rnn.dynamic_rnn
函數處理這個單元格數據,以檢索輸出結果。步驟3詳細介紹了如何使用TensorFlow來實現使用LSTM的預測模型。
步驟3:定義RNN模型
def model(self):
"""
:param x: inputs of size [T, batch_size, input_size]
:param W: matrix of fully-connected output layer weights
:param b: vector of fully-connected output layer biases
"""
cell = rnn.BasicLSTMCell(self.hidden_dim) #A
outputs, states = tf.nn.dynamic_rnn(cell, self.x, dtype=tf.float32) #B
num_examples = tf.shape(self.x)[0]
W_repeated = tf.tile(tf.expand_dims(self.W_out, 0), [num_examples, 1, 1])#C
out = tf.matmul(outputs, W_repeated) + self.b_out
out = tf.squeeze(out)
return out
#A創建一個LSTM單元。
#B運行輸入單元,獲取輸出和狀態的張量。
#C將輸出層計算為完全連接的線性函數。
通過定義模型和成本函數,我們現在可以實現訓練函數,該函數學習給定示例輸入/輸出對的LSTM權重。如步驟4所示,你打開會話並重複運行優化器。
另外,你可以使用交叉驗證來確定訓練模型的迭代次數。在這裏我們假設固定數量的epocs。
訓練後,將模型保存到文件中,以便稍後加載使用。
步驟4:在一個數據集上訓練模型
def train(self, train_x, train_y):
with tf.Session() as sess:
tf.get_variable_scope().reuse_variables()
sess.run(tf.global_variables_initializer())
for i in range(1000): #A
mse = sess.run([self.train_op, self.cost], feed_dict={self.x: train_x, self.y: train_y})
if i % 100 == 0:
print(i, mse)
save_path = self.saver.save(sess, 'model.ckpt')
print('Model saved to {}'.format(save_path))
#A訓練1000次
我們的模型已經成功地學習了參數。接下來,我們想評估利用其他數據來評估以下預測模型的性能。步驟5加載已保存的模型,並通過饋送一些測試數據以此來運行模型。如果學習的模型在測試數據上表現不佳,那麼我們可以嚐試調整LSTM單元格的隱藏維數。
步驟5:測試學習的模型
def test(self, test_x):
with tf.Session() as sess:
tf.get_variable_scope().reuse_variables()
self.saver.restore(sess, './model.ckpt')
output = sess.run(self.model(), feed_dict={self.x: test_x})
print(output)
但為了完善自己的工作,讓我們組成一些數據,並嚐試訓練預測模型。在步驟6中,我們將創建輸入序列,稱為train_x
,和相應的輸出序列,稱為train_y
。
步驟6訓練並測試一些虛擬數據
if __name__ == '__main__':
predictor = SeriesPredictor(input_dim=1, seq_size=4, hidden_dim=10)
train_x = [[[1], [2], [5], [6]],
[[5], [7], [7], [8]],
[[3], [4], [5], [7]]]
train_y = [[1, 3, 7, 11],
[5, 12, 14, 15],
[3, 7, 9, 12]]
predictor.train(train_x, train_y)
test_x = [[[1], [2], [3], [4]], #A
[[4], [5], [6], [7]]] #B
predictor.test(test_x)
#A預測結果應為1,3,5,7。
#B預測結果應為4,9,11,13。
你可以將此預測模型視為黑盒子,並用現實世界的時間數據進行測試。
這篇博文隻是我新書的一小部分,如果你想要學習更多的知識請移步:
Machine Learning with TensorFlow
本文由北郵@愛可可-愛生活老師推薦,阿裏雲雲棲社區組織整理。
文章原標題:《Recurrent Neural Networks》
作者:Nishant Shukla 機器學習布道者
譯者:虎說八道。審校:主題曲哥哥。
文章為簡譯,更為詳細的內容,請查看原文
最後更新:2017-10-10 14:33:30