tensorflow学习,建立LSTM循环神经网络,教机器作诗,训练篇(27)

第26节讨论了如何将诗集数据转换为数字信息,便于训练 长短期记忆循环神经网络(LSTM RNN)第25节则介绍了 LSTM RNN 在 tensorflow 中常用的函数。本节将在此基础上,建立网络,并训练之。


建立多层 LSTM 循环神经网络

先封装一个神经元,使用dropout防止过拟合。

def GetOneCell(lstm_size, keep_prob):
            lstm = tf.nn.rnn_cell.BasicLSTMCell(lstm_size)
            drop = tf.nn.rnn_cell.DropoutWrapper(lstm, output_keep_prob=keep_prob)
            return drop

封装好GetOneCell方法,就可以很方便的建立多层 LSTM 网络了。

cell = tf.nn.rnn_cell.MultiRNNCell(
                [get_a_cell(lstm_size, keep_prob) for _ in range(num_layers)]
            )

建立好以后,就可以用tf.nn.dynamic_rnn方法展开时间维度了,该方法的说明可以参考第25节

initial_state = cell.zero_state(num_seqs, tf.float32)               #初始状态使用零状态
lstm_outputs, final_state = tf.nn.dynamic_rnn(cell, lstm_inputs, initial_state=initial_state)

得到的lstm_outputs其实是 LSTM 的隐状态层 h,所以还需要一层 softmax 计算概率。建立 softmax 层就相当于一层全连接层,首先需要将lstm_outputs的形状 reshape。这里 reshape 成 [-1, lstm_size] 形状,即只保证有 lstm_size 列,不关心到底多少行。因为建立的是多层 LSTM,所以在 reshape 前,先将第二维合并。

lstm_outputs的第一维是 batch_size 即句子的条数,第二维是 诗句的长度,第三维是 lstm size。

代码如下,建立 softmax 层非常熟,不用细说了。

seq_output = tf.concat(lstm_outputs, 1)
x = tf.reshape(seq_output, [-1, lstm_size])

softmax_w = tf.Variable(tf.truncated_normal([lstm_size, num_classes], stddev=0.1))
softmax_b = tf.Variable(tf.zeros(num_classes))
logits = tf.matmul(x, softmax_w) + softmax_b
proba_prediction = tf.nn.softmax(logits)

建立损失函数 loss

这里仍然是使用tf.nn.softmax_cross_entropy_with_logits方法,该方法的使用前面几节介绍的非常清楚,可以翻回去看看。在计算 loss 前,需要先将参考值做点处理:建立one-hot型标签后,reshape 为 logits 的形状即可。具体代码如下

def build_loss():
       y_one_hot = tf.one_hot(targets, num_classes)
       y_reshaped = tf.reshape(y_one_hot, logits.get_shape())
       lossi = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_reshaped)
       loss = tf.reduce_mean(lossi)

对应的优化器可以如下建立:

def build_optimizer():
        # 使用clipping gradients
        tvars = tf.trainable_variables()
        grads, _ = tf.clip_by_global_norm(tf.gradients(self.loss, tvars), self.grad_clip)
        train_op = tf.train.AdamOptimizer(self.learning_rate)
        self.optimizer = train_op.apply_gradients(zip(grads, tvars))

建立数据输入

网络和损失函数、优化器都建立好了,接下来就可以建立数据输入了。使用placeholder,数据通过 feed 传入。因为打算训练的是诗文的数据,所以需要使用embedding层。

inputs = tf.placeholder(tf.int32, shape=(
        num_seqs, num_steps))
targets = tf.placeholder(tf.int32, shape=(
        num_seqs, num_steps))
keep_prob = tf.placeholder(tf.float32)

    # 对于中文,需要使用embedding层
    # 英文字母没有必要用embedding层
with tf.device("/cpu:0"):
    embedding = tf.get_variable('embedding', [num_classes, embedding_size])
    lstm_inputs = tf.nn.embedding_lookup(embedding, inputs)

训练方法

以上几个模块建立好了以后,定义训练方法就非常简单了。总体过程就是利用第26节建立的数据转换方法,将诗文转换为数字信息,然后再经过embedding层,就可以feed给建立好的网络了。每隔一段训练次数,就保存一次训练结果,防止训练意外中断,又得从头训练,这点之前的有篇博客深有体会。

def train(batch_generator, max_steps, save_path, save_every_n, log_every_n):
    session = tf.Session()
    with session as sess:
        sess.run(tf.global_variables_initializer())
        # Train network
        step = 0
        new_state = sess.run(initial_state)
        for x, y in batch_generator:
            step += 1
            feed = {inputs: x,
                    targets: y,
                    keep_prob: train_keep_prob,
                    initial_state: new_state}
            batch_loss, new_state, _ = sess.run([loss,
                                                 final_state,
                                                 optimizer],
                                                feed_dict=feed)
            if (step % save_every_n == 0):
                self.saver.save(sess, os.path.join(save_path, 'model'), global_step=step)
            if step >= max_steps:
                break
        self.saver.save(sess, os.path.join(save_path, 'model'), global_step=step)

全部代码

代码和诗集数据可以点击下面链接下载,含义本节已经说得比较清楚。

代码

训练网络

执行脚本,进行训练,得到以下结果:

$ python train.py   --use_embedding   --input_file data/poetry.txt   --name poetry   --learning_rate 0.005   --num_steps 26   --num_seqs 32   --max_steps 10000
step: 10/10000...  loss: 6.5859...  0.2540 sec/batch
step: 20/10000...  loss: 6.5014...  0.2491 sec/batch
step: 30/10000...  loss: 6.3253...  0.2469 sec/batch
step: 40/10000...  loss: 6.1925...  0.2984 sec/batch
step: 50/10000...  loss: 5.9969...  0.2483 sec/batch
step: 60/10000...  loss: 5.8543...  0.3229 sec/batch
...

发现 loss 在不停的变小,这是网络能够正常工作的必要条件,本节就到这里。下一节,将利用训练好的网络作诗。

本节主要参考《21个项目玩转深度学习》
阅读更多:   tensorflow
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif