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

查看:34
本文介绍了如何使用屏蔽层屏蔽 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元素(其中Nicode>是输入序列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 misinterprets training data shape

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

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:

So, instead of RepeatVector, you can use this:

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

选项 2(味道不好):在 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天全站免登陆