RNN起名器(二)——RNN基礎(chǔ)

這篇博客介紹RNN基礎(chǔ)。

具體關(guān)于RNN的細(xì)節(jié)介紹和實(shí)現(xiàn),推薦wildml的這個(gè)系列博客,一共四篇,帶你由淺入深學(xué)習(xí)RNN和Theano實(shí)現(xiàn)。補(bǔ)充:看到知乎上有人把這個(gè)系列翻譯出來了,可以看看

另外,Karpathy(char-rnn的作者)的博客講了更多關(guān)于RNN和語言模型的知識。

這里我簡單總結(jié)下。

1. RNN

這里說的RNN特指循環(huán)神經(jīng)網(wǎng)絡(luò)(Recurrent Neural Network),先看下面這張圖:

簡單介紹下符號:

先看左邊沒有展開的圖,若輸入x直接到輸出o,那就是一個(gè)普通的神經(jīng)元;RNN就是在原來的基礎(chǔ)上,增加了一個(gè)中間狀態(tài)s,然后這個(gè)中間狀態(tài)會(huì)受到上一個(gè)時(shí)間點(diǎn)(序列中前一個(gè))中間狀態(tài)的影響。

按時(shí)間展開這個(gè)RNN單元,就可以獲得右邊的圖,U,V,W是唯一的。

用數(shù)學(xué)語言描述上面的圖:

下面給出theano實(shí)現(xiàn):

# 1.先定義單個(gè)時(shí)間序列下的計(jì)算規(guī)則
def forward_prop_step(x_t, s_t_prev, U, V, W):
    s_t = T.tanh(U[:, x_t] + W.dot(s_t_prev))
    o_t = T.nnet.softmax(V.dot(s_t))
    return [o_t[0], s_t]
# 2.對輸入序列x,計(jì)算隱藏狀態(tài)序列s,和輸出序列o;thean中的scan相當(dāng)于for循環(huán)。
[o, s], updates = theano.scan(
    forward_prop_step,
    sequences=x,
    outputs_info=[None, dict(initial=T.zeros(self.hidden_dim))],
    non_sequences=[U, V, W],
    truncate_gradient=self.bptt_truncate,
    strict=True)

預(yù)測和損失函數(shù):

prediction = T.argmax(o, axis=1)
o_error = T.sum(T.nnet.categorical_crossentropy(o, y))

2. GRU(門限遞歸單元)

普通的RNN會(huì)有梯度消失的問題,即對于較長的輸入序列,會(huì)出現(xiàn)梯度為0的狀況。

于是產(chǎn)生了GRU(門限遞歸單元)和LSTM(長短項(xiàng)記憶)。

GRU:

解釋:

Theano實(shí)現(xiàn):

# 獲得embedding
x_e = E[:, x_t]

# GRU 
z_t = T.nnet.hard_sigmoid(U[0].dot(x_e) + W[0].dot(s_t_prev) + b[0])
r_t = T.nnet.hard_sigmoid(U[1].dot(x_e) + W[1].dot(s_t_prev) + b[1])
h_t = T.tanh(U[2].dot(x_e) + W[2].dot(s_t_prev * r_t) + b[2])
s_t = (T.ones_like(z_t) - z_t) * h_t + z_t * s_t_prev

3. LSTM(長短項(xiàng)記憶)

繼續(xù)介紹LSTM:

解釋:


Tensorflow實(shí)現(xiàn):

參數(shù)定義:

# Parameters:
  # Input gate: input, previous output, and bias.
  ix = tf.Variable(tf.truncated_normal([vocabulary_size, num_nodes], -0.1, 0.1))
  im = tf.Variable(tf.truncated_normal([num_nodes, num_nodes], -0.1, 0.1))
  ib = tf.Variable(tf.zeros([1, num_nodes]))
  # Forget gate: input, previous output, and bias.
  fx = tf.Variable(tf.truncated_normal([vocabulary_size, num_nodes], -0.1, 0.1))
  fm = tf.Variable(tf.truncated_normal([num_nodes, num_nodes], -0.1, 0.1))
  fb = tf.Variable(tf.zeros([1, num_nodes]))
  # Memory cell: input, state and bias.                             
  cx = tf.Variable(tf.truncated_normal([vocabulary_size, num_nodes], -0.1, 0.1))
  cm = tf.Variable(tf.truncated_normal([num_nodes, num_nodes], -0.1, 0.1))
  cb = tf.Variable(tf.zeros([1, num_nodes]))
  # Output gate: input, previous output, and bias.
  ox = tf.Variable(tf.truncated_normal([vocabulary_size, num_nodes], -0.1, 0.1))
  om = tf.Variable(tf.truncated_normal([num_nodes, num_nodes], -0.1, 0.1))
  ob = tf.Variable(tf.zeros([1, num_nodes]))
  # Variables saving state across unrollings.
  saved_output = tf.Variable(tf.zeros([batch_size, num_nodes]), trainable=False)
  saved_state = tf.Variable(tf.zeros([batch_size, num_nodes]), trainable=False)
  # Classifier weights and biases.
  w = tf.Variable(tf.truncated_normal([num_nodes, vocabulary_size], -0.1, 0.1))
  b = tf.Variable(tf.zeros([vocabulary_size]))

計(jì)算規(guī)則:

def lstm_cell(i, o, state):
    """Create a LSTM cell. See e.g.: http://arxiv.org/pdf/1402.1128v1.pdf
    Note that in this formulation, we omit the various connections between the
    previous state and the gates."""
    input_gate = tf.sigmoid(tf.matmul(i, ix) + tf.matmul(o, im) + ib)
    forget_gate = tf.sigmoid(tf.matmul(i, fx) + tf.matmul(o, fm) + fb)
    update = tf.matmul(i, cx) + tf.matmul(o, cm) + cb
    state = forget_gate * state + input_gate * tf.tanh(update)
    output_gate = tf.sigmoid(tf.matmul(i, ox) + tf.matmul(o, om) + ob)
    return output_gate * tf.tanh(state), state

4. 一些細(xì)節(jié)

?
符號°代表矩陣的Element-wise product,也稱為Hadamard product。
?
在theano和tensorflow中,*直接表示Element-wise product。
?
而theano中的.dot和tensorflow中的tf.matmul,表示矩陣乘法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容