從rnn到lstm,再到seq2seq(一)


rnn的的公式很簡單:

 

對於每個時刻,輸入上一個時刻的隱層s和這個時刻的文本x,然后輸出這個時刻的隱層s。對於輸出的隱層s 做個ws+b就是這個時刻的輸出y。

tf.scan(fn, elems, initializer) # scan operation def fn(st_1, xt): # recurrent function st = f(st_1, xt) return st

rnn的實現:

def step(hprev, x):
    # initializer
    xav_init = tf.contrib.layers.xavier_initializer
    # params
    W = tf.get_variable('W', shape=[state_size, state_size], initializer=xav_init())
    U = tf.get_variable('U', shape=[state_size, state_size], initializer=xav_init())
    b = tf.get_variable('b', shape=[state_size], initializer=tf.constant_initializer(0.))
    # current hidden state
    h = tf.tanh(tf.matmul(hprev, W) + tf.matmul(x,U) + b)
    return h
states = tf.scan(step, 
            tf.transpose(rnn_inputs, [1,0,2]),
            initializer=init_state) 

 

lstm只是網絡結構上個對rnn進行改進,它同時增加一個單元叫做state狀態,每個lstm有個hidden和一個state。

下面圖中h就是隱層,下面圖中的c就是狀態。首先根據這個時刻的輸入x和上個時刻的隱層算出三個門,f(forget),i(input),o(ouput)

激活函數是sigmoid函數,輸出0或者1。算出來的f門是來控制上個狀態多少被忘記。算出來的i門來控制這個時刻狀態的多少被輸入。

本時刻的狀態由這個時刻的輸入x和上個時刻的隱層算出然后用tan函數激活(對應第四行公式)。

本時刻隱層的輸出h是由本時刻的狀態用tan來激活,然后乘以輸出門

 看看lstm的實現:

            def step(prev, x):
                # gather previous internal state and output state
                st_1, ct_1 = tf.unpack(prev)
                ####
                # GATES
                #
                #  input gate
                i = tf.sigmoid(tf.matmul(x,U[0]) + tf.matmul(st_1,W[0]))
                #  forget gate
                f = tf.sigmoid(tf.matmul(x,U[1]) + tf.matmul(st_1,W[1]))
                #  output gate
                o = tf.sigmoid(tf.matmul(x,U[2]) + tf.matmul(st_1,W[2]))
                #  gate weights
                g = tf.tanh(tf.matmul(x,U[3]) + tf.matmul(st_1,W[3]))
                ###
                # new internal cell state
                ct = ct_1*f + g*i
                # output state
                st = tf.tanh(ct)*o
                return tf.pack([st, ct])
            ###
            # here comes the scan operation; wake up!
            #   tf.scan(fn, elems, initializer)
            states = tf.scan(step, 
                    tf.transpose(rnn_inputs, [1,0,2]),
                    initializer=init_state)

 

 

在來看下gru

gru里面沒有state這個東西,它有兩個門,一個是z,遺忘門,一個是r,就是reset門

跟lstm。算出遺忘門,來控制上個時刻的多少隱層被遺忘,另一半(1-z)就是本時刻多少隱層被輸入。

本時刻多少隱層,跟lstm也很相似,只是在上個時刻的h上加了個reset門,就是:根據上個時刻的h加上reset門,和本時刻的輸入x,通過tan來激活

看看gru的實現:

  def step(st_1, x):
                ####
                # GATES
                #
                #  update gate
                z = tf.sigmoid(tf.matmul(x,U[0]) + tf.matmul(st_1,W[0]))
                #  reset gate
                r = tf.sigmoid(tf.matmul(x,U[1]) + tf.matmul(st_1,W[1]))
                #  intermediate
                h = tf.tanh(tf.matmul(x,U[2]) + tf.matmul( (r*st_1),W[2]))
                ###
                # new state
                st = (1-z)*h + (z*st_1)
                return st
            ###
            # here comes the scan operation; wake up!
            #   tf.scan(fn, elems, initializer)
            states = tf.scan(step, 
                    tf.transpose(rnn_inputs, [1,0,2]),
                    initializer=init_state)

 

 

參考文章:

http://colah.github.io/posts/2015-08-Understanding-LSTMs/

http://suriyadeepan.github.io/2017-02-13-unfolding-rnn-2/

https://github.com/suriyadeepan/rnn-from-scratch

http://karpathy.github.io/2015/05/21/rnn-effectiveness/


免責聲明!

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



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