首页 文章

LSTM自动编码器

提问于
浏览
27

我正在尝试构建一个LSTM自动编码器,目标是从序列中获取一个固定大小的矢量,这表示序列尽可能好 . 该自动编码器由两部分组成:

  • LSTM 编码器:获取一个序列并返回一个输出向量( return_sequences = False

  • LSTM 解码器:获取输出向量并返回一个序列( return_sequences = True

因此,最后,编码器是 many to one LSTM,解码器是 one to many LSTM .

enter image description here
图片来源:Andrej Karpathy

在高级别上,编码看起来像这样(类似于描述here):

encoder = Model(...)
decoder = Model(...)

autoencoder = Model(encoder.inputs, decoder(encoder(encoder.inputs)))

autoencoder.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

autoencoder.fit(data, data,
          batch_size=100,
          epochs=1500)

data 数组的形状(训练样本数,序列长度,输入维数)是 (1200, 10, 5) ,如下所示:

array([[[1, 0, 0, 0, 0],
        [0, 1, 0, 0, 0],
        [0, 0, 1, 0, 0],
        ..., 
        [0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0]],
        ... ]

Problem: 我不知道如何继续,特别是如何将 LSTM 集成到 Model 以及如何让解码器从矢量生成序列 .

我正在使用 kerastensorflow 后端 .

EDIT: 如果有人想试试,这是我的程序来生成带有移动序列的随机序列(包括填充):

import random
import math

def getNotSoRandomList(x):
    rlen = 8
    rlist = [0 for x in range(rlen)]
    if x <= 7:
        rlist[x] = 1
    return rlist


sequence = [[getNotSoRandomList(x) for x in range(round(random.uniform(0, 10)))] for y in range(5000)]

### Padding afterwards

from keras.preprocessing import sequence as seq

data = seq.pad_sequences(
    sequences = sequence,
    padding='post',
    maxlen=None,
    truncating='post',
    value=0.
)

2 回答

  • 20

    模型可以是您想要的任何方式 . 如果我理解正确,您只想知道如何使用LSTM创建模型?

    Using LSTMs

    嗯,首先,你必须定义你的编码矢量的样子 . 假设您希望它是一个包含20个元素的数组,即1维向量 . 形状(无,20) . 它的大小取决于你,并且没有明确的规则来了解理想的规则 .

    并且您的输入必须是三维的,例如您的(1200,10,5) . 在keras摘要和错误消息中,它将显示为(None,10,5),因为“None”表示批次大小,每次训练/预测时都会有所不同 .

    有很多方法可以做到这一点,但是,假设您只需要一个LSTM层:

    from keras.layers import *
    from keras.models import Model
    
    inpE = Input((10,5)) #here, you don't define the batch size   
    outE = LSTM(units = 20, return_sequences=False, ...optional parameters...)(inpE)
    

    对于一个非常简单的编码器来说,这足以产生一个包含20个元素的数组(但如果需要,可以堆叠更多层) . 让我们创建模型:

    encoder = Model(inpE,outE)
    

    现在,对于解码器来说,它变得模糊不清 . 你不再有实际的序列,而是一个静态有意义的向量 . 您可能仍想使用LTSM,他们会假设矢量是一个序列 .

    但是在这里,由于输入具有形状(无,20),因此必须首先将其重塑为某个三维数组,以便接下来附加LSTM图层 .

    你重塑它的方式完全取决于你 . 20个步骤的1个元素? 1步20元素? 10个步骤的2个元素?谁知道?

    inpD = Input((20,))   
    outD = Reshape((10,2))(inpD) #supposing 10 steps of 2 elements
    

    重要的是要注意,如果你不再有10个步骤,你将无法启用“return_sequences”并获得你想要的输出 . 你必须工作一点 . 非常,没有必要使用“return_sequences”甚至使用LSTM,但你可以这样做 .

    因为在我的重塑中我有10个时间步(有意),所以可以使用“return_sequences”,因为结果将有10个步骤(作为初始输入)

    outD1 = LSTM(5,return_sequences=True,...optional parameters...)(outD)    
    #5 cells because we want a (None,10,5) vector.
    

    您可以通过许多其他方式工作,例如只需创建一个50单元LSTM而无需返回序列,然后重新整形结果:

    alternativeOut = LSTM(50,return_sequences=False,...)(outD)    
    alternativeOut = Reshape((10,5))(alternativeOut)
    

    我们的模型是:

    decoder = Model(inpD,outD1)  
    alternativeDecoder = Model(inpD,alternativeOut)
    

    之后,您将模型与您的代码联合起来并训练自动编码器 . 所有三个模型都具有相同的权重,因此您可以通过使用 predict 方法使编码器带来结果 .

    encoderPredictions = encoder.predict(data)
    

    我经常看到的LSTM用于生成序列就像预测下一个元素一样 .

    您只需要序列中的几个元素并尝试查找下一个元素 . 而你又向前迈出了一步,依此类推 . 这可能有助于生成序列 .

  • 5

    你可以在这里找到一个简单的序列来自动编码:https://blog.keras.io/building-autoencoders-in-keras.html

相关问题