1
  • 我是否编写了自定义代码(而不是使用 TensorFlow 中提供的股票示例脚本):是的。基于 NMT 教程,我正在为自己的任务编写自定义代码。
  • 操作系统平台和发行版(例如,Linux Ubuntu 16.04):Linux Ubuntu 14.04 LTS
  • TensorFlow 安装自(源代码或二进制文件):Source
  • TensorFlow 版本(使用下面的命令):1.5
  • Python版本:3.6.3
  • Bazel 版本(如果从源代码编译):0.9.0
  • GCC/编译器版本(如果从源代码编译):5.4.1
  • CUDA/cuDNN 版本:CUDA 8.0、cuDNN 6
  • GPU型号和内存:1080 Ti
  • 重现的确切命令:将通过这篇文章进行解释。

我正在编写基于 NMT 教程代码的 Seq2Seq 代码。(https://github.com/tensorflow/nmt

我已将解码器的输出投影仪修改为全连接层,而不仅仅是教程代码中的线性投影仪。通过定义以下自定义层类:

自定义层.py

https://github.com/kami93/ntptest/blob/master/customlayer.py

然后像这样初始化自定义层:

with tf.variable_scope("decoder/output_layer"):
  output_layer = customlayer.FCLayers(
    [256]*2 + [757],
    activation = tf.nn.relu,
    is_decoder_output=True,
    residual=True,
    kernel_initializer=initializer,
    trainable=True)

然后像这样把层作为 BeamSearchDecoder 的 output_layer

my_decoder = tf.contrib.seq2seq.BeamSearchDecoder(
          cell=cell,
          embedding=embedding_decoder,
          start_tokens=start_tokens,
          end_token=end_token,
          initial_state=decoder_initial_state,
          beam_width=beam_width,
          output_layer=output_layer)

最后像这样得到输出sample_id

outputs, final_context_state, _ = tf.contrib.seq2seq.dynamic_decode(
        my_decoder,
        maximum_iterations=maximum_iterations,
        output_time_major=time_major,
        swap_memory=True,
        scope=decoder_scope)
sample_id = outputs.predicted_ids

问题就出现在这里。

因为我的自定义层的最后一个输出维度是“757”,所以我希望 sample_id 应该是自定义层输出的 argmax id 的索引,它应该在 [0,756] 之间。

但是,返回的实际 sample_id 介于 [1,757] 之间(即返回“我的预期 sample_id + 1”)。

在https://github.com/tensorflow/tensorflow/blob/r1.5/tensorflow/contrib/seq2seq/python/ops/beam_search_decoder.py检查 tf.contrib.seq2seq.BeamSearchDecoder 的实际代码 ...是在“line 510”和“line 652”之间的行上执行“_beam_search_step”,

在第 545 行,vacab_size 被收集为 757。

vocab_size = logits.shape[-1].value or array_ops.shape(logits)[-1]

在第 577 行,在所有嵌套的“K*757”假设中确定具有最高 K(Beam width) softmax 概率的索引。

next_beam_scores, word_indices = nn_ops.top_k(scores_flat, k=next_beam_size)

在第 595 行,通过模运算计算实际指数。

 raw_next_word_ids = math_ops.mod(word_indices, vocab_size,
                               name="next_beam_word_ids")
 next_word_ids = math_ops.to_int32(raw_next_word_ids)

结果,我认为 [1,757] 之间的索引完全没有必要作为 sample_id 返回。至少由于 757 的模运算严格返回 [0,756] 之间的值,因此我认为永远不应该返回 757 的 sample_id。但我实际上得到了它。

有人可以建议为什么我得到[1,757]的样本ID,而不是[0,756]?

4

0 回答 0