深度学习深度学习项目实践集Deep Learning

RNN起名器(二)——RNN基础

2017-02-03  本文已影响299人  Cer_ml
这篇博客介绍RNN基础。

具体关于RNN的细节介绍和实现,推荐wildml的这个系列博客,一共四篇,带你由浅入深学习RNN和Theano实现。补充:看到知乎上有人把这个系列翻译出来了,可以看看

另外,Karpathy(char-rnn的作者)的博客讲了更多关于RNN和语言模型的知识。

这里我简单总结下。

1. RNN

这里说的RNN特指循环神经网络(Recurrent Neural Network),先看下面这张图:

先看左边没有展开的图,若输入x直接到输出o,那就是一个普通的神经元;RNN就是在原来的基础上,增加了一个中间状态s,然后这个中间状态会受到上一个时间点(序列中前一个)中间状态的影响。

按时间展开这个RNN单元,就可以获得右边的图,U,V,W是唯一的。

用数学语言描述上面的图:

下面给出theano实现:

# 1.先定义单个时间序列下的计算规则
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,计算隐藏状态序列s,和输出序列o;thean中的scan相当于for循环。
[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)

预测和损失函数:

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

2. GRU(门限递归单元)

普通的RNN会有梯度消失的问题,即对于较长的输入序列,会出现梯度为0的状况。

于是产生了GRU(门限递归单元)和LSTM(长短项记忆)。

GRU:

Theano实现:

# 获得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(长短项记忆)

继续介绍LSTM:


Tensorflow实现:

参数定义:

# 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]))

计算规则:

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. 一些细节


符号∘代表矩阵的Element-wise product,也称为Hadamard product。

在theano和tensorflow中,*直接表示Element-wise product。

而theano中的.dot和tensorflow中的tf.matmul,表示矩阵乘法。

上一篇下一篇

猜你喜欢

热点阅读