【问题标题】:How to use masking layer to mask input/output in LSTM autoencoders?如何使用屏蔽层来屏蔽 LSTM 自动编码器中的输入/输出?
【发布时间】:2018-03-21 01:39:10
【问题描述】:

我正在尝试使用 LSTM 自动编码器以可变长度的序列作为输入进行序列到序列学习,使用以下代码:

inputs = Input(shape=(None, input_dim))
masked_input = Masking(mask_value=0.0, input_shape=(None,input_dim))(inputs)
encoded = LSTM(latent_dim)(masked_input)

decoded = RepeatVector(timesteps)(encoded)
decoded = LSTM(input_dim, return_sequences=True)(decoded)
sequence_autoencoder = Model(inputs, decoded)
encoder = Model(inputs, encoded)

其中inputs 是用 0 填充到相同长度的原始序列数据 (timesteps)。使用上面的代码,输出的长度也是timesteps,但是当我们计算损失函数时,我们只需要输出的第一个Ni元素(其中Ni是输入序列i的长度,不同的长度可能不同序列)。有谁知道有什么好办法吗?

谢谢!

【问题讨论】:

  • 您是否尝试用零填充输出?
  • @DanielMöller 输出的长度已经是timesteps,如果我用零填充它会更长吗?
  • 对不起,用零填充“目标”。
  • @DanielMöller 是的,这就是我所做的,问题与填充有关。例如,如果一个特定的输入有 5 个元素,当它被送入自动编码器时,它会被填充 5 个零,长度为 10。理想情况下,在计算损失时,我们只需要关心输出的前 5 个元素,但是由于最后 5 个元素的存在(除非它们全为零,这几乎是不可能的),损失会更大。所以我想知道在计算损失时是否可以“屏蔽”输出的最后 5 个元素?
  • 现在我明白了……“RepeatVector”之后的另一个 Masking 怎么样?我会写一个选项...

标签: machine-learning deep-learning keras lstm autoencoder


【解决方案1】:

对于这个 LSTM 自动编码器架构,我假设你理解,由于 LSTM 编码器层的 return_sequences=False,Mask 在重复向量处丢失。

所以另一个选项,而不是像上面那样裁剪,也可以是传播掩码的create custom bottleneck layer

【讨论】:

    【解决方案2】:

    选项 1:如果您接受单独训练批次,则始终可以在不使用填充的情况下进行训练。

    请参阅此答案,了解一种分离等长批次的简单方法:Keras misinterprets training data shape

    在这种情况下,您所要做的就是以另一种方式执行“重复”操作,因为您在训练时没有确切的长度。

    所以,你可以用这个代替RepeatVector

    import keras.backend as K
    
    def repeatFunction(x):
    
        #x[0] is (batch,latent_dim)
        #x[1] is inputs: (batch,length,features)
    
        latent = K.expand_dims(x[0],axis=1) #shape(batch,1,latent_dim)
        inpShapeMaker = K.ones_like(x[1][:,:,:1]) #shape (batch,length,1)
    
        return latent * inpShapeMaker
    
    #instead of RepeatVector:
    Lambda(repeatFunction,output_shape=(None,latent_dim))([encoded,inputs])
    

    Option2(不好闻):在 RepeatVector 之后使用另一个掩码。

    我试过这个,它可以工作,但我们最后没有得到 0,我们得到最后一个值重复直到最后。因此,您将不得不在目标数据中进行奇怪的填充,重复最后一步直到结束。

    示例:目标 [[[1,2],[5,7]]] 必须是 [[[1,2],[5,7],[5,7],[5,7] ...]]

    我认为这可能会使您的数据严重失衡......

    def makePadding(x):
    
        #x[0] is encoded already repeated  
        #x[1] is inputs    
    
        #padding = 1 for actual data in inputs, 0 for 0
        padding =  K.cast( K.not_equal(x[1][:,:,:1],0), dtype=K.floatx())
            #assuming you don't have 0 for non-padded data
    
        #padding repeated for latent_dim
        padding = K.repeat_elements(padding,rep=latent_dim,axis=-1)
    
        return x[0]*padding
    
    inputs = Input(shape=(timesteps, input_dim))
    masked_input = Masking(mask_value=0.0)(inputs)
    encoded = LSTM(latent_dim)(masked_input)
    
    decoded = RepeatVector(timesteps)(encoded)
    decoded = Lambda(makePadding,output_shape=(timesteps,latent_dim))([decoded,inputs])
    decoded = Masking(mask_value=0.0)(decoded)
    
    decoded = LSTM(input_dim, return_sequences=True)(decoded)
    sequence_autoencoder = Model(inputs, decoded)
    encoder = Model(inputs, encoded)
    

    选项 3(最佳):直接从输入中裁剪输出,这也消除了梯度

    def cropOutputs(x):
    
        #x[0] is decoded at the end
        #x[1] is inputs
        #both have the same shape
    
        #padding = 1 for actual data in inputs, 0 for 0
        padding =  K.cast( K.not_equal(x[1],0), dtype=K.floatx())
            #if you have zeros for non-padded data, they will lose their backpropagation
    
        return x[0]*padding
    
    ....
    ....
    
    decoded = LSTM(input_dim, return_sequences=True)(decoded)
    decoded = Lambda(cropOutputs,output_shape=(timesteps,input_dim))([decoded,inputs])
    

    【讨论】:

    • 但也许真正最好的方法是将选项 2 和 3 结合起来(当你有中间掩码时,你可以节省处理时间,并在最后消除会(?)影响你的损失函数的无意义的重复值) .
    • 一个我现在不会尝试的测试是:创建一个带有掩码的模型,看看重复的输出是否参与反向传播。
    • 后端函数通常使用 theano 或 tensorflow 函数进行 1 到 1 的映射。他们在这里:github.com/fchollet/keras/tree/master/keras/backend --- 我不知道反向传播是如何工作的,但我认为 Keras 将这一切留给 tensorflow/theano 去做。
    • 我一直认为equal/not_equal的结果是常量。它们不会反向传播,但它们不会改变它们修改的张量的反向传播,当然,除非它们为 0。到目前为止,我的尝试一直在正常工作。
    • 我的意思是潜在的暗淡。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    相关资源
    最近更新 更多