如何使用LSTM autonecoder正确忽略多特征序列中解码时的填充或缺失时间步长



我正试图通过使用AUTOENCODER进行重建来学习文本序列(多个特征(3((的潜在表示。由于一些序列比最大焊盘长度或我正在考虑的时间步长(seq_length=15(短,我不确定重建是否会学会忽略时间步长来计算损失或精度。

我遵循了这个答案中的建议来裁剪输出,但我的损失很小,也有几个准确性。

input1 = keras.Input(shape=(seq_length,),name='input_1')
input2 = keras.Input(shape=(seq_length,),name='input_2')
input3 = keras.Input(shape=(seq_length,),name='input_3')
input1_emb = layers.Embedding(70,32,input_length=seq_length,mask_zero=True)(input1)
input2_emb = layers.Embedding(462,192,input_length=seq_length,mask_zero=True)(input2)
input3_emb = layers.Embedding(84,36,input_length=seq_length,mask_zero=True)(input3)
merged = layers.Concatenate()([input1_emb, input2_emb,input3_emb])
activ_func = 'tanh'
encoded = layers.LSTM(120,activation=activ_func,input_shape=(seq_length,),return_sequences=True)(merged) #
encoded = layers.LSTM(60,activation=activ_func,return_sequences=True)(encoded)
encoded = layers.LSTM(15,activation=activ_func)(encoded)
# Decoder reconstruct inputs
decoded1 = layers.RepeatVector(seq_length)(encoded)
decoded1 = layers.LSTM(60, activation= activ_func , return_sequences=True)(decoded1)
decoded1 = layers.LSTM(120, activation= activ_func , return_sequences=True,name='decoder1_last')(decoded1)

解码器一的输出形状为(None,15120(。

input_copy_1 = layers.TimeDistributed(layers.Dense(70, activation='softmax'))(decoded1)
input_copy_2 = layers.TimeDistributed(layers.Dense(462, activation='softmax'))(decoded1)
input_copy_3 = layers.TimeDistributed(layers.Dense(84, activation='softmax'))(decoded1)

对于每个输出,我都试图按照这个答案的建议裁剪O填充的时间步长。padding具有0,其中实际输入丢失(由于填充而为零(,而1否则为

@tf.function
def cropOutputs(x):
#x[0] is softmax of respective feature (time distributed) on top of decoder
#x[1] is the actual input feature
padding =  tf.cast( tf.not_equal(x[1][1],0), dtype=tf.keras.backend.floatx())
print(padding)
return x[0]*tf.tile(tf.expand_dims(padding, axis=-1),tf.constant([1,x[0].shape[2]], tf.int32))

将裁剪函数应用于所有三个输出。

input_copy_1 = layers.Lambda(cropOutputs, name='input_copy_1', output_shape=(None, 15, 70))([input_copy_1,input1])
input_copy_2 = layers.Lambda(cropOutputs, name='input_copy_2', output_shape=(None, 15, 462))([input_copy_2,input2])
input_copy_3 = layers.Lambda(cropOutputs, name='input_copy_3', output_shape=(None, 15, 84))([input_copy_3,input3])

我的逻辑是裁剪每个特征的时间步长(序列的所有3个特征都有相同的长度,这意味着它们一起错过了时间步长(。但对于时间步长,它们已根据其特征大小(70462,84(应用softmax,因此我必须通过在掩码padding的帮助下制作等于该特征大小的0或1的多维掩码阵列来将时间步长清零,并使用多维掩码阵列乘以相应的softmax表示。

我不确定我做得对不对,因为我有这些输入的Nan损失,以及我与此任务共同学习的其他精度(只有在这种裁剪情况下才会发生(。

如果这对某人有帮助,我最终会直接从丢失中裁剪填充条目(从这些答案中获取一些keras代码指针(。

@tf.function
def masked_cc_loss(y_true, y_pred):
mask = tf.keras.backend.all(tf.equal(y_true, masked_val_hotencoded), axis=-1)
mask = 1 - tf.cast(mask, tf.keras.backend.floatx())    

loss = tf.keras.losses.CategoricalCrossentropy()(y_true, y_pred) * mask 

return tf.keras.backend.sum(loss) / tf.keras.backend.sum(mask) #  averaging by the number of unmasked entries

最新更新