MATLAB:一步先进的神经网络时间序列预测

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;

注意: 函数“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

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

哦,我的意思是在机器学习中提问。非常抱歉。 - user1656007
1个回答

4

我没有检查你的代码,但是进行了类似的测试,用神经网络预测sin()。结果看起来合理,没有滞后。我认为你的bug出现在将预测值与实际值同步的某个地方。 以下是代码:

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


你是对的,这是一个同步错误。导致错误的代码是这个小家伙:estdata = y(1:split+j-1);-1 是不必要的。非常感谢您的帮助,先生。 - user1656007

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接