如何在LSTM自动编码器中使用屏蔽层来屏蔽输入/输出? [英] How to use masking layer to mask input/output in LSTM autoencoders?

查看:147
本文介绍了如何在LSTM自动编码器中使用屏蔽层来屏蔽输入/输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to use LSTM autoencoder to do sequence-to-sequence learning with variable lengths of sequences as inputs, using following code:

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的长度,对于不同的输入可能有所不同)序列).有谁知道有没有很好的方法做到这一点?

where inputs are raw sequence data padded with 0s to the same length (timesteps). Using the code above, the output is also of length timesteps, but when we calculate loss function we only want first Ni elements of the output (where Ni is length of input sequence i, which may be different for different sequences). Does anyone know if there is some good way to do that?

谢谢!

推荐答案

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

请参阅以下答案,以简单的方式来分离相等长度的批次: Keras会误解训练数据的形状

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

In this case, all you have to do is to perform the "repeat" operation in another manner, since you don't have the exact length at training time.

因此,您可以使用代替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,我们得到的最后一个值一直重复到最后.因此,您将不得不对目标数据进行奇怪的填充,重复最后一步直到最后.

Option2 (doesn't smell good): use another masking after RepeatVector.

I tried this, and it works, but we don't get 0's at the end, we get the last value repeated until the end. So, you will have to make a weird padding in your target data, repeating the last step until the end.

例如:目标[[[1,2],[5,7]]]必须为[[[1,2],[5,7],[5,7],[5,7] ...]]

Example: target [[[1,2],[5,7]]] will have to be [[[1,2],[5,7],[5,7],[5,7]...]]

我认为,这可能会使您的数据失衡很多....

This may unbalance your data a lot, I think....

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])

这篇关于如何在LSTM自动编码器中使用屏蔽层来屏蔽输入/输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆