Прогнозирование временных рядов Используя глубокое обучение

Этот пример показывает, как предсказать данные временных рядов с помощью сети долгой краткосрочной памяти (LSTM).

Чтобы предсказать значения будущих временных шагов последовательности, можно обучить сеть LSTM регрессии от последовательности к последовательности, где ответы являются обучающими последовательностями со значениями, переключенными одним временным шагом. Таким образом, на каждом временном шаге входной последовательности сеть LSTM учится предсказывать значение следующего временного шага.

Чтобы предсказать значения нескольких временных шагов в будущем, используйте функцию predictAndUpdateState, чтобы предсказать временные шаги по одному и обновить сетевое состояние в каждом прогнозе.

Этот пример использует набор данных chickenpox_dataset. Пример обучает сеть LSTM, чтобы предсказать количество случаев ветрянки, учитывая количество случаев в предыдущих месяцах.

Загрузите данные о последовательности

Загрузите данные в качестве примера. chickenpox_dataset содержит одни временные ряды с временными шагами, соответствующими месяцам и значениям, соответствующим количеству случаев. Вывод является массивом ячеек, где каждый элемент является одним временным шагом. Измените данные, чтобы быть вектором - строкой.

data = chickenpox_dataset;
data = [data{:}];

figure
plot(data)
xlabel("Month")
ylabel("Cases")
title("Monthy Cases of Chickenpox")

Разделите обучение и тестовые данные. Обучайтесь на первых 90% последовательности и теста на последних 10%.

numTimeStepsTrain = floor(0.9*numel(data));

dataTrain = data(1:numTimeStepsTrain+1);
dataTest = data(numTimeStepsTrain+1:end);

Стандартизируйте данные

Для лучшей подгонки и препятствовать обучению отличаться, стандартизируйте данные тренировки, чтобы иметь нулевое среднее значение и модульное отклонение. Во время прогноза необходимо стандартизировать тестовые данные с помощью тех же параметров в качестве данных тренировки.

mu = mean(dataTrain);
sig = std(dataTrain);

dataTrainStandardized = (dataTrain - mu) / sig;

Подготовьте предикторы и ответы

Чтобы предсказать значения будущих временных шагов последовательности, задайте ответы, чтобы быть обучающими последовательностями со значениями, переключенными одним временным шагом. Таким образом, на каждом временном шаге входной последовательности сеть LSTM учится предсказывать значение следующего временного шага. Предикторы являются обучающими последовательностями без итогового временного шага.

XTrain = dataTrainStandardized(1:end-1);
YTrain = dataTrainStandardized(2:end);

Задайте сетевую архитектуру LSTM

Создайте сеть регрессии LSTM. Задайте слой LSTM, чтобы иметь 200 скрытых модулей.

numFeatures = 1;
numResponses = 1;
numHiddenUnits = 200;

layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits)
    fullyConnectedLayer(numResponses)
    regressionLayer];

Задайте опции обучения. Установите решатель на 'adam' и обучайтесь в течение 250 эпох. Чтобы препятствовать тому, чтобы градиенты взорвались, установите порог градиента к 1. Укажите, что начальная буква изучает уровень 0.005 и пропускает изучить уровень после 125 эпох путем умножения фактором 0,2.

options = trainingOptions('adam', ...
    'MaxEpochs',250, ...
    'GradientThreshold',1, ...
    'InitialLearnRate',0.005, ...
    'LearnRateSchedule','piecewise', ...
    'LearnRateDropPeriod',125, ...
    'LearnRateDropFactor',0.2, ...
    'Verbose',0, ...
    'Plots','training-progress');

Обучите сеть LSTM

Обучите сеть LSTM с заданными опциями обучения при помощи trainNetwork.

net = trainNetwork(XTrain,YTrain,layers,options);

Предскажите будущие временные шаги

Чтобы предсказать значения нескольких временных шагов в будущем, используйте функцию predictAndUpdateState, чтобы предсказать временные шаги по одному и обновить сетевое состояние в каждом прогнозе. Для каждого прогноза используйте предыдущий прогноз, как введено для функции.

Стандартизируйте тестовые данные с помощью тех же параметров в качестве данных тренировки.

dataTestStandardized = (dataTest - mu) / sig;
XTest = dataTestStandardized(1:end-1);

Чтобы инициализировать сетевое состояние, сначала предскажите на данных тренировки XTrain. Затем, сделайте первый прогноз с помощью последнего временного шага учебного ответа YTrain(end). Цикл по остающимся прогнозам и входу предыдущий прогноз к predictAndUpdateState.

Для большого количества данных, длинных последовательностей или больших сетей, прогнозы на графическом процессоре обычно быстрее, чтобы вычислить, чем прогнозы на центральном процессоре. В противном случае прогнозы на центральном процессоре обычно быстрее, чтобы вычислить. Для одного прогнозов временного шага используйте центральный процессор. Чтобы использовать центральный процессор для прогноза, установите опцию 'ExecutionEnvironment' predictAndUpdateState к 'cpu'.

net = predictAndUpdateState(net,XTrain);
[net,YPred] = predictAndUpdateState(net,YTrain(end));

numTimeStepsTest = numel(XTest);
for i = 2:numTimeStepsTest
    [net,YPred(:,i)] = predictAndUpdateState(net,YPred(:,i-1),'ExecutionEnvironment','cpu');
end

Не стандартизируйте прогнозы с помощью параметров, вычисленных ранее.

YPred = sig*YPred + mu;

Учебный график прогресса сообщает о среднеквадратичной ошибке (RMSE), вычисленной от стандартизированных данных. Вычислите RMSE из нестандартизированных прогнозов.

YTest = dataTest(2:end);
rmse = sqrt(mean((YPred-YTest).^2))
rmse = single
    205.7020

Постройте учебные временные ряды с предсказанными значениями.

figure
plot(dataTrain(1:end-1))
hold on
idx = numTimeStepsTrain:(numTimeStepsTrain+numTimeStepsTest);
plot(idx,[data(numTimeStepsTrain) YPred],'.-')
hold off
xlabel("Month")
ylabel("Cases")
title("Forecast")
legend(["Observed" "Forecast"])

Сравните предсказанные значения с тестовыми данными.

figure
subplot(2,1,1)
plot(YTest)
hold on
plot(YPred,'.-')
hold off
legend(["Observed" "Forecast"])
ylabel("Cases")
title("Forecast")

subplot(2,1,2)
stem(YPred - YTest)
xlabel("Month")
ylabel("Error")
title("RMSE = " + rmse)

Обновите сетевое состояние с наблюдаемыми величинами

Если у вас есть доступ к фактическим значениям временных шагов между прогнозами, то можно обновить сетевое состояние с наблюдаемыми величинами вместо ожидаемых значений.

Во-первых, инициализируйте сетевое состояние. Чтобы сделать прогнозы на новой последовательности, сбросьте сетевое состояние с помощью resetState. Сброс сетевого состояния препятствует тому, чтобы предыдущие прогнозы влияли на прогнозы на новых данных. Сбросьте сетевое состояние, и затем инициализируйте сетевое состояние путем предсказания на данных тренировки.

net = resetState(net);
net = predictAndUpdateState(net,XTrain);

Предскажите на каждом временном шаге. Для каждого прогноза предскажите следующий временной шаг с помощью наблюдаемой величины предыдущего временного шага. Установите опцию 'ExecutionEnvironment' predictAndUpdateState к 'cpu'.

YPred = [];
numTimeStepsTest = numel(XTest);
for i = 1:numTimeStepsTest
    [net,YPred(:,i)] = predictAndUpdateState(net,XTest(:,i),'ExecutionEnvironment','cpu');
end

Не стандартизируйте прогнозы с помощью параметров, вычисленных ранее.

YPred = sig*YPred + mu;

Вычислите среднеквадратичную ошибку (RMSE).

rmse = sqrt(mean((YPred-YTest).^2))
rmse = 124.2284

Сравните предсказанные значения с тестовыми данными.

figure
subplot(2,1,1)
plot(YTest)
hold on
plot(YPred,'.-')
hold off
legend(["Observed" "Predicted"])
ylabel("Cases")
title("Forecast with Updates")

subplot(2,1,2)
stem(YPred - YTest)
xlabel("Month")
ylabel("Error")
title("RMSE = " + rmse)

Здесь, прогнозы более точны при обновлении сетевого состояния с наблюдаемыми величинами вместо ожидаемых значений.

Смотрите также

| | |

Похожие темы