【问题标题】:Tensorflow LSTM character by character sequence predictionTensorFlow LSTM 逐字符序列预测
【发布时间】:2017-05-28 01:00:06
【问题描述】:

我正在尝试使用 Tensorflow 复制优秀文章 http://karpathy.github.io/2015/05/21/rnn-effectiveness/ 中演示的字符级语言建模。

到目前为止,我的尝试都失败了。我的网络通常在处理 800 个左右字符后输出单个字符。 我相信我从根本上误解了张量流实现 LSTM 的方式,也许是一般的 rnns。我发现文档很难理解。

这是我的代码的精髓:

图表定义

idata = tf.placeholder(tf.int32,[None,1])   #input byte, use value 256 for start and end of file
odata = tf.placeholder(tf.int32,[None,1])    #target output byte, ie, next byte in sequence..
source =  tf.to_float(tf.one_hot(idata,257)) #input byte as 1-hot float
target = tf.to_float(tf.one_hot(odata,257))  #target output as 1-hot float

with tf.variable_scope("lstm01"):
    cell1 = tf.nn.rnn_cell.BasicLSTMCell(257)
    val1, state1 = tf.nn.dynamic_rnn(cell1, source, dtype=tf.float32)

output = val1

损失计算

cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output, target))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)  
output_am = tf.argmax(output,2)
target_am = tf.argmax(target,2)
correct_prediction = tf.equal(output_am, target_am)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

培训

for i in range(0, source_data.size-1, batch_size):
    start = i
    stop = i + batch_size
    i_data = source_data[start:stop].reshape([-1,1])
    o_data = source_data[start+1:stop+1].reshape([-1,1])

    train_step.run(feed_dict={idata: i_data, odata: o_data})

    if i%(report_interval*batch_size) == 0:
        batch_out, fa = sess.run([output_am, accuracy], feed_dict={idata: i_data, odata: o_data, keep_prob: 1.0})

        print("step %d, training accuracy %s"%(i, str(fa)))
        print("i_data sample: %s"%str(squeeze(i_data)))
        print("o_data sample: %s"%str(squeeze(o_data)))
        print("batch sample: %s"%str(squeeze(batch_out)))

输出,使用 1MB Shakespere 文件训练

step 0, training accuracy 0.0
i_data sample: [ 256.   70.  105.  114.  115.  116.   32.   67.  105.  116.]
o_data sample: [  70.  105.  114.  115.  116.   32.   67.  105.  116.  105.]
batch sample: [254  18 151  64  51 199  83 174 151 199]

step 400, training accuracy 0.2
i_data sample: [  32.   98.  101.   32.  100.  111.  110.  101.   58.   32.]
o_data sample: [  98.  101.   32.  100.  111.  110.  101.   58.   32.   97.]
batch sample: [ 32 101  32  32  32  32  10  32 101  32]

step 800, training accuracy 0.0
i_data sample: [ 112.   97.  114.  116.  105.   99.  117.  108.   97.  114.]
o_data sample: [  97.  114.  116.  105.   99.  117.  108.   97.  114.  105.]
batch sample: [101 101 101  32 101 101  32 101 101 101]

step 1200, training accuracy 0.1
i_data sample: [  63.   10.   10.   70.  105.  114.  115.  116.   32.   67.]
o_data sample: [  10.   10.   70.  105.  114.  115.  116.   32.   67.  105.]
batch sample: [ 32  32  32 101  32  32  32  32  32  32]

step 1600, training accuracy 0.2
i_data sample: [  32.  116.  105.  108.  108.   32.  116.  104.  101.   32.]
o_data sample: [ 116.  105.  108.  108.   32.  116.  104.  101.   32.   97.]
batch sample: [32 32 32 32 32 32 32 32 32 32]

这显然是不正确的。

我想我对“批次”和“序列”之间的区别感到困惑,以及 LSTM 的状态是否保留在我所谓的“批次”(即子序列)之间

我得到的印象是我已经使用长度为 1 的“批次”序列对其进行了训练,并且在每个批次之间,状态数据被丢弃。因此,它只是找到最常出现的符号。

谁能证实这一点,或者以其他方式纠正我的错误,并指出我应该如何使用非常长的训练序列进行逐个字符的预测任务?

非常感谢。

【问题讨论】:

    标签: tensorflow sequences lstm


    【解决方案1】:

    所以您的 idata 应该具有以下形状:[batch_size, maximum_sequence_length, 257]。 (如果不是批次中的所有序列都具有相同的长度,则需要根据需要进行填充,并且在计算损失时要小心,这仅在未填充的值上完成。)

    dynamic_rnn 会为您按时间逐步检查您的输入。因此,您只需要循环批处理。

    因为您的 idata 的第二维是 1,所以您的有效序列长度是 1 是对的。

    对于不是基于字符但使用词嵌入的语言模型,请查看this 教程。

    其他说明:

    • 如果您想在 LSTM 中试验不同数量的单元 - 考虑在输出顶部添加一个线性层以将每个输出(对于时间 t 的批处理条目 i)投影到 257,即数字目标的类别。

    • 无需对目标进行 one-hot 编码。看看 sparse_softmax_cross_entropy。

    【讨论】:

    • 我将我的训练数据视为一个非常长的序列。如果我尝试通过网络放置多个兆字节的序列,我预计这会导致内存问题。我是否只是简单地读出状态变量并将其作为 dynamic_rnn 操作的 initial_state 重新输入到图的下一次执行中?
    • 我会回应 danijar 建议使用 static_state_saving_rnn。
    • 我查看了 state_saving_rnn 的 api。它需要一个 state_saver 对象,我不确定如何提供(似乎文档中对状态保护程序的唯一引用是保存到磁盘)。因此,我使用了 user1506145 的解决方案,它本身并不完整,因为您无法将 LSTMStateTuple 传递到提要中。我花了一点时间才弄清楚我必须这样做:for n in range(number_of_layers): init_state[n,0] = state[n].c, init_state[n,1] = state[n].h 将数据从 LSTMStateTuple 复制到原始列表中。
    • 重新插入状态数据似乎也不起作用。当我弄清楚问题是什么时,我会发布另一个问题。
    猜你喜欢
    • 2021-11-03
    • 2018-09-22
    • 2021-04-21
    • 2021-06-13
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    相关资源
    最近更新 更多