4

はじめに: 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 を確認してください)

結果:

MATLAB を使用した予測結果のスクリーンショット。

青: 予測値

赤: 実際の値

ここで私が間違っていることを誰かに教えてもらえますか? または、望ましい結果を達成するための別の方法を推奨しますか (正弦波関数の遅延のない予測、および最終的にはより混沌とした時系列)? よろしくお願いいたします。

編集: 数日経ちましたが、皆さんが週末を楽しんでくれたことを願っています。解決策が見つからないので、ヘルパー関数 '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
4

1 に答える 1

4

私はあなたのコードをチェックしませんでしたが、sin()NN で予測するために同様のテストを行いました。結果は、ラグなしで妥当なようです。あなたのバグは、予測値と実際の値の同期のどこかにあると思います。コードは次のとおりです。

%% init & params
t = (-50 : 0.2 : 100)';
y = sin(t) + 0.5 * sin(t + pi / 3);
sigma = 0.2;
n_lags = 12;
hidden_layer_size = 15;
%% create net
net = fitnet(hidden_layer_size);
%% train
noise = sigma * randn(size(t));
y_train = y + noise;
out = circshift(y_train, -1);
out(end) = nan;
in = lagged_input(y_train, n_lags);
net = train(net, in', out');
%% test
noise = sigma * randn(size(t)); % new noise
y_test = y + noise;
in_test = lagged_input(y_test, n_lags);
out_test = net(in_test')';
y_test_predicted = circshift(out_test, 1); % sync with actual value
y_test_predicted(1) = nan;
%% plot
figure, 
plot(t, [y, y_test, y_test_predicted], 'linewidth', 2); 
grid minor; legend('orig', 'noised', 'predicted')

そしてlagged_input()機能:

function in = lagged_input(in, n_lags)
    for k = 2 : n_lags
        in = cat(2, in, circshift(in(:, end), 1));
        in(1, k) = nan;
    end
end

ここに画像の説明を入力

于 2013-02-04T18:11:59.780 に答える