【機器學習】RNN學習

小說:1月份可以種植常春藤種子嗎?作者:王順北華更新時間:2019-05-27字數:60003

真正可怕的是你們這些駕駛高達的人,在你們手中高達的性能超越極限的發揮,達到一種可怕的地步,戰艦的破壞力雖然大,但是在你們駕馭的高達面前根本就是靶子。

2017年最新木瓜海棠價格

不過就算天河之水的力量沒有爆發出來,可這畢竟是共工的真元法力所化的天河之水,就算沒有爆發出其力量來也十分的恐怖,云天河和韓菱紗了,兩個玄仙聯手之下加上后天靈寶望舒劍的力量才勉強凍結住天河之水。
這一下銀河星爆比起剛才對付潘多拉的終極死亡的那一次大了幾倍,顯然加隆是不想殺死潘多拉,所以留有余地,但是現在潘多拉的實力已經嚴重威脅到加隆了,所以加隆也不敢留手,畢竟他可不想一不小心掛掉了。

“是,大師?!北妼W員同時應聲。原本出現了幾分差別的眼神重新變得一致。不知道為什么,一向心境平和的唐三此時心中對勝利極其渴望。

【機器學習】RNN學習


感謝中國人民大學的胡鶴老師,課程容量巨大,收獲頗豐。

之前提到的CNN模型主要用到人類的視覺中樞,但其有一劣勢,無論是人類的視覺神經還是聽覺神經,所接受到的都是一個連續的序列,使用CNN相當于割裂了前后的聯系。從而誕生了專門為處理序列的Recurrent Neural Network(RNN),每一個神經元除了當前信息的輸入外,還有之前產生的記憶信息,保留序列依賴型。

一、RNN基本原理

如下圖所示有兩種表示方法,每張圖片左邊是RNN的神經元(稱為memory cell),右邊是按時間軸展開后的情況。每次輸入兩個信息輸出兩個信息,每輪處理hidden state。把同樣神經元在時間上展開處理,比CNN更加節省參數,是一個相當高效的表示方法。

?

可參考如下公式表示,最后簡化后的形式同一般神經元相同,輸入信息乘權重加偏值:

由于t狀態的t由t-1時候決定,因而具有記憶功能,也叫作memory cell(或cell)

隱狀態可由如下表示:

隱狀態是當前t時刻的狀態,也由t-1時刻決定,簡單情況下,hidden state等同于output(y),但大多較為復雜的cell中,它們并不相同。如下圖所示:

?

二、RNN種類:

1. sequence-to-sequence:輸入輸出都是一個序列。例如股票預測中的RNN,輸入是前N天價格,輸出明天的股市價格。

2. sequence-to-vector:輸入是一個序列,輸出單一向量。

  例如,輸入一個電影評價序列,輸出一個分數表示情感趨勢(喜歡還是討厭)。

3. vector-to-sequence:輸入單一向量,輸出一個序列。

4.Encoder-Decoder:輸入sequence-to-vector,稱作encoder,輸出vector-to-sequence,稱作decoder。

這是一個delay模型,經過一段延遲,即把所有輸入都讀取后,在decoder中獲取輸入并輸出一個序列。這個模型在機器翻譯中使用較廣泛,源語言輸在入放入encoder,濃縮在狀態信息中,生成目標語言時,可以生成一個不長度的目標語言序列。

?

?三、RNN實例

1.手動實現

以下是一個手動實現RNN的實例

n_inputs = 3
# hidden state 
n_neurons = 5

X0 = tf.placeholder(tf.float32, [None, n_inputs])
X1 = tf.placeholder(tf.float32, [None, n_inputs])

# 由于Wx要和X相乘,故低維是n_inputs
Wx = tf.Variable(tf.random_normal(shape=[n_inputs, n_neurons],dtype=tf.float32))
# 低維,高維都是n_neurons,為了使得輸出也是hidden state的深度
# 這樣下一次才可以繼續運算
Wy = tf.Variable(tf.random_normal(shape=[n_neurons,n_neurons],dtype=tf.float32))
b = tf.Variable(tf.zeros([1, n_neurons], dtype=tf.float32))

# Y0初始化為0,初始時沒有記憶
Y0 = tf.tanh(tf.matmul(X0, Wx) + b)
# 把上一輪輸出Y0也作為輸入
Y1 = tf.tanh(tf.matmul(Y0, Wy) + tf.matmul(X1, Wx) + b)
init = tf.global_variables_initializer()
import numpy as np
X0_batch = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 0, 1]]) # t = 0 
X1_batch = np.array([[9, 8, 7], [0, 0, 0], [6, 5, 4], [3, 2, 1]]) # t = 1  
with tf.Session() as sess:
  init.run()
  Y0_val, Y1_val = sess.run([Y0, Y1], feed_dict={X0: X0_batch, X1: X1_batch}) 

# Y0,Y1都是4*5大小,4是mini-batch數目,5是輸出神經元個數

TensorFlow函數集成后實現

2.static unrolling through time

static_rnn()是使用鏈式cells實現一個按時間軸展開的RNN

# 這種和上面那種手動實現的效果相同
n_inputs = 3
n_neurons = 5
X0 = tf.placeholder(tf.float32, [None, n_inputs])
X1 = tf.placeholder(tf.float32, [None, n_inputs])

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
output_seqs, states = tf.contrib.rnn.static_rnn(basic_cell, [X0, X1], dtype=tf.float32)
Y0, Y1 = output_seqs
# run部分
init = tf.global_variables_initializer()
X0_batch = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 0, 1]])
X1_batch = np.array([[9, 8, 7], [0, 0, 0], [6, 5, 4], [3, 2, 1]])

with tf.Session() as sess:
    init.run()
    Y0_val, Y1_val = sess.run([Y0, Y1], feed_dict={X0: X0_batch, X1: X1_batch})

packing sequence

n_steps = 2
n_inputs = 3
n_neurons = 5
# 輸入是一個三維tensor,none是mini-batch大小不限,n_steps是序列長度
X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
# 把一個高維度n的tensor展開成一個n-1維,降維,這里是3位降到2維列表
# unstack之前要做一個1,2維轉置,相當于構造了n_steps個數的列表
X_seqs = tf.unstack(tf.transpose(X, perm=[1, 0, 2]))
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
# states是最新狀態
output_seqs, states = tf.contrib.rnn.static_rnn( basic_cell, X_seqs, dtype=tf.float32) 
# 再做一個轉置,和輸入對應 
outputs = tf.transpose(tf.stack(output_seqs), perm=[1, 0, 2]) 
# 輸入大小4*2*3 
X_batch = np.array([ 
# t = 0     t = 1 
[[0, 1, 2], [9, 8, 7]], # instance 0 
[[3, 4, 5], [0, 0, 0]], # instance 1 
[[6, 7, 8], [6, 5, 4]], # instance 2 
[[9, 0, 1], [3, 2, 1]], # instance 3 
]) 
with tf.Session() as sess:
 init.run()
 outputs_val = outputs.eval(feed_dict={X: X_batch})
 # output_val是一個4*2*5,僅輸出維度神經元個數改變

3. dynamic RNN

本身支持高維tensor輸入,內嵌一個循環運行足夠多次數的cell,不需要unstack步驟。

這個內嵌循環while_loop()在前向傳播中將每次迭代的tensor值存儲下來,以便于反向傳播過程中使用其計算梯度值。

X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
# 動態RNN內部封裝一個循環
# 根據輸入,動態決定自己需要展開幾次
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)

dynamicRNN可以動態規定輸入大?。ň拖窬渥虞斎耄?/span>

n_steps = 2
n_inputs = 3
n_neurons = 5

X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
seq_length = tf.placeholder(tf.int32, [None])
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32, sequence_length=seq_length)
init = tf.global_variables_initializer()
# X_batch的大小4*2*3
X_batch = np.array([
        # step 0     step 1
        [[0, 1, 2], [9, 8, 7]], # instance 1
        [[3, 4, 5], [0, 0, 0]], # instance 2 (padded with zero vectors)
        [[6, 7, 8], [6, 5, 4]], # instance 3
        [[9, 0, 1], [3, 2, 1]], # instance 4
    ])
# 這里設置sequence大小,一共4個batch,第二維上只取第一個
seq_length_batch = np.array([2, 1, 2, 2])
with tf.Session() as sess:
    init.run()
    outputs_val, states_val = sess.run(
        [outputs, states], feed_dict={X: X_batch, seq_length: seq_length_batch})

?如果事先不知道輸出序列的長度,就需要定義一個end-of-sequence token(eos token),無論是課上還是網上相關信息都很少,這里就不展開了。。

四、RNN訓練

1. 擬合分類

RNN比較難以訓練,單是如下圖的節點中,cost function就包含y2,y3,y4三個輸出,往回回溯。

以下MINIST中使用150個RNN神經元,最后加一個全連接層,得到10個神經元的輸出(分別對應0-9),最后看對應在

?

?

from tensorflow.contrib.layers import fully_connected
n_steps = 28
n_inputs = 28
n_neurons = 150
n_outputs = 10
learning_rate = 0.001

X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
# 一維輸出
y = tf.placeholder(tf.int32, [None])
# 使用最簡單的basicRNNcell
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
#使用dynamic_rnn
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
# 原始輸出
logits = fully_connected(states, n_outputs, activation_fn=None)
# 計算和真實的交叉熵
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
loss = tf.reduce_mean(xentropy)
# 使用AdamOptimizer
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
training_op = optimizer.minimize(loss)
# 計算準確率,只有等于y才是對的,其他都錯
correct = tf.nn.in_top_k(logits, y, 1)
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
init = tf.global_variables_initializer()

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/")
# 轉換到合理的輸入shape
X_test = mnist.test.images.reshape((-1, n_steps, n_inputs))
y_test = mnist.test.labels
# run100遍,每次處理150個輸入
n_epochs = 100
batch_size = 150
# 開始循環
with tf.Session() as sess:
    init.run()
    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            # 讀入數據并reshape
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            X_batch = X_batch.reshape((-1, n_steps, n_inputs))
            # X大寫,y小寫
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
        acc_test = accuracy.eval(feed_dict={X: X_test, y: y_test})
        # 每次打印一下當前信息
        print(epoch, "Train accuracy:", acc_train, "Test accuracy:", acc_test)

以下,只用了150個參數,做了單層。就可以達到非常高的效果,可以看出rnn效果非常不錯

序列預測,前20個狀態作為輸入,則第2個到21個作為輸出,作為訓練集

# 輸入x0-x19
n_steps = 20
# 只預測一個值
n_inputs = 1
# rnn有100個
n_neurons = 100
n_outputs = 1
# none表示min_batch大小這里任意
X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
y = tf.placeholder(tf.float32, [None, n_steps, n_outputs])
cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons, activation=tf.nn.relu)
outputs, states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)

?

如上代碼中,每次輸出的vector都是100維的,加入一個output rejections后,使得每次只輸出1個值

output rejection實現代碼如下

# 設置輸出為上面設定的n_outputs大小
cell = tf.contrib.rnn.OutputProjectionWrapper(
     tf.contrib.rnn.BasicRNNCell(num_units=n_neurons, activation=tf.nn.relu), output_size=n_outputs)

learning_rate = 0.001
loss = tf.reduce_mean(tf.square(outputs - y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
training_op = optimizer.minimize(loss)
init = tf.global_variables_initializer()
# 開始訓練
n_iterations = 10000
batch_size = 50
with tf.Session() as sess:
    init.run()
    for iteration in range(n_iterations):
        X_batch, y_batch = [...] # fetch the next training batch
        sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        if iteration % 100 == 0:
            mse = loss.eval(feed_dict={X: X_batch, y: y_batch})
            print(iteration, "	MSE:", mse)

?2.預測

當一個RNN訓練好后,它就可以生成很多新的東西。RNN的強大的生成能力非常有魅力,用很多曲子去訓練它,它就可以生成新的曲子,用很多文章訓練它,他就可以生成新的文章。如果可以訓練出功能非常強的RNN模型,就有可能代替人的工作。

with tf.Session() as sess:                  
    # 導入訓練好的模型
    saver.restore(sess, "./my_time_series_model") 
    # 生成新的曲線
    sequence = [0.] * n_steps
    for iteration in range(300):
        X_batch = np.array(sequence[-n_steps:]).reshape(1, n_steps, 1)
        y_pred = sess.run(outputs, feed_dict={X: X_batch})
        sequence.append(y_pred[0, -1, 0])

RNN也可以不斷疊加,形成很深的網絡,如下圖所示,每一層輸出都反饋到當前位置的輸入,時間軸展開后,如右邊所示。

n_inputs = 2
n_steps = 5

X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
n_neurons = 100
n_layers = 3 # 做了3層rnn
# 模型不是越復雜越好,越復雜所需數據量越大,否則會有過擬合的風險
# 可以加dropout來控制
layers = [tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
          for layer in range(n_layers)]
multi_layer_cell = tf.contrib.rnn.MultiRNNCell(layers)
outputs, states = tf.nn.dynamic_rnn(multi_layer_cell, X, dtype=tf.float32)
init = tf.global_variables_initializer()
X_batch = np.random.rand(2, n_steps, n_inputs)
with tf.Session() as sess:
    init.run()
    outputs_val, states_val = sess.run([outputs, states], feed_dict={X: X_batch})

五、困難及優化

反向訓練時,對于RNN來說,要橫向往前推,一直往前推到序列開始的地方。當序列非常長時,梯度消失,梯度爆炸都與路徑長度太長有關,前面的權重都基本固定不變,沒有訓練效果。

為了解決這個困難,有了很多更復雜RNN模型的提出

?1.LSTM(Long Short Term Memory)

97年提出,直到深度學習提出,使用LSTM做出具體實事后,才火起來?;蛟S是因為現在有大數據的環境,以及訓練能力很強的硬件這些客觀條件得具備,才能真正發揮LSTM的威力。

它把訓練信息分為長期記憶(c)和短期記憶(h),上面的長期記憶信息,可以穿到很遠,即使序列長到1000,也可以向前傳導。

它分了很多個門(gate),輸出信息趨近于0,門關閉,趨近于1門打開。i是輸入門控制新輸入加多少到長期記憶中,f是forget控制是否受長期記憶的影響,哪些長期記憶被忘掉,o是輸出門控制哪些長期記憶可以輸出并作為短期記憶ht傳遞下去,通過這3個門控制信息的流動。

可以保證長期記憶變換的緩慢,相對穩定,可以對距離比較遠的序列影響,ht和ht-1可以看到距離也比較遠,短期記憶ht-1變化明顯。

?

?

# TensorFlow中LSTM具體實現
n_steps = 28
n_inputs = 28
n_neurons = 150
n_outputs = 10
n_layers = 3

learning_rate = 0.001

X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
y = tf.placeholder(tf.int32, [None])

lstm_cells = [tf.contrib.rnn.BasicLSTMCell(num_units=n_neurons)
              for layer in range(n_layers)]
multi_cell = tf.contrib.rnn.MultiRNNCell(lstm_cells)
outputs, states = tf.nn.dynamic_rnn(multi_cell, X, dtype=tf.float32)
top_layer_h_state = states[-1][1]
logits = tf.layers.dense(top_layer_h_state, n_outputs, name="softmax")
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
loss = tf.reduce_mean(xentropy, name="loss")
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
training_op = optimizer.minimize(loss)
correct = tf.nn.in_top_k(logits, y, 1)
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
    
init = tf.global_variables_initializer()

LSTM還有一點改進Peephole Connection

?lstm_cell = tf.contrib.rnn.LSTMCell(num_units=n_neurons, use_peepholes=True)?

?2. GRU(Gated recurrent unit)

?GRU是對LSTM簡化后的版本,去掉了長短期記憶的區分(都是h),減少了幾個門,2014年提出,從參數上來說較LSTM簡單些。

統一用update gate控制原來的i門和f門。z趨近于0就用ht-1來更新,趨近于1就取當前輸入。

比LSTM還少一個矩陣乘法,實際表現不比LSTM差,也成為現在很多研究者越來越看重的方法。

調用時,直接調用GRU cell即可

?gru_cell = tf.contrib.rnn.GRUCell(num_units=n_neurons)?

?六、RNN在NLP(natural language processing)中的應用

RNN的輸入原本是one-hot的表示,但這樣會使得輸入極其稀疏,不好訓練。于是將高維空間映射到低維(如100維)空間,用這個低維嵌入的輸入做訓練,非常有效。

Word Embeddings

相同含義的詞在低維空間中距離近,含義差的多的離得遠。

# 把50000維數據映射到150維數據空間上
vocabulary_size = 50000
embedding_size = 150
# 做一個全連接
embeddings = tf.Variable(tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))

train_inputs = tf.placeholder(tf.int32, shape=[None]) # from ids
embed = tf.nn.embedding_lookup(embeddings, train_inputs)# to embd

例如下圖所示,把要翻譯的英文句子做輸入,用訓練后的狀態值做輸入,和法語作為訓練集的作為decoder輸入。第一位放一個起始信號<go>,輸出和輸入剛好錯一位,最后一位以一個結束標識<eos>結束。這樣做是為了后繼應用時,翻譯新句子沒有training label,只有英文輸入。把英文輸入放進來后加一個<go>,得到第一個je輸出,把第一個詞放進來得到第二個輸出bois。。最后<eos>翻譯結束。

最后實際應用時如下,輸入<go>開始翻譯。

當前文章:http://www.hfcxdn.com/content/01-12/74128/content_1182892247.html

發布時間:2019-05-27 01:10:59

龜甲冬青哪里有賣? 湖北扶芳藤都在哪里買的? 直徑7公分紅玉蘭多少錢一棵? 八角金盤籽市場什么價格? 櫻花7月份可以種植嗎? 直徑5公分白玉蘭多少錢一棵? 五十厘米高的紫藤苗多少錢一株? 紅楓與雞爪槭是不是一個品種,它們之間有什么區別?

綠化黃刺玫報價哪家最低? 美人蕉小苗什么價格能買到? 福建有種植榆葉梅的基地嗎? 紫藤幼苗哪里有出售? 花卉什么時候移栽最好? 草花春播時間是什么時候? 甘肅適合種植果嶺草嗎? 重瓣矢車菊種子哪家便宜? 浙江適合種植日本黑松嗎?

編輯:道秉

我要說兩句: (0人參與)

發布
捕鱼达人之深海狩猎