LSTM 自动编码器

新手上路,请多包涵

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

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

所以,最后,编码器是 多对一的 LSTM,解码器是 一对多 的 LSTM。

在此处输入图像描述 图片来源: Andrej Karpathy

在高层次上,编码看起来像这样(类似于 此处 描述的):

 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]],
        ... ]

问题: 我不确定如何进行,尤其是如何将 LSTM 集成到 Model 以及如何让解码器从向量生成序列。

我正在使用 kerastensorflow 后端。

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

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

原文由 ScientiaEtVeritas 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 930
2 个回答

模型可以是您想要的任何方式。如果我没理解错的话,你只是想知道如何使用 LSTM 创建模型?

使用 LSTM

好吧,首先,您必须定义编码后的矢量的外观。假设您希望它是一个包含 20 个元素的数组,一个一维向量。所以,形状(无,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,它们会假设向量是一个序列。

但在这里,由于输入的形状为 (None,20),您必须首先将其重新整形为某个 3 维数组,以便接下来附加 LSTM 层。

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

 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 类似于预测下一个元素。

您只取序列中的几个元素并尝试找到下一个元素。然后您将另一部分向前迈出一步,依此类推。这可能有助于生成序列。

原文由 Daniel Möller 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以在此处找到一个简单的序列到序列自动编码器: https ://blog.keras.io/building-autoencoders-in-keras.html

原文由 user6903745 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏