web-dev-qa-db-ja.com

LSTMオートエンコーダー

シーケンスから可能な限り良好なシーケンスを表す固定サイズのベクトルを取得することを目標に、LSTM自動エンコーダーを構築しようとしています。このオートエンコーダーは2つの部分で構成されています。

  • LSTMエンコーダー:シーケンスを取り、出力ベクトル(return_sequences = False
  • LSTMデコーダー:出力ベクトルを取得し、シーケンス(return_sequences = True

したがって、最終的に、エンコーダーはmany to oneLSTMであり、デコーダーはone to manyLSTM。

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

問題:続行する方法、特にLSTMModelに統合する方法と、ベクトルからシーケンスを生成するデコーダー。

kerasバックエンドでtensorflowを使用しています。

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

モデルは自由に設定できます。私がそれを正しく理解していれば、あなたは単にLSTMでモデルを作成する方法を知りたいですか?

LSTMを使用

まあ、最初に、エンコードされたベクトルがどのように見えるかを定義する必要があります。 20要素の配列、1次元ベクトルにしたいとします。したがって、形状(なし、20)。それの大きさはあなた次第であり、理想的なものを知る明確なルールはありません。

また、入力は(1200,10,5)などの3次元でなければなりません。 kerasの概要とエラーメッセージでは、「なし」はバッチサイズを表すため、(なし、10、5)と表示されます。これは、トレーニング/予測するたびに変化する可能性があります。

これを行うには多くの方法がありますが、1つの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レイヤーをアタッチするために、まず入力を3次元配列に変形する必要があります。

あなたがそれを作り直す方法は完全にあなた次第です。 1要素の20ステップ? 20要素の1ステップ? 2要素の10ステップ?知るか?

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

10のステップがもうない場合は、単に「return_sequences」を有効にして、必要な出力を得ることができないことに注意することが重要です。あなたは少し働かなければなりません。 Acually、 "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)   

その後、モデルとコードを統合し、オートエンコーダーをトレーニングします。 3つのモデルはすべて同じ重みを持つため、predictメソッドを使用するだけでエンコーダに結果をもたらすことができます。

encoderPredictions = encoder.predict(data)

シーケンスを生成するためのLSTMについてよく目にするのは、次の要素を予測するようなものです。

シーケンスのいくつかの要素を取得し、次の要素を見つけようとします。そして、あなたは別のセグメントを一歩前進させます。これは、シーケンスの生成に役立つ場合があります。

23
Daniel Möller

オートエンコーダをシーケンスするための簡単なシーケンスは、ここで見つけることができます: https://blog.keras.io/building-autoencoders-in-keras.html

6
user6903745