Keras 双向 LSTM Seq2Seq

11

我正在尝试修改keras的lstm_seq2seq.py示例,将其修改为双向LSTM模型。

https://github.com/keras-team/keras/blob/master/examples/lstm_seq2seq.py

我尝试了不同的方法:

  • 第一种方法是直接将Bidirectional包装器应用于LSTM层:

    encoder_inputs = Input(shape=(None, num_encoder_tokens))
    encoder = Bidirectional(LSTM(latent_dim, return_state=True))
    

但我收到了这个错误信息:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-76-a80f8554ab09> in <module>()
     75 encoder = Bidirectional(LSTM(latent_dim, return_state=True))
     76 
---> 77 encoder_outputs, state_h, state_c = encoder(encoder_inputs)
     78 # We discard `encoder_outputs` and only keep the states.
     79 encoder_states = [state_h, state_c]

/home/tristanbf/.virtualenvs/pydev3/lib/python3.5/site-packages/keras/engine/topology.py in __call__(self, inputs, **kwargs)
    601 
    602             # Actually call the layer, collecting output(s), mask(s), and shape(s).
--> 603             output = self.call(inputs, **kwargs)
    604             output_mask = self.compute_mask(inputs, previous_mask)
    605 

/home/tristanbf/.virtualenvs/pydev3/lib/python3.5/site-packages/keras/layers/wrappers.py in call(self, inputs, training, mask)
    293             y_rev = K.reverse(y_rev, 1)
    294         if self.merge_mode == 'concat':
--> 295             output = K.concatenate([y, y_rev])
    296         elif self.merge_mode == 'sum':
    297             output = y + y_rev

/home/tristanbf/.virtualenvs/pydev3/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py in concatenate(tensors, axis)
   1757     """
   1758     if axis < 0:
-> 1759         rank = ndim(tensors[0])
   1760         if rank:
   1761             axis %= rank

/home/tristanbf/.virtualenvs/pydev3/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py in ndim(x)
    597     ```
    598     """
--> 599     dims = x.get_shape()._dims
    600     if dims is not None:
    601         return len(dims)

AttributeError: 'list' object has no attribute 'get_shape'
encoder_input_data = np.empty(len(input_texts), dtype=object)
decoder_input_data = np.empty(len(input_texts), dtype=object)
decoder_target_data = np.empty(len(input_texts), dtype=object)

for i, (input_text, target_text) in enumerate(zip(input_texts, target_texts)):
    encoder_input_data[i] = [input_token_index[char] for char in input_text]
    tseq = [target_token_index[char] for char in target_text]
    decoder_input_data[i] = tseq
    decoder_output_data[i] = tseq[1:]

encoder_input_data = sequence.pad_sequences(encoder_input_data, maxlen=max_encoder_seq_length)
decoder_input_data = sequence.pad_sequences(decoder_input_data, maxlen=max_decoder_seq_length)
decoder_target_data = sequence.pad_sequences(decoder_target_data, maxlen=max_decoder_seq_length)

但我收到了相同的错误信息:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-75-474b2515be72> in <module>()
     73 encoder = Bidirectional(LSTM(latent_dim, return_state=True))
     74 
---> 75 encoder_outputs, state_h, state_c = encoder(encoder_inputs)
     76 # We discard `encoder_outputs` and only keep the states.
     77 encoder_states = [state_h, state_c]

/home/tristanbf/.virtualenvs/pydev3/lib/python3.5/site-packages/keras/engine/topology.py in __call__(self, inputs, **kwargs)
    601 
    602             # Actually call the layer, collecting output(s), mask(s), and shape(s).
--> 603             output = self.call(inputs, **kwargs)
    604             output_mask = self.compute_mask(inputs, previous_mask)
    605 

/home/tristanbf/.virtualenvs/pydev3/lib/python3.5/site-packages/keras/layers/wrappers.py in call(self, inputs, training, mask)
    293             y_rev = K.reverse(y_rev, 1)
    294         if self.merge_mode == 'concat':
--> 295             output = K.concatenate([y, y_rev])
    296         elif self.merge_mode == 'sum':
    297             output = y + y_rev

/home/tristanbf/.virtualenvs/pydev3/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py in concatenate(tensors, axis)
   1757     """
   1758     if axis < 0:
-> 1759         rank = ndim(tensors[0])
   1760         if rank:
   1761             axis %= rank

/home/tristanbf/.virtualenvs/pydev3/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py in ndim(x)
    597     ```
    598     """
--> 599     dims = x.get_shape()._dims
    600     if dims is not None:
    601         return len(dims)

AttributeError: 'list' object has no attribute 'get_shape'

需要帮忙吗?谢谢

( 代码: https://gist.github.com/anonymous/c0fd6541ab4fc9c2c1e0b86175fb65c7 )


我在Keras的Github上找到了一个看起来相似的未解决问题:https://github.com/keras-team/keras/issues/8823 - JJ E. D.
2个回答

23
您所看到的错误是由于 Bidirectional 包装器未正确处理状态张量引起的。我已在 此 PR 中进行了修复,并且它已经在最新的 2.1.3 发布版本中实现。因此,如果您将 Keras 升级到最新版本,则问题中的代码应该可以正常工作。
请注意,从 Bidirectional(LSTM(..., return_state=True)) 返回的值是一个包含以下内容的列表:
  1. 层输出
  2. 向前层的状态 (h, c)
  3. 向后层的状态 (h, c)
因此,在传递给解码器之前(通常是单向的),您可能需要合并状态张量。例如,如果您选择连接状态,则:
encoder_inputs = Input(shape=(None, num_encoder_tokens))
encoder = Bidirectional(LSTM(latent_dim, return_state=True))
encoder_outputs, forward_h, forward_c, backward_h, backward_c = encoder(encoder_inputs)

state_h = Concatenate()([forward_h, backward_h])
state_c = Concatenate()([forward_c, backward_c])
encoder_states = [state_h, state_c]

decoder_inputs = Input(shape=(None, num_decoder_tokens))
decoder_lstm = LSTM(latent_dim * 2, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs, initial_state=encoder_states)

感谢您的修复/PR! - hyperspasm

0

如果问题与数据准备过程有关,则在概念上类似于此 one,其中一个简单的列表通常没有由Numpy添加的形状属性。

此外,您应该将输入馈送到LSTM编码器或仅将input_shape值设置为LSTM层。在馈送双向层时,始终在LSTM层中使用return_sequences=True。查看此 thread 以了解如何正确使用它们,然后查看我为NLP项目编写的一些代码行(我也使用了Bidirectional层)my GitHub


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接