🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

840閲覧

LSTMでエラーが出て困ってます

Dpulex

総合スコア9

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2019/10/07 03:00

前提・実現したいこと

pythonのlstmを用いて異常検知をしようとしています。
lstmのmodel.fitの機能を実装中に以下のエラーメッセージが発生しました。
X_train(行数が300,列数(次元数)が1042の特徴量)を用いて学習させ,X_testに違う値が入った(行数が300,列数(次元数)が1042)の特徴量を利用しようと考えています。最終的に距離を用いてannomary scoreを出したいです。
LSTM初心者のため色々困惑しながらソースを書いています。
何卒よろしくお願いします。

発生している問題・エラーメッセージ

Traceback (most recent call last): File "lstm_tokutyou.py", line 108, in <module> callbacks=[early_stopping]) File "//anaconda3/lib/python3.7/site-packages/keras/engine/training.py", line 952, in fit batch_size=batch_size) File "//anaconda3/lib/python3.7/site-packages/keras/engine/training.py", line 789, in _standardize_user_data exception_prefix='target') File "//anaconda3/lib/python3.7/site-packages/keras/engine/training_utils.py", line 128, in standardize_input_data 'with shape ' + str(data_shape)) ValueError: Error when checking target: expected activation_1 to have 2 dimensions, but got array with shape (300, 1042, 1)

該当のソースコード

python

1#coding:utf-8 2import csv 3import re 4import datetime 5import time 6import numpy as np 7import matplotlib.pyplot as plt 8from keras.models import Sequential 9from keras.layers.core import Dense, Activation 10from keras.layers.recurrent import LSTM 11from keras.layers.wrappers import Bidirectional 12from keras.optimizers import Adam 13from keras.callbacks import EarlyStopping 14from sklearn import datasets 15from sklearn.model_selection import train_test_split 16from sklearn.utils import shuffle 17from sklearn.utils import shuffle 18from keras import initializers 19from sklearn import preprocessing 20def show_graph(day, data, label, color="b"): 21 pylab.figure(figsize=(14, 8)) 22 pylab.subplot(211) 23 pylab.xlabel('time') 24 pylab.ylabel('score') 25 pylab.plot(day, data, color=color, label=label) 26 pylab.legend(loc='upper right') 27 pylab.show() 28data = np.loadtxt("tokutyou1.csv",delimiter=",") 29print(len(data[0])) #1042 30X = data[:,:1042] 31ss = preprocessing.StandardScaler() 32X = preprocessing.scale(X) 33X_train_number = np.arange(300) 34X_train = X[:300] 35X_valid = X[300:400] 36X_test = X[400:700] 37print(len(X_train))#300 38print(len(X_valid))#100 39print(len(X_test)) #300 40X_train = X_train.reshape(-1, 1042, 1) 41X_valid = X_valid.reshape(-1, 1042, 1) 42X_test = X_test.reshape(-1, 1042, 1) 43del X 44 45 46n_in = 1 47n_long = 1042 48n_hidden = 128 49n_out = 1042 50 51 52#def weight_variable(shape, name=None): 53 #return np.random.normal(scale=.01, size=shape) 54 55 56early_stopping = EarlyStopping(monitor='val_loss', patience=10, verbose=1) 57 58model = Sequential() 59model.add(Bidirectional(LSTM(n_hidden), 60 input_shape=(n_long,n_in))) 61model.add(Dense(n_out, kernel_initializer=initializers.random_normal())) 62model.add(Activation('softmax')) 63 64model.compile(loss='categorical_crossentropy', 65 optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999), 66 metrics=['accuracy']) 67 68''' 69モデル学習 70''' 71epochs = 30 72batch_size = 100 73 74hist = model.fit(X_train, X_train, 75 batch_size=batch_size, 76 epochs=epochs, 77 validation_data=(X_valid, X_valid), 78 callbacks=[early_stopping]) 79 80''' 81学習の進み具合を可視化 82''' 83print(hist.history) 84acc = hist.history['val_accuracy'] 85loss = hist.history['val_loss'] 86 87plt.rc('font', family='serif') 88fig = plt.figure() 89plt.plot(range(len(loss)), loss, 90 label='loss', color='black') 91plt.plot(range(len(acc)), acc, 92 label='acc', color='black') 93plt.xlabel('epochs') 94plt.show() 95 96del X_train 97 98preds = model.predict(X_train) 99 100 101 102def calculate_mse(value, predict_value, variance=1.0): 103 value = value[:, 0, 0] 104 print('value') 105 print(value) 106 predict_value = predict_value[:, 0, 0] 107 print('predict_value') 108 print(predict_value) 109 mse_value = [(v - p_v)**2 / variance for v, p_v in zip(value, predict_value)] 110 return np.array(mse_value) 111 112mse_value = mse_value = calculate_mse(X_train, preds, mse_value_variance) 113show_graph(X_train_number, mse_value, 'Anomaly Score train', color="r")

試したこと

ValueError:ターゲットのチェック中にエラーが発生しました:activation_1は2次元であると予想されましたが、形状(300、1042、1)の配列を取得しました

日本語訳するとこうなるのですが、なぜ2次元で予測されているのかわからないです。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

model.compileの下でmodel.outputsをprintしてみてください。
期待する出力の形状と異なっているはずです。

期待する形状: (?, 1042, 1)
現状の出力: (?, 1042)

投稿2019/10/07 04:25

qax

総合スコア622

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Dpulex

2019/10/07 04:35

[<tf.Tensor 'activation_1/Softmax:0' shape=(?, 1042) dtype=float32>] 確かにこのように出てきました。 どのように解決すれば良いのでしょうか?
qax

2019/10/07 04:47 編集

現状のモデル定義では、 Inputs: (?, 1042, 1) = (?, 1042, 1) BidirectionalLSTM: (?, 1042) = (?, n_long) Dense: (?, 1042) = (?, n_out) Softmax: (?, 1042) = (?, n_out) となっています。したがって、outputsは(?, 1042)です。 ここで、おかしい点はいくつかありますが、順を追って説明します。 (1) BidirectionalLSTMの出力が(?, n_long, n_hidden*2)になっていない。 これは、LSTM()に引数return_sequencesがあります。 これはデフォルトはFalseで、最後のステップの出力だけ使うという意味です。 すべてのステップを使用したい場合、Trueに設定します。 こうすると、BidirectionalLSTMの出力が(?, n_long, n_hidden*2)になります。 (2) n_outの値 (1)を実施したとき、BidirectionalLSTMの出力は(?, n_long, n_hidden*2)です。 これにDense(n_out)をかけると、(?, n_long, n_out)=(?, 1024, 1024)となります。 ここで、n_outに指定すべきは1のはずです。1に設定すれば(?, 1024, 1)となります。 Activationで形状が変わることはありませんから、これで出力形状が期待する形状に一致するはずです。
Dpulex

2019/10/07 05:00

回答ありがとうございます。 ただいま修正いたしました。 n_in = 1 n_long = 1042 n_hidden = 128 n_out = 1 #def weight_variable(shape, name=None): #return np.random.normal(scale=.01, size=shape) early_stopping = EarlyStopping(monitor='val_loss', patience=10, verbose=1) model = Sequential() model.add(Bidirectional(LSTM(n_hidden,return_sequences = True), input_shape=(n_long,n_in))) model.add(Dense(n_out, kernel_initializer=initializers.random_normal())) model.add(Activation('softmax')) model.compile(loss='categorical_crossentropy', optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999), metrics=['accuracy']) print(model.outputs) ''' モデル学習 ''' epochs = 30 batch_size = 100 hist = model.fit(X_train, X_train, batch_size=batch_size, epochs=epochs, validation_data=(X_valid, X_valid), callbacks=[early_stopping]) そうすると、このようなエラーが出たのですが、変更の仕方が間違ってましたでしょうか。 [<tf.Tensor 'activation_1/truediv:0' shape=(?, 1042, 1) dtype=float32>] Traceback (most recent call last): File "lstm_tokutyou.py", line 117, in <module> callbacks=[early_stopping]) File "//anaconda3/lib/python3.7/site-packages/keras/engine/training.py", line 952, in fit batch_size=batch_size) File "//anaconda3/lib/python3.7/site-packages/keras/engine/training.py", line 809, in _standardize_user_data y, self._feed_loss_fns, feed_output_shapes) File "//anaconda3/lib/python3.7/site-packages/keras/engine/training_utils.py", line 273, in check_loss_and_target_compatibility ' while using as loss `categorical_crossentropy`. ' ValueError: You are passing a target array of shape (300, 1042, 1) while using as loss `categorical_crossentropy`. `categorical_crossentropy` expects targets to be binary matrices (1s and 0s) of shape (samples, classes). If your targets are integer classes, you can convert them to the expected format via: ``` from keras.utils import to_categorical y_binary = to_categorical(y_int) ``` Alternatively, you can use the loss function `sparse_categorical_crossentropy` instead, which does expect integer targets.
qax

2019/10/07 05:10

loss='categorical_crossentropy'とされていますが、 クロスエントロピーは一般に分類問題(このデータはAとかこのデータはBとかを識別する)に使用される誤差関数です。 この関数は、(?, dim)のような形のデータしか計算できません。 今回の場合は、回帰問題(入力がXXXの時、出力は0.01のような結果をだす)問題ですから、 一般にはmean squared errorを使用します。 コードを編集するには、 loss='categorical_crossentropy' これを loss='mse' に変更します。 使用されているマシンの性能によっては、 InternalError: Blas GEMM launch failed : a.shape=(100, 128), b.shape=(128, 128), m=100, n=128, k=128 [[{{node bidirectional_1/while_1/MatMul_4}}]] [[{{node metrics/acc/Mean_1}}]] のようなものが出るかもしれません。 これは、メモリ不足によるものですので、batch_sizeを減らすか、n_hiddenを減らすしかありません。
qax

2019/10/07 05:15

ちなみに、Activation("Softmax")というのも不自然です。 これも一般に分類問題で使用するものです。 今回の場合はこの行をコメントアウトしてしまうか、入力データの値の範囲が0~1ならActivation("sigmoid")などにするとよいです。
Dpulex

2019/10/07 05:32

ありがとうございます。 エラーを乗り越えることができました。 話は変わるのですが、答えていただけると幸いです。 hist = model.fit(X_train, X_train, batch_size=batch_size, epochs=epochs, validation_data=(X_valid, X_valid), callbacks=[early_stopping]) ここの部分なのですが、X_trainを用いれX_trainをよくしているという解釈でいるのですがあっているのでしょうか。 3つ先の時系列データを予測したいなどというときはどのようにしたらいいでしょうか。 preds = model.predict(X_train) 変数predsが [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] このなるということは正常に作動しているということなのでしょうか。 もしよろしければ回答いただけると嬉しいです。
Dpulex

2019/10/07 05:42

Activation("sigmoid")に変更することを忘れていました。 すると、predsの値も変化し、 [[[0.00634333] [0.00599834] [0.00558019] ... [0.00704193] [0.00725007] [0.00810096]] [[0.00634325] [0.00599846] [0.00558051] ... [0.00704193] [0.00725007] [0.00810102]] [[0.00634325] [0.00599843] [0.00558034] ... [0.00704193] [0.00725007] [0.00810096]] ... [[0.00634331] [0.00599855] [0.00558048] ... [0.005164 ] [0.00548869] [0.00581053]] [[0.00634384] [0.00599912] [0.00558075] ... [0.00516421] [0.00548887] [0.00581065]] [[0.00634345] [0.00599876] [0.00558084] ... [0.00516436] [0.00548893] [0.00581074]]] という形になりました。
qax

2019/10/07 05:47

違います。 まず、 hist = model.fit(X_train, Y_train) # ほかの引数は省略 このようにしたとき、 X_trainを入力として、出力(model.outputs)がY_trainになるように学習していきます。 すなわち、1~1042 stepのデータから、1043~1045 stepのデータを予測したい場合、 X_trainが(?, 1042, 1), Y_train(=model.outputs)が(?, 3, 1)となるようにモデルを設計する必要があります。 # Y_trainに入れる値は、実際の3ステップ後の値を入れます。 また、predsがすべて1になっているのはActivation("Softmax")の影響です。 予測したい値が0~1の範囲であれば、Activation("Sigmoid")、0~∞ なら Activation("Relu") -1~+1ならActivation("tanh")、-∞~∞ならActivation("linear")としましょう。 # 精度を高めたいということであれば、もう少し知識が必要ですが、まずはこれでそれっぽい値が出るはずです。
Dpulex

2019/10/07 05:58

なるほど、解説ありがとうございます。 今の状態ですと、1-1042を用いて1043-2085のデータを予測しているということなのですね。 Activationの値も理解することができました。 mse_value = calculate_mse(X_train, preds, mse_value_variance) show_graph(X_train_number, mse_value, 'Anomaly Score train', color="r") ここの解釈としてはX_trainとpreds(予測した値)との距離という解釈で大丈夫でしょうか?
qax

2019/10/07 06:09

> 今の状態ですと、1-1042を用いて1043-2085のデータを予測しているということなのですね。 半分正解で半分誤っています。 model.fit(X_train, X_train, ...) としているので、X_train(1-1042)を入力としてX_train(1-1042)を予測してしまっています。 通常は1043-1045に当たるデータY_trainを用意し、これを使ってmodel.fit(X_train, Y_train, ...)とします。 > ここの解釈としてはX_trainとpreds(予測した値)との距離という解釈で大丈夫でしょうか? コードそのもの自体はその解釈通りの処理をしています。 ただし、こちらも一般には、calculate_mse(Y_train, preds, mse_value_variance) のようにY_trainを与えて、出力と正解との差分を計算するのが正しいはずです。
Dpulex

2019/10/07 06:31

なるほど、最終的にはX_trainで学習させてしきい値の壁のようなものを作り,X_test(大半はX_trainと似ている特徴量,少量X_trainとは似ていないもの)をpredictさせてX_testの中に存在するX_trainと似ていないものを距離を計算してannomary scoreとして算出したいと考えています。 今の状態ですと、model.fit(X_train, X_train, ...)この部分をどう改良していこうかと悩んでいます。 今Xの行列はX 1042 x 4500の行列で、X_train[0]を読み込んで,X_train[1]を予測したい場合は、X_trainの行数を一つずらしたY_trainを準備すればいいのでしょうか?
qax

2019/10/07 08:02

LSTMを使用した時系列データの異常検知については、よく理解していないと実装が難しい(動きはしてもほんとうに異常検知できているのかよくわからない)です。 ここでは、イメージのみお伝えします。 まず、時系列データによらず、一般のデータでDeepLearningを使用して異常検知をする場合、 Inputs (?, input_dims) -> Hidden (?, hidden_dims) -> Outputs (?, input_dims) このようなネットワークを作成します。 ここで、input_dims > hidden_dims であることに注意してください。 つまり、Inputsに入力データを与え、Denseによって入力データの次元を圧縮し、Outputsに渡すときに次元をもとに戻す。ということをします。 そして、Outputsと入力データの誤差(MSE)をとります。 fit()によって学習を進めると、この誤差が0になるようにモデルが更新されていきます。 これがうまくいくと、入力データを圧縮しても、元のデータを復元できるようなモデルを学習していくわけです。 この学習を正常データだけで行うと、モデルは正常データについては、圧縮して復元することに成功します。 一方、異常データについては、モデルは学習できていないので、圧縮して復元しようとすると、元のデータと異なるデータが出てきてしまうわけです。 この時、入力データと圧縮・復元後の出力データが異なるわけですから、Inputs - Outputsの値が0でなくなる(大きい)わけですね。 こうして、入力されたデータが異常であると分かるわけです。 一般には、もう少し高度なテクニックを使って異常検知をしますが(これだけでは複雑なタスクの場合精度がでないため)、基本的な概念はこのような形です。 =====まずはここまでを理解した上で以降に取り組むとよいです。===== 時系列データを扱う場合、工夫が必要です。 例えば以下のような構成の場合、 Inputs(?, 3 steps, 1 dims) -> Hidden(?, 3 steps, n_dims) -> Outputs(?, 3 steps, 1 dims) まず、次元の圧縮が1dimsなので、これ以上圧縮できません。 そして、通常のLSTMでは、 出力の 1step目は入力の1step目のみを使って計算されます。 出力の 2step目は入力の1,2step目を使って計算されます。 出力の 3step目は入力の1,2,3step目を使って計算されます。 この時、明らかに最後のstepの方が情報量が多いですね。平等ではありません。 そこで、2つのLSTMを用意します。 片方は入力を入れるだけの出力のないLSTMです。 もう片方は最初のLSTMの状態を受け取って入力データを使わずに出力するLSTMです。 言葉では説明が難しいので、イメージを描きます。     x x x   ① ② ③ (出力)     ↑ ↑ ↑   ↑ ↑ ↑     ○→○→○ → ○→○→○     ↑ ↑ ↑   ↑ ↑ ↑ (入力)① ② ③   △ ① ② このような構成です。 xの部分は使いません。 △はノイズです。 右側のLSTMでは最初のステップの入力のノイズ(例えば定数0)を入れて、 出力①を得ます。そしてその次のstepの入力にはここで得た出力①を入れます。 そしてさらに出力②を使って出力③を得る。 といったイメージです。 こうして出力と入力データの差が0になるように学習させていきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問