尝试对带有掩码输入的 LSTM Seq2Seq 执行推理时的 CUDNN_STATUS_BAD_PARAM

Posted

技术标签:

【中文标题】尝试对带有掩码输入的 LSTM Seq2Seq 执行推理时的 CUDNN_STATUS_BAD_PARAM【英文标题】:CUDNN_STATUS_BAD_PARAM when trying to perform inference on a LSTM Seq2Seq with masked inputs 【发布时间】:2020-03-12 17:00:47 【问题描述】:

我在 tensorflow 2.0 上使用 keras 层来构建一个简单的基于 LSTM 的 Seq2Seq 模型用于文本生成

版本我正在使用:Python 3.6.9、Tensorflow 2.0.0、CUDA 10.0、CUDNN 7.6.1、Nvidia 驱动程序版本 410.78。

我知道criteria needed by TF to delegate to CUDNNLstm when a GPU is present(我确实有一个 GPU,我的模型/数据满足所有这些条件)。

训练进行得很顺利(带有警告信息,请参阅本文末尾),我可以验证正在使用 CUDNNLstm。

但是,当我尝试在推理时调用encoder_model.predict(input_sequence)时,我收到以下错误消息

UnknownError:  [_Derived_]  CUDNN_STATUS_BAD_PARAM
in tensorflow/stream_executor/cuda/cuda_dnn.cc(1424): 'cudnnSetRNNDataDescriptor( data_desc.get(), data_type, layout, max_seq_length, batch_size, data_size, seq_lengths_array, (void*)&padding_fill)'
     [[node cond/then/_0/CudnnRNNV3]]
     [[lstm/StatefulPartitionedCall]] [Op:__inference_keras_scratch_graph_91878]

Function call stack:
keras_scratch_graph -> keras_scratch_graph -> keras_scratch_graph

这是训练代码:(source_sequencestarget_sequences 都是右填充序列,嵌入矩阵是预训练的 Glove 嵌入)

# Define an input sequence and process it.
encoder_inputs = tf.keras.layers.Input(shape=(24,))
encoder_embedding_layer = tf.keras.layers.Embedding(
  VOCABULARY_SIZE_1,
  EMBEDDING_DIMS,
  embeddings_initializer=initializers.Constant(encoder_embedding_matrix),
  mask_zero=True)
encoder_embedding = encoder_embedding_layer(encoder_inputs)

_, state_h, state_c = tf.keras.layers.LSTM(
  EMBEDDING_DIMS,
  implementation=1,
  return_state=True)(encoder_embedding)

encoder_states = [state_h, state_c]

decoder_inputs = tf.keras.layers.Input(shape=(24,))
decoder_embedding_layer = tf.keras.layers.Embedding(
  VOCABULARY_SIZE_2,
  EMBEDDING_DIMS,
  embeddings_initializer=initializers.Constant(decoder_embedding_matrix),
  mask_zero=True)
decoder_embedding = decoder_embedding_layer(decoder_inputs)

decoder_lstm = tf.keras.layers.LSTM(
    EMBEDDING_DIMS, 
    return_sequences=True, 
    return_state=True,
    implementation=1)

decoder_outputs, _, _ = decoder_lstm(decoder_embedding, initial_state=encoder_states)

decoder_dense = tf.keras.layers.Dense(VOCABULARY_SIZE_TITLE, activation='softmax')

output = decoder_dense(decoder_outputs)

model = tf.keras.models.Model([encoder_inputs, decoder_inputs], output)

model.compile(optimizer='rmsprop', loss='sparse_categorical_crossentropy')
model.summary()

model.fit([source_sequences, target_sequences], decoder_target_data,
    batch_size=32,
    epochs=10,
    validation_split=0.0,
    verbose=2)

这些是推理模型

encoder_model = tf.keras.models.Model(encoder_inputs, encoder_states)

decoder_state_input_h = tf.keras.layers.Input(shape=(input_dimension ,))
decoder_state_input_c = tf.keras.layers.Input(shape=(input_dimension ,))

decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]

decoder_outputs, state_h, state_c = decoder_lstm_layer(
        decoder_embedding_layer , initial_state=decoder_states_inputs)

decoder_states = [state_h, state_c]

decoder_outputs = output_layer(decoder_outputs)
decoder_model = tf.keras.models.Model(
        [decoder_inputs] + decoder_states_inputs,
        [decoder_outputs] + decoder_states)

当我在 encoder_model 上调用 predict() 时,我得到 CUDNN_STATUS_BAD_PARAM

推理代码(触发错误的地方)

# build the initial state with a right-padded input sequence
#### CUDNN_STATUS_BAD_PARAM is TRIGGERED ON THIS LINE!!! ######## <<<<<<<<<
state = encoder_model.predict(masked_input_sequence)

empty_target_sequence = np.zeros((1,1))
# this signals the Start of sequence
empty_target_sequence[0,0] = titles_word_index[sos_token]

decoder_outputs, h, c = decoder_model.predict([empty_target_sequence] + state)

我尝试过的事情

显式创建掩码 (encoder_embedding_layer.compute_mask()) 并在每次调用 LSTM 层时将它们作为参数添加,例如:

encoder_embedding = encoder_embedding_layer(encoder_inputs)

encoder_mask = encoder_embedding_layer.compute_mask(encoder_inputs)

_, state_h, state_c = tf.keras.layers.LSTM(
  EMBEDDING_DIMS,
  return_state=True)(encoder_embedding,mask=encoder_mask)

不要对嵌入层使用初始化器来查看问题是否存在


PS: 强制在 CPU 上进行训练可以消除错误,但我需要在 GPU 上进行训练,否则需要很长时间才能完成。

P.S.:这似乎与我遇到的错误完全相同:Masking LSTM: OP_REQUIRES failed at cudnn_rnn_ops.cc:1498 : Unknown: CUDNN_STATUS_BAD_PARAM

PS:当我在modelencoder_modeldecoder_model 上调用方法supports_masking 时,由于某种原因,它们都返回False

PS: 就像我说的,训练完成时没有(明显的)错误,但如果我在命令行上查看 Jupyter 输出日志,我可以看到以下 警告消息培训

2019-11-16 19:48:20.144265: W 
tensorflow/core/grappler/optimizers/implementation_selector.cc:310] Skipping optimization due to error while loading function libraries: 
Invalid argument: Functions '__inference___backward_cudnn_lstm_with_fallback_47598_49057' and 
'__inference___backward_cudnn_lstm_with_fallback_47598_49057_specialized_for_StatefulPartitionedCall_1_at___inference_distributed_function_52868'
 both implement 'lstm_d41d5ccb-14be-4a74-b5e8-cc4f63c5bb02' but their signatures do not match.

【问题讨论】:

所以你的输入层的形状是(None, None)(当你添加批量维度时)。你能解释这是为什么吗?你没有办法定义时间步数吗? 你能提供一些样本数据来测试模型吗? 至于最后一个 P.S. (跳过优化):似乎可以忽略此警告消息,如下所述:github.com/tensorflow/tensorflow/issues/… @thushv89 抱歉,我现在设置了时间步长 【参考方案1】:

你应该使用 cudnn7.4 引用这个web

【讨论】:

以上是关于尝试对带有掩码输入的 LSTM Seq2Seq 执行推理时的 CUDNN_STATUS_BAD_PARAM的主要内容,如果未能解决你的问题,请参考以下文章

多图+公式全面解析RNN,LSTM,Seq2Seq,Attention注意力机制

带有用于可变长度输入的掩蔽层的 Keras lstm

如何在 PyTorch 中正确实现 Seq2Seq LSTM 的填充?

Seq2seq LSTM 无法生成合理的摘要

从rnn到lstm,再到seq2seq

对注意力机制(Attention)的一些理解附上Bi-LSTM和seq2seq加上注意力机制的代码