- 我是否编写了自定义代码(而不是使用 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)
我已将解码器的输出投影仪修改为全连接层,而不仅仅是教程代码中的线性投影仪。通过定义以下自定义层类:
自定义层.pyhttps://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]?