はじめに: MATLAB の Neural Network Toolbox を使用して、時系列を 1 ステップ先まで予測しようとしています。現在、単純な正弦波関数を予測しようとしていますが、満足のいく結果が得られたら、もう少し複雑なものに進むことができれば幸いです。
問題:すべてうまくいっているように見えますが、予測された予測は 1 期間遅れる傾向にあります。ニューラル ネットワーク予測は、1 単位時間遅れた系列を出力するだけではあまり役に立ちませんよね。
コード:
t = -50:0.2:100;
noise = rand(1,length(t));
y = sin(t)+1/2*sin(t+pi/3);
split = floor(0.9*length(t));
forperiod = length(t)-split;
numinputs = 5;
forecasted = [];
msg = '';
for j = 1:forperiod
fprintf(repmat('\b',1,numel(msg)));
msg = sprintf('forecasting iteration %g/%g...\n',j,forperiod);
fprintf('%s',msg);
estdata = y(1:split+j-1);
estdatalen = size(estdata,2);
signal = estdata;
last = signal(end);
[signal,low,high] = preprocess(signal'); % pre-process
signal = signal';
inputs = signal(rowshiftmat(length(signal),numinputs));
targets = signal(numinputs+1:end);
%% NARNET METHOD
feedbackDelays = 1:4;
hiddenLayerSize = 10;
net = narnet(feedbackDelays,[hiddenLayerSize hiddenLayerSize]);
net.inputs{1}.processFcns = {'removeconstantrows','mapminmax'};
signalcells = mat2cell(signal,[1],ones(1,length(signal)));
[inputs,inputStates,layerStates,targets] = preparets(net,{},{},signalcells);
net.trainParam.showWindow = false;
net.trainparam.showCommandLine = false;
net.trainFcn = 'trainlm'; % Levenberg-Marquardt
net.performFcn = 'mse'; % Mean squared error
[net,tr] = train(net,inputs,targets,inputStates,layerStates);
next = net(inputs(end),inputStates,layerStates);
next = postprocess(next{1}, low, high); % post-process
next = (next+1)*last;
forecasted = [forecasted next];
end
figure(1);
plot(1:forperiod, forecasted, 'b', 1:forperiod, y(end-forperiod+1:end), 'r');
grid on;
注: 関数 'preprocess' は単にデータをログに記録された % 差に変換し、'postprocess' はログに記録された % 差をプロット用に変換します。(前処理と後処理のコードについては EDIT を確認してください)
結果:
青: 予測値
赤: 実際の値
ここで私が間違っていることを誰かに教えてもらえますか? または、望ましい結果を達成するための別の方法を推奨しますか (正弦波関数の遅延のない予測、および最終的にはより混沌とした時系列)? よろしくお願いいたします。
編集: 数日経ちましたが、皆さんが週末を楽しんでくれたことを願っています。解決策が見つからないので、ヘルパー関数 'postprocess.m'、'preprocess.m'、およびそれらのヘルパー関数 'normalize.m' のコードを投稿することにしました。たぶん、これはボールを転がすのに役立ちます。
postprocess.m:
function data = postprocess(x, low, high)
% denormalize
logdata = (x+1)/2*(high-low)+low;
% inverse log data
sign = logdata./abs(logdata);
data = sign.*(exp(abs(logdata))-1);
end
preprocess.m:
function [y, low, high] = preprocess(x)
% differencing
diffs = diff(x);
% calc % changes
chngs = diffs./x(1:end-1,:);
% log data
sign = chngs./abs(chngs);
logdata = sign.*log(abs(chngs)+1);
% normalize logrets
high = max(max(logdata));
low = min(min(logdata));
y=[];
for i = 1:size(logdata,2)
y = [y normalize(logdata(:,i), -1, 1)];
end
end
正規化.m:
function Y = normalize(X,low,high)
%NORMALIZE Linear normalization of X between low and high values.
if length(X) <= 1
error('Length of X input vector must be greater than 1.');
end
mi = min(X);
ma = max(X);
Y = (X-mi)/(ma-mi)*(high-low)+low;
end