4

简介:我正在使用 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;

注意: 函数“预处理”只是将数据转换为记录的百分比差异,而“后处理”将记录的百分比差异转换回用于绘图。(检查 EDIT 的预处理和后处理代码)

结果:

使用 MATLAB 的预测结果截图。

蓝色:预测值

红色:实际值

谁能告诉我我在这里做错了什么?或者也许推荐另一种方法来达到预期的结果(正弦函数的无滞后预测,最终更混乱的时间序列)?非常感激您的帮忙。

编辑: 现在已经有几天了,我希望每个人都过得愉快。由于没有出现任何解决方案,我决定发布辅助函数“postprocess.m”、“preprocess.m”及其辅助函数“normalize.m”的代码。也许这将有助于让球滚起来。

后处理.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

预处理.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 回答