LSTM 自编码器 [英] LSTM Autoencoder

查看:161
本文介绍了LSTM 自编码器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to build a LSTM autoencoder with the goal of getting a fixed sized vector from a sequence, which represents the sequence as good as possible. This autoencoder consists of two parts:

  • LSTM 编码器:获取一个序列并返回一个输出向量(return_sequences = False)
  • LSTM 解码器:获取一个输出向量并返回一个序列(return_sequences = True)
  • LSTM Encoder: Takes a sequence and returns an output vector (return_sequences = False)
  • LSTM Decoder: Takes an output vector and returns a sequence (return_sequences = True)

因此,最终,编码器是一个多对一 LSTM,而解码器是一个一对多 LSTM.

So, in the end, the encoder is a many to one LSTM and the decoder is a one to many LSTM.

图片来源:Andrej Karpathy

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

On a high level the coding looks like this (similar as described 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) 如下所示:

The shape (number of training examples, sequence length, input dimension) of the data array is (1200, 10, 5) and looks like this:

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 以及如何让解码器生成一个来自向量的序列.

Problem: I am not sure how to proceed, especially how to integrate LSTM to Model and how to get the decoder to generate a sequence from a vector.

我正在使用 kerastensorflow 后端.

I am using keras with tensorflow backend.

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

If someone wants to try out, here is my procedure to generate random sequences with moving ones (including padding):

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

推荐答案

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

Models can be any way you want. If I understood it right, you just want to know how to create models with LSTM?

使用 LSTM

好吧,首先,您必须定义编码向量的外观.假设您希望它是一个包含 20 个元素的数组,一个一维向量.所以,形状(无,20).它的大小取决于您,并且没有明确的规则来知道理想的大小.

Well, first, you have to define what your encoded vector looks like. Suppose you want it to be an array of 20 elements, a 1-dimension vector. So, shape (None,20). The size of it is up to you, and there is no clear rule to know the ideal one.

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

And your input must be three-dimensional, such as your (1200,10,5). In keras summaries and error messages, it will be shown as (None,10,5), as "None" represents the batch size, which can vary each time you train/predict.

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

There are many ways to do this, but, suppose you want only one LSTM layer:

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 个元素的数组(但如果需要,您可以堆叠更多层).让我们创建模型:

This is enough for a very very simple encoder resulting in an array with 20 elements (but you can stack more layers if you want). Let's create the model:

encoder = Model(inpE,outE)   

现在,对于解码器,它变得晦涩难懂.您不再有实际的序列,而是一个静态的有意义的向量.您可能仍想使用 LTSM,它们会假设向量是一个序列.

Now, for the decoder, it gets obscure. You don't have an actual sequence anymore, but a static meaningful vector. You may want to use LTSMs still, they will suppose the vector is a sequence.

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

But here, since the input has shape (None,20), you must first reshape it to some 3-dimensional array in order to attach an LSTM layer next.

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

The way you will reshape it is entirely up to you. 20 steps of 1 element? 1 step of 20 elements? 10 steps of 2 elements? Who knows?

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

请务必注意,如果您不再有 10 个步骤,您将无法仅启用return_sequences"并获得您想要的输出.你得工作一点.实际上,没有必要使用return_sequences"甚至使用 LSTM,但您可以这样做.

It's important to notice that if you don't have 10 steps anymore, you won't be able to just enable "return_sequences" and have the output you want. You'll have to work a little. Acually, it's not necessary to use "return_sequences" or even to use LSTMs, but you may do that.

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

Since in my reshape I have 10 timesteps (intentionally), it will be ok to use "return_sequences", because the result will have 10 timesteps (as the initial input)

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

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

You could work in many other ways, such as simply creating a 50 cell LSTM without returning sequences and then reshaping the result:

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

我们的模型是这样的:

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

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

After that, you unite the models with your code and train the autoencoder. All three models will have the same weights, so you can make the encoder bring results just by using its predict method.

encoderPredictions = encoder.predict(data)

<小时>

我经常看到的 LSTM 生成序列类似于预测下一个元素.


What I often see about LSTMs for generating sequences is something like predicting the next element.

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

You take just a few elements of the sequence and try to find the next element. And you take another segment one step forward and so on. This may be helpful in generating sequences.

这篇关于LSTM 自编码器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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