MATLAB:一步到位的神经网络时间序列预测

时间:2013-01-31 04:17:40

标签: matlab neural-network time-series lag prediction

简介:我正在使用MATLAB的神经网络工具箱,试图将时间序列预测到未来的一步。目前我只是想预测一个简单的正弦函数,但希望在得到满意的结果后我能够继续进行更复杂的事情。

问题:一切似乎都运转正常,但预测的预测往往会滞后一个时期。如果神经网络预测只是输出延迟一个单位时间的系列,那么神经网络预测就不多了,对吗?

代码:

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'将记录的%差异转换回绘图。 (检查编辑预处理和后处理代码)

结果:

A screenshot of the forecasting results using MATLAB. http://img59.imageshack.us/img59/8831/narnetsinusoidalforecas.png

蓝色:预测值

RED:实际值

谁能告诉我这里我做错了什么?或者可能会推荐另一种方法来实现预期的结果(正弦函数的无滞后预测,以及最终更混乱的时间序列)?非常感谢您的帮助。

修改 已经有几天了,我希望每个人都享受他们的周末。由于没有出现解决方案,我决定发布辅助函数'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

normalize.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

1 个答案:

答案 0 :(得分:4)

我没有检查您的代码,但进行了类似的测试以使用NN预测sin()。结果似乎合理,没有滞后。我认为,您的错误是预测值与实际值同步的某个地方。 这是代码:

%% 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

enter image description here