Keras LSTMと1D時系列


10

私はKerasの使用方法を学んでおり、CholletのDeep Learning for Pythonの例を使用して、ラベル付けされたデータセットで妥当な成功を収めました。データセットは、3つの潜在的なクラスを含む長さ3125の〜1000時系列です。

予測率が約70%になる基本的な高密度レイヤーを超えて、LSTMレイヤーとRNNレイヤーについて説明します。

すべての例では、各時系列に複数の機能を持つデータセットを使用しているようであり、結果としてデータを実装する方法を見つけるのに苦労しています。

たとえば、1000x3125の時系列がある場合、それをSimpleRNNやLSTMレイヤーなどにフィードするにはどうすればよいですか?これらのレイヤーの機能に関する基本的な知識が不足していますか?

現在のコード:

import pandas as pd
import numpy as np
import os
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM, Dropout, SimpleRNN, Embedding, Reshape
from keras.utils import to_categorical
from keras import regularizers
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

def readData():
    # Get labels from the labels.txt file
    labels = pd.read_csv('labels.txt', header = None)
    labels = labels.values
    labels = labels-1
    print('One Hot Encoding Data...')
    labels = to_categorical(labels)

    data = pd.read_csv('ts.txt', header = None)

    return data, labels

print('Reading data...')
data, labels = readData()

print('Splitting Data')
data_train, data_test, labels_train, labels_test = train_test_split(data, labels)

print('Building Model...')
#Create model
model = Sequential()
## LSTM / RNN goes here ##
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

print('Training NN...')
history = model.fit(data_train, labels_train, epochs=1000, batch_size=50,
    validation_split=0.25,verbose=2)

results = model.evaluate(data_test, labels_test)

predictions = model.predict(data_test)

print(predictions[0].shape)
print(np.sum(predictions[0]))
print(np.argmax(predictions[0]))

print(results)

acc = history.history['acc']
val_acc = history.history['val_acc']
epochs = range(1, len(acc) + 1)

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and Validation Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

回答:


10

LSTM層には、異なる形状のデータが必要です。

あなたの説明から、開始データセットは3125行と1000列であると理解しています。各行は1つのタイムステップです。ターゲット変数は、3125行と1列を持つ必要があります。各値は、3つの可能な値のいずれかになります。だから、あなたは分類問題をやっているように聞こえます。これをコードで確認するには、次のようにします。

>>> X.shape
(3125, 1000)

>>> y.shape
(1000,)

LSTMクラスでは、各単一サンプルが時間の「ブロック」で構成される必要があります。100タイムステップのブロックが欲しいとしましょう。これはX[0:100]、のターゲット変数に対応する単一の入力サンプルであることを意味しy[100]ます。これは、ウィンドウサイズ(タイムステップの数またはラグの数)が100に等しいことを意味します。前述のように、サンプルは3125なので、N = 3125です。最初のブロックを形成するには、残念ながら、の最初の100サンプルを破棄するy必要がありますX[0]。利用可能なデータから100のブロック全体を形成することはできないためです(結局、の前にデータポイントが必要になります)。

これらすべてを踏まえると、LSTMでは(N - window_size, window_size, num_features)(3125 - 100, 100, 1000)==に変換されるシェイプのバッチを提供する必要があります(3025, 100, 1000)

これらの時間ブロックを作成するのは少し面倒ですが、一度良い関数を作成してから保存してください:)

やるべき多くの仕事があり、おそらく上記の私の説明の深さの実施例でよりを見てここに ...かの読んだLSTMのドキュメントを(、まだ良いか、ソースコードを!)。

最終的なモデルは(コードに基づいて)十分に単純になります。

#Create model
model = Sequential()
model.add(LSTM(units=32, activation='relu',
               input_shape=(100, 1000))    # the batch size is neglected!
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam',
              metrics=['accuracy'])

モデルの入力形状に関するドキュメントをご覧Sequentialください。基本的には、内のバッチ数を指定する必要がないと述べていますinput_shapebatch_size=50固定数にする必要がある場合などは、で実行できます。

input_shape引数がのドキュメントにないことは知っていますLSTMが、クラス自体はから継承されRNN、クラスはから継承されLayerます。したがって、提供された情報を使用できます。

最後のヒント:複数のLSTMレイヤーを追加する(それらを「スタックする」)場合は、最後の を除くすべてLSTM、つまりに引数を1つ追加する必要がありますreturn_sequences=True


包括的な返信デクスター(!)ありがとうございます。バッチサイズに関するコメントについて、model.fit引数で指定されたbatch_sizeは、独自のカスタムバッチを作成する場合とは異なるハイパーパラメーターですか?data = np.reshape(data、(1000,1,3125))を使用して、1000x3125マトリックスから3Dマトリックスにデータを再形成することで、コードを少なくとも実行できるようにしました。これにより、input_shape(1,3125)を指定してLSTMを実行できますが、何をしているのか本当にわかりません。繰り返しますが、返信ありがとうございます。私はあなたが提供したリンクを見て、あなたの答えをもう少し調べます。
user1147964 2018

どういたしまして!はい、batch_sizeわかりました。モデルを定義するときに省略した場合、それは内の同じ引数から取得されますmodel.fit()。getを再形成する必要が(3025, 100, 1000)あります。つまり、100(行)タイムステップと1000(列)変数のそれぞれが3025バッチになるということです。np.reshape残念ながら、これを使用するとうまくいきません(エラーが発生します)。これは、データが重複するためです。最終的な形状には入力よりも多くのデータがあります。> 3125x1000 3025x100x1000は - np.reshapeではない、それは曖昧だとしてそのように行います。データセットを単純にループすることをお勧めします。1ループ= 1サンプルです。
n1k31t4 2018

私はここで少し混乱していると思いますが、誤ってすでにバッチ処理を実行した可能性があります。ここでは特定の値を使用します。6.25 kHzで3種類の異なる測定値を約3分間サンプリングした結果、3つの時系列の長さ1093750が得られました。これにより、3x1093750マトリックスが生成されます。次に、各TSを0.5秒刻みに分割し、1050x3125のマトリックスを作成しました。これを技術的に3x350x3125の寸法の3Dマトリックスに再構成できます。これにより、350、0.5秒の「バッチ」が得られます。あなたの再形成はより多くの価値を生み出すようです再び回答をありがとうございます。申し訳ありません
user1147964

付け加えると、あなたが投稿した最初のリンクを読むと、私は物事を正しく形作っていると思います。明らかなものがない場合はお詫びしますが、ここではTSの長さ5000で始まり、それを次元のある3Dマトリックスに変換します[1 25 200]。
user1147964 2018

あなたのリンクの方法と比較して、私の方法はより多くのサンプルを作成します。これは、一種の「ローリング」ウィンドウを使用しているためです。この描写を見てください。彼らはローリングウィンドウを使用しません。3分を350x0.5sのチャンクにすることは問題ありません(おそらく必要ないかもしれません-どのくらいの頻度で予測しますか?)、各チャンクは3x3125でなければなりません。「これを3x350x3125の次元を持つ3Dマトリックスに再構築できます」 -これはより良いように聞こえますが、分割後は350x3x3125(3x3125の350チャンク)が予想されます。次に、これらのチャンクのそれぞれを、私が説明したように処理できます。
n1k31t4 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.