m行n列の2次元行列​データを入力としたL​STMによる時系列予​測の学習方法について

LSTMによる時系列予測の入力データについて質問です。
こちらのページをサンプルコードとしMatlabによる時系列予測のプログラミングを練習中なのですが、最終的には5行5列の2次元行列データ(350個)を
入力データとし、その時系列予測を行いたいと考えています。
そこで上記ページのコードをもとに書き換え、一旦テストとして以下のようなコードを実行したところ、
「トレーニング シーケンスの特徴次元は 5 1495 1 ですが、入力層には特徴次元 5 5 1 のシーケンスが必要です。」
とエラーが出ました。
5行5列の行列データを300個横方向につなげ5行1500列の一つのデータセットを作成しXTrainとYTtrainを生成、
その後numFeaturesで[5 5 1]を指定することで5行5列ごとに読み込み学習するというようなイメージでいたためこのようになっています。
これを5行5列の行列データごとに学習するようにするためにはどうすればよいでしょうか?
また、numResponsesは1のままでよいのでしょうか?
至らぬ点は多々あるかと存じますが、ご教示のほどどうぞよろしくお願いいたします。
% read
path = %csv形式で保存された5行5列のデータが保存されているフォルダのパス
D = dir(path); % *.csv
dataset = [];
for k = 1:length(D)
datum = % csvファイルの読み込み
dataset = [dataset, datum]; %横方向に結合
end
%%split dataset
dataTrain = dataset(:,1:1500);
dataTest = dataset(:,1501:1750);
XTrain = dataTrain(:,1:1495);
YTrain = dataTrain(:,6:1500);
numFeatures = [5 5 1];
numResponses = 1;
numHiddenUnits = 200;
layers = [ ...
sequenceInputLayer(numFeatures)
flattenLayer('Name','flatten') % サンプルコードに追加
lstmLayer(numHiddenUnits)
fullyConnectedLayer(numResponses)
regressionLayer];
options = trainingOptions('adam', ...
'MaxEpochs',250, ...
'GradientThreshold',1, ...
'InitialLearnRate',0.005, ...
'LearnRateSchedule','piecewise', ...
'LearnRateDropPeriod',125, ...
'LearnRateDropFactor',0.2, ...
'Verbose',0, ...
'Plots','training-progress');
net = trainNetwork(XTrain,YTrain,layers,options);

 Accepted Answer

Kenta
Kenta on 21 Feb 2020
Edited: Kenta on 23 Feb 2020

0 votes

こんにちは、以下のコードで、5×5の入力から2つの値を返すようになっています。
Yuukiさまのコードで改良すべき点は、XTrainの形をかえることではないかと思います。
例えば、XTrainを300個のセルを持つ、セル配列にして、そのセルの1つ1つに5×5のデータを入れるようにします。
今回は、単に横につなげていらっしゃいますが、numFeaturesを[5 5 1]と設定しても、それではうまく反応しません。
おそらく、dataset=[dataset, datanum]として横につなぐのではなく、
XTrain{i}=datanum;のように、各セルの中に格納していくとうまくいくはずです。
「また、numResponsesは1のままでよいのでしょうか?」に関しては、出力する個数を指定してください。
たとえば、下の例だと、2つの出力を返したいため、numResponse=2とすればよいです。
%%split dataset
% dataTrain = dataset(:,1:1500);
% dataTest = dataset(:,1501:1750);
% XTrain = dataTrain(:,1:1495);
% YTrain = dataTrain(:,6:1500);
XTrain = cell(1,300);
for i=1:300
XTrain{i}=randi(100,[5 5]);
end
YTrain = ones(300,2);
numFeatures = 5;
numResponses = 2;
numHiddenUnits = 200;
layers = [ ...
sequenceInputLayer(numFeatures)
flattenLayer('Name','flatten') % サンプルコードに追加
lstmLayer(numHiddenUnits,'OutputMode','last')
fullyConnectedLayer(numResponses)
regressionLayer];
options = trainingOptions('adam', ...
'MaxEpochs',50, ...
'GradientThreshold',1, ...
'InitialLearnRate',0.005, ...
'LearnRateSchedule','piecewise', ...
'LearnRateDropPeriod',125, ...
'LearnRateDropFactor',0.2, ...
'Verbose',0, ...
'Plots','training-progress');
net = trainNetwork(XTrain,YTrain,layers,options);
XTest=cell(10,1);
for i=1:10
XTest{i}=randi(100,[5 5]);
end
YPred = predict(net,XTest)

6 Comments

Yuuki
Yuuki on 22 Feb 2020
Edited: Yuuki on 22 Feb 2020
Kenta 様、
cell配列というものがあるのですね。
当方matlabに移行してきたばかりでして、基礎的な内容の質問をしてしまい申し訳ありませんでした。
Kenta様から頂いたコードで問題なく5行5列の行列データのまま入力として用いることができました。
親切にご対応いただき心より感謝申し上げます。
[追加のご質問]
Kenta様のコードではYTrainやYPred等の出力は2行1列となっており、numResponse=2とすることは理解致しました。
ここである時刻tの入力データをXTrain(t)とすると、それに対する出力YTrain(t)=XTrain(t+1)となる予測値を出力する。
つまり、入力のひとつ先のタイムステップにおける値を予測し、出力も入力と同じく5行5列にしたいと考えています。
このため、本番実行前の練習として頂いたコードを以下のように書き換えたのですが
「無効な学習データです。応答は数値応答のマトリックス、またはシーケンスの N 行 1 列の cell 配列でなければなりま
せん。ここで N はシーケンスの数です。すべてのシーケンスの特徴次元は同じでなければなりません。」
とエラーが出ました。
YTrain{i}=randi(100,[25 1])とすると実行はできましたが、出力を5行5列にすることはできないのでしょうか?
XTrain = cell(1,300);
YTrain = cell(1,300);
for i=1:300
XTrain{i}=randi(100,[5 5]);
YTrain{i}=randi(100,[5 5]); % changed
end
numFeatures = [5 5 1];
numResponses = 25; %changed
numHiddenUnits = 200;
% (以下略)
Kenta
Kenta on 22 Feb 2020
こんにちは、ご丁寧に返信をありがとうございます。
>>cell配列というものがあるのですね。当方matlabに移行してきたばかりでして、基礎的な内容の質問をしてしまい申し訳ありませんでした
確かに、cell配列で入れる、というのははじめは変な感じがするかもしれません。CNNで分類をする、などであれば、比較的敷居は低め(それでも悩むことは多いですが)である一方、いきなりLSTMだとコーディングから悩むことも多いかもしれません。以下、参考になれば幸いです。また別視点のご質問がありましたら新たにご質問を設けていただけると幸いです。
例えば、下のURLでも回帰による出力はN×1の形とあるので、5×5を出力にすることは、直接的にはできないのではと思います。
>>ここである時刻tの入力データをXTrain(t)とすると、それに対する出力YTrain(t)=XTrain(t+1)となる予測値を>>出力する。つまり、入力のひとつ先のタイムステップにおける値を予測し、出力も入力と同じく5行5列に>>したいと考えています。
とありますが、出力したい5×5の縦の列は、例えば各センサーのt+1のデータとして、横方向は、すべてt+1での値なのでしょうか。例えば、横方向の5つの値が、センサーXの-100m, -50m, 0m, 50m, 100m地点の値であるなら、各座標(-100 m地点など)での時系列データをまとめ、学習させればよいのではと思うのですがいかがでしょうか。
Yuuki
Yuuki on 22 Feb 2020
Kenta 様、
>>回帰による出力はN×1の形とあるので、5×5を出力にすることは、直接的にはできないのではと思います。
私の方でもいろいろと試してみましたが、どうやらそのようですね。
>>センサーXの-100m, -50m, 0m, 50m, 100m地点の値であるなら、各座標(-100 m地点など)での時系列データをまとめ、学習させればよいのではと思うのですがいかがでしょうか。
入力と同様の形で出力できなかった場合に私が考えていたバックアッププランがまさにその通りでございます。
実際に用いるデータは仰るような「時刻tにおけるm行n列目の地点で取得したセンサデータ」が格納された行列となっておりますので、入力および出力はN×1の形に切り分けそれぞれの列ごとに学習モデルを作成することで解決しようと思います。
度重なる質問にも丁寧にご返信いただきありがとうございました。
また何か行き詰まった際には改めて新規の質問として設けさせていただきたいと思います。
Kenta
Kenta on 22 Feb 2020
丁寧に進行状況を教えていただきありがとうございます。
>実際に用いるデータは仰るような「時刻tにおけるm行n列目の地点で取得したセンサデータ」が格納された行列となっておりますので、入力および出力はN×1の形に切り分けそれぞれの列ごとに学習モデルを作成することで解決しようと思います。
こちらも報告いただきありがとうございます。
ちなみにですが、(といっても目的や状況次第で以下が適切かどうか変わってくると思いますが)
上のたとえ話でいう、「時刻tにおけるm行n列目の地点で取得したセンサデータ」のt+1における(k,l)での値は、
周辺のt時点での(k,l)周辺のセンサーデータに影響される場合も多くあると思います。その場合は、
関心点の近傍N個分のセンサー×しかるべき時間ステップ分を訓練データ、その中心のセンサーのt+1での値を出力値、として切り出してもよいかもしれません。
Yuuki
Yuuki on 23 Feb 2020
Kenta 様,
>>関心点の近傍N個分のセンサー×しかるべき時間ステップ分を訓練データ、その中心のセンサーのt+1での値を出力値
アドバイスありがとうございます.
手法の一つとして取り入れさせていただきたいと思います.
改めましてご回答ありがとうございました.
今後も機会がございましたらぜひともよろしくお願い致します.
Kenta
Kenta on 23 Feb 2020
失礼いたしました。はじめの回答、いくつか間違いがありました。コードのほう、訂正していますので今後も使う機会があればご注意ください。
また、何かございましたらいつでも聞いてください。よろしくお願いいたします。
YTrain = ones(300,2);
numFeatures = 5;
lstmLayer(numHiddenUnits,'OutputMode','last')

Sign in to comment.

More Answers (0)

Categories

Asked:

on 21 Feb 2020

Commented:

on 23 Feb 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!