tf.keras使用mask_zero = True嵌入,然后跟随GlobalAveragePooling1D生成TypeError

时间:2019-10-15 18:30:09

标签: keras mask embedding tf.keras max-pooling

我正在使用tf.keras在google colab上使用tensorflow v2。我正在尝试使用掩盖嵌入,然后使用全局平均值。这是我的代码:

vocab_size = 1500

inputs = Input(shape=(None,), dtype=tf.int32, name='word_sequence')

x = Embedding(input_dim=vocab_size, output_dim=16, mask_zero=True)(inputs)

outputs = tf.keras.layers.GlobalAveragePooling1D()(x)

model = Model(inputs, outputs)

但是我得到了这个错误:

TypeError:无法将类型的对象转换为Tensor。内容:[-1,无,1]。考虑将元素强制转换为受支持的类型。

如果我提供了显式长度的Input(shape =(10,),.....)序列,则似乎没有错误(尽管我没有使用示例数据对其进行测试)。我想知道为什么您需要指定一个明确的序列长度,我认为当层首次遇到数据时可以在运行时懒惰地完成。

此外,以下作品(摘自“ masking and padding” tf教程):

inputs = tf.keras.Input(shape=(None,), dtype='int32')
x = layers.Embedding(input_dim=5000, output_dim=16, mask_zero=True)(inputs)
outputs = layers.LSTM(32)(x)

model = tf.keras.Model(inputs, outputs)

对于LSTM,似乎对模型的功能性api构造过程中的None输入形状感到满意。

有人可以解释一下GlobalAveragePooling1D有什么不好吗,还是应该起作用,但是我做错了什么?

谢谢。

2 个答案:

答案 0 :(得分:0)

我没有发表评论的声誉,所以这是我想说的:GRU和LSTM似乎都存在相同的问题。当我改用GlobalMaxPooling1D时,问题似乎消失了。我觉得这是由Masking的底层实现引起的问题,但是我对低级Keras API对此一无所知。

答案 1 :(得分:0)

这是因为在input_mask不为None时实现了GlobalAveragePooling1D,因此需要指定时间步长。因此,如果您尝试在Embedding层中删除mask_zero = True,则可以成功构建模型。

查看GlobalAveragePooling1D的源代码,我们可以看到:

  def call(self, inputs, mask=None):
    steps_axis = 1 if self.data_format == 'channels_last' else 2
    if mask is not None:
      mask = math_ops.cast(mask, backend.floatx())
      input_shape = inputs.shape.as_list()
      broadcast_shape = [-1, input_shape[steps_axis], 1]
      mask = array_ops.reshape(mask, broadcast_shape)
      inputs *= mask
      return backend.sum(inputs, axis=steps_axis) / math_ops.reduce_sum(
          mask, axis=steps_axis)
    else:
      return backend.mean(inputs, axis=steps_axis)

因此,如果mask不为None(在您的示例中,mask是由Embedding层生成的mask,因为您设置了mask_zero = True),那么broadcast_shape将为[-1,None,1],并且None会导致错误在reshape(mask,broadcast_shape)中。因此,我认为唯一的解决方案是将时间步长(序列长度)指定为输入形状。