TensorFlow實現(xiàn)RNN循環(huán)神經(jīng)網(wǎng)絡
RNN(recurrent neural Network)循環(huán)神經(jīng)網(wǎng)絡
主要用于自然語言處理(nature language processing,NLP)
RNN主要用途是處理和預測序列數(shù)據(jù)
RNN廣泛的用于 語音識別、語言模型、機器翻譯
RNN的來源就是為了刻畫一個序列當前的輸出與之前的信息影響后面節(jié)點的輸出
RNN 是包含循環(huán)的網(wǎng)絡,允許信息的持久化。
RNN會記憶之前的信息,并利用之前的信息影響后面節(jié)點的輸出。
RNN的隱藏層之間的節(jié)點是有相連的,隱藏層的輸入不僅僅包括輸入層的輸出,還包括上一時刻隱藏層的輸出。
RNN會對于每一個時刻的輸入結(jié)合當前模型的狀態(tài)給出一個輸出。
RNN理論上被看作同一個神經(jīng)網(wǎng)絡結(jié)構(gòu)被無限復制的結(jié)果,目前RNN無法做到真正的無限循環(huán),一般以循環(huán)體展開。
RNN圖:

RNN最擅長的問題是與時間序列相關(guān)的。
RNN對于一個序列數(shù)據(jù),可以將序列上不同時刻的數(shù)據(jù)依次輸入循環(huán)神經(jīng)網(wǎng)絡的輸入層,而輸出可以是對序列中下一個時刻的預測,也可以是對當前時刻信息的處理結(jié)果。
RNN 的關(guān)鍵點之一就是他們可以用來連接先前的信息到當前的任務上
展開后的RNN:

循環(huán)體網(wǎng)絡中的參數(shù)在不同的時刻也是共享的。
RNN的狀態(tài)是通過一個向量來表示,這個向量的維度也稱為RNN隱藏層的大小。
假如該向量為h,輸入為x,激活函數(shù)為tanh,則有如圖:

前向傳播的計算過程:

理論上RNN可以支持任意長度的序列,但是如果序列太長會導致優(yōu)化時實現(xiàn)梯度消失的問題,一般會設置最大長度,超長會對其截斷。
代碼實現(xiàn)簡單的RNN:
import numpy as np
# 定義RNN的參數(shù)。
X = [1,2]
state = [0.0, 0.0]
w_cell_state = np.asarray([[0.1, 0.2], [0.3, 0.4]])
w_cell_input = np.asarray([0.5, 0.6])
b_cell = np.asarray([0.1, -0.1])
w_output = np.asarray([[1.0], [2.0]])
b_output = 0.1
# 執(zhí)行前向傳播過程。
for i in range(len(X)):
before_activation = np.dot(state, w_cell_state) + X[i] * w_cell_input + b_cell
state = np.tanh(before_activation)
final_output = np.dot(state, w_output) + b_output
print ("before activation: ", before_activation)
print ("state: ", state)
print ("output: ", final_output)
LSTM(long short-term memory)長短時記憶網(wǎng)絡:
LSTM解決了RNN不支持長期依賴的問題,使其大幅度提升記憶時長。
RNN被成功應用的關(guān)鍵就是LSTM。
LSTM是一種擁有三個“門”結(jié)構(gòu)的特殊網(wǎng)絡結(jié)構(gòu)。

粉色的圈代表 pointwise 的操作,諸如向量的和,而黃色的矩陣就是學習到的神經(jīng)網(wǎng)絡層。合在一起的線表示向量的連接,分開的線表示內(nèi)容被復制,然后分發(fā)到不同的位置。
LSTM核心思想:
LSTM 的關(guān)鍵就是細胞狀態(tài),水平線在圖上方貫穿運行。
細胞狀態(tài)類似于傳送帶。直接在整個鏈上運行,只有一些少量的線性交互,信息在上面流傳保持不變會很容易。

LSTM 有通過精心設計的稱作為“門”的結(jié)構(gòu)來去除或者增加信息到細胞狀態(tài)的能力。
“門”是一種讓信息選擇式通過的方法,包含一個sigmoid 神經(jīng)網(wǎng)絡層和一個 pointwise (按位做乘法)的操作。
之所以稱之為“門”,因為使用Sigmoid 作為激活函數(shù)的層會輸出 0 到 1 之間的數(shù)值,描述每個部分有多少信息量可以通過這個結(jié)構(gòu)。
0 代表“不許任何量通過”,1 就指“允許任意量通過”!
LSTM的公式:

代碼實現(xiàn):
import tensorflow as tf
# 定義一個LSTM結(jié)構(gòu)
lstm = rnn_cell.BasicLSTMCell(lstm_hidden_size)
# 將LSTM中的狀態(tài)初始化為全0數(shù)組,每次使用一個batch的訓練樣本
state = lstm.zero_state(batch_size,tf.float32)
# 定義損失函數(shù)
loss = 0.0
# 規(guī)定一個最大序列長度
for i in range(num_steps):
# 復用之前定義的變量
if i > 0:
tf.get_variable_scope().reuse_variables()
# 將當前輸入和前一時刻的狀態(tài)傳入定義的LSTM結(jié)構(gòu),得到輸出和更新后的狀態(tài)
lstm_output, state = lstm(current_input,state)
# 將當前時刻的LSTM結(jié)構(gòu)的輸出傳入一個全連接層得到最后的輸出。
final_output = fully_connectd(lstm_output)
# 計算當前時刻輸出的損失
loss += calc_loss(final_output,expected_output)
雙向循環(huán)神經(jīng)網(wǎng)絡
經(jīng)典的循環(huán)神經(jīng)網(wǎng)絡中的狀態(tài)傳輸是從前往后單向的,然而當前時刻的輸出不僅和之前的狀態(tài)有關(guān)系,也和之后的狀態(tài)相關(guān)。
雙向循環(huán)神經(jīng)網(wǎng)絡能解決狀態(tài)單向傳輸?shù)膯栴}。
雙向循環(huán)神經(jīng)網(wǎng)絡是由兩個循環(huán)神經(jīng)網(wǎng)絡反向上下疊加在一起組成,兩個循環(huán)神經(jīng)網(wǎng)絡的狀態(tài)共同決定輸出。
也就是時間t時的輸出不僅僅取決于過去的記憶,也同樣取決于后面發(fā)生的事情。

深層(雙向)循環(huán)神經(jīng)網(wǎng)絡
深層循環(huán)神經(jīng)網(wǎng)絡似于雙向循環(huán)神經(jīng)網(wǎng)絡,只不過是每個時長內(nèi)都有多層。
深層循環(huán)神經(jīng)網(wǎng)絡有更強的學習能力。
深層循環(huán)神經(jīng)網(wǎng)絡在每個時刻上將循環(huán)體結(jié)構(gòu)復制多次,和卷積神經(jīng)網(wǎng)絡類似,每一層循環(huán)體中的參數(shù)是一致的,不同層的參數(shù)可以不同。

TensorFlow中使用MultiRNNCell實現(xiàn)深層循環(huán)神經(jīng)網(wǎng)絡中每一個時刻的前向傳播過程。剩下的步驟和RNN的構(gòu)建步驟相同。
RNN中的dropout
通過dropout方法可以上卷積神經(jīng)網(wǎng)絡更加健壯,類似的用在RNN上也能取得同樣的效果。
類似卷積神經(jīng)網(wǎng)絡,RNN只在最后的全連接層使用dropout。
RNN一般只在不同層循環(huán)體結(jié)構(gòu)中使用dropout,不在同層循環(huán)體使用。
同一時刻t中,不同循環(huán)體之間會使用dropout。
在TensorFlow中,使用DropoutWrapper類實現(xiàn)dropout功能。
通過input_keep_prob參數(shù)控制輸入的dropout概率
通過output_keep_prob參數(shù)控制輸出的dropout概率
TensorFlow樣例實現(xiàn)RNN語言模型
代碼:
import numpy as np
import tensorflow as tf
import reader
DATA_PATH = "../datasets/PTB/data"
HIDDEN_SIZE = 200 # 隱藏層規(guī)模
NUM_LAYERS = 2 # 深層RNN中的LSTM結(jié)構(gòu)的層數(shù)
VOCAB_SIZE = 10000 # 單詞標識符個數(shù)
LEARNING_RATE = 1.0 # 學習速率
TRAIN_BATCH_SIZE = 20 # 訓練數(shù)據(jù)大小
TRAIN_NUM_STEP = 35 # 訓練數(shù)據(jù)截斷長度
# 測試時不需要截斷
EVAL_BATCH_SIZE = 1 # 測試數(shù)據(jù)大小
EVAL_NUM_STEP = 1 # 測試數(shù)據(jù)截斷長度
NUM_EPOCH = 2 # 使用訓練數(shù)據(jù)輪數(shù)
KEEP_PROB = 0.5 # 節(jié)點不被dropout
MAX_GRAD_NORM = 5 # 控制梯度膨脹參數(shù)
# 定義一個類來描述模型結(jié)構(gòu)。
class PTBModel (object):
def __init__(self, is_training, batch_size, num_steps):
self.batch_size = batch_size
self.num_steps = num_steps
# 定義輸入層。
self.input_data = tf.placeholder (tf.int32, [batch_size, num_steps])
self.targets = tf.placeholder (tf.int32, [batch_size, num_steps])
# 定義使用LSTM結(jié)構(gòu)及訓練時使用dropout。
lstm_cell = tf.contrib.rnn.BasicLSTMCell (HIDDEN_SIZE)
if is_training:
lstm_cell = tf.contrib.rnn.DropoutWrapper (lstm_cell, output_keep_prob=KEEP_PROB)
cell = tf.contrib.rnn.MultiRNNCell ([lstm_cell] * NUM_LAYERS)
# 初始化最初的狀態(tài)。
self.initial_state = cell.zero_state (batch_size, tf.float32)
embedding = tf.get_variable ("embedding", [VOCAB_SIZE, HIDDEN_SIZE])
# 將原本單詞ID轉(zhuǎn)為單詞向量。
inputs = tf.nn.embedding_lookup (embedding, self.input_data)
if is_training:
inputs = tf.nn.dropout (inputs, KEEP_PROB)
# 定義輸出列表。
outputs = []
state = self.initial_state
with tf.variable_scope ("RNN"):
for time_step in range (num_steps):
if time_step > 0: tf.get_variable_scope ().reuse_variables ()
cell_output, state = cell (inputs[:, time_step, :], state)
outputs.append (cell_output)
output = tf.reshape (tf.concat (outputs, 1), [-1, HIDDEN_SIZE])
weight = tf.get_variable ("weight", [HIDDEN_SIZE, VOCAB_SIZE])
bias = tf.get_variable ("bias", [VOCAB_SIZE])
logits = tf.matmul (output, weight) + bias
# 定義交叉熵損失函數(shù)和平均損失。
loss = tf.contrib.legacy_seq2seq.sequence_loss_by_example (
[logits],
[tf.reshape (self.targets, [-1])],
[tf.ones ([batch_size * num_steps], dtype=tf.float32)])
self.cost = tf.reduce_sum (loss) / batch_size
self.final_state = state
# 只在訓練模型時定義反向傳播操作。
if not is_training: return
trainable_variables = tf.trainable_variables ()
# 控制梯度大小,定義優(yōu)化方法和訓練步驟。
grads, _ = tf.clip_by_global_norm (tf.gradients (self.cost, trainable_variables), MAX_GRAD_NORM)
optimizer = tf.train.GradientDescentOptimizer (LEARNING_RATE)
self.train_op = optimizer.apply_gradients (zip (grads, trainable_variables))
# 使用給定的模型model在數(shù)據(jù)data上運行train_op并返回在全部數(shù)據(jù)上的perplexity值
def run_epoch(session, model, data, train_op, output_log, epoch_size):
total_costs = 0.0
iters = 0
state = session.run(model.initial_state)
# 訓練一個epoch。
for step in range(epoch_size):
x, y = session.run(data)
cost, state, _ = session.run([model.cost, model.final_state, train_op],
{model.input_data: x, model.targets: y, model.initial_state: state})
total_costs += cost
iters += model.num_steps
if output_log and step % 100 == 0:
print("After %d steps, perplexity is %.3f" % (step, np.exp(total_costs / iters)))
return np.exp(total_costs / iters)
# 定義主函數(shù)并執(zhí)行
def main():
train_data, valid_data, test_data, _ = reader.ptb_raw_data(DATA_PATH)
# 計算一個epoch需要訓練的次數(shù)
train_data_len = len(train_data)
train_batch_len = train_data_len // TRAIN_BATCH_SIZE
train_epoch_size = (train_batch_len - 1) // TRAIN_NUM_STEP
valid_data_len = len(valid_data)
valid_batch_len = valid_data_len // EVAL_BATCH_SIZE
valid_epoch_size = (valid_batch_len - 1) // EVAL_NUM_STEP
test_data_len = len(test_data)
test_batch_len = test_data_len // EVAL_BATCH_SIZE
test_epoch_size = (test_batch_len - 1) // EVAL_NUM_STEP
initializer = tf.random_uniform_initializer(-0.05, 0.05)
with tf.variable_scope("language_model", reuse=None, initializer=initializer):
train_model = PTBModel(True, TRAIN_BATCH_SIZE, TRAIN_NUM_STEP)
with tf.variable_scope("language_model", reuse=True, initializer=initializer):
eval_model = PTBModel(False, EVAL_BATCH_SIZE, EVAL_NUM_STEP)
# 訓練模型。
with tf.Session() as session:
tf.global_variables_initializer().run()
train_queue = reader.ptb_producer(train_data, train_model.batch_size, train_model.num_steps)
eval_queue = reader.ptb_producer(valid_data, eval_model.batch_size, eval_model.num_steps)
test_queue = reader.ptb_producer(test_data, eval_model.batch_size, eval_model.num_steps)
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=session, coord=coord)
for i in range(NUM_EPOCH):
print("In iteration: %d" % (i + 1))
run_epoch(session, train_model, train_queue, train_model.train_op, True, train_epoch_size)
valid_perplexity = run_epoch(session, eval_model, eval_queue, tf.no_op(), False, valid_epoch_size)
print("Epoch: %d Validation Perplexity: %.3f" % (i + 1, valid_perplexity))
test_perplexity = run_epoch(session, eval_model, test_queue, tf.no_op(), False, test_epoch_size)
print("Test Perplexity: %.3f" % test_perplexity)
coord.request_stop()
coord.join(threads)
if __name__ == "__main__":
main()
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- 深度學習TextRNN的tensorflow1.14實現(xiàn)示例
- python循環(huán)神經(jīng)網(wǎng)絡RNN函數(shù)tf.nn.dynamic_rnn使用
- python人工智能tensorflow構(gòu)建循環(huán)神經(jīng)網(wǎng)絡RNN
- Python使用循環(huán)神經(jīng)網(wǎng)絡解決文本分類問題的方法詳解
- 基于循環(huán)神經(jīng)網(wǎng)絡(RNN)實現(xiàn)影評情感分類
- 基于循環(huán)神經(jīng)網(wǎng)絡(RNN)的古詩生成器
- 循環(huán)神經(jīng)網(wǎng)絡TextRNN實現(xiàn)情感短文本分類任務
相關(guān)文章
Python opencv缺陷檢測的實現(xiàn)及問題解決
這篇文章主要介紹了Python opencv缺陷檢測的實現(xiàn)及問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04
Python3讀取Excel數(shù)據(jù)存入MySQL的方法
今天小編就為大家分享一篇Python3讀取Excel數(shù)據(jù)存入MySQL的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05

