exponenta event banner

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

В этом примере показано, как прогнозировать данные временных рядов с использованием сети LSTM.

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

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

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

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

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

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

figure
plot(data)
xlabel("Month")
ylabel("Cases")
title("Monthly 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.

Для больших коллекций данных, длинных последовательностей или больших сетей прогнозы на GPU обычно вычисляются быстрее, чем прогнозы на CPU. В противном случае предсказания на CPU обычно вычисляются быстрее. Для прогнозирования одного шага времени используйте CPU. Чтобы использовать CPU для прогнозирования, установите '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
    248.5531

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

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 = 158.0959

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

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)

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

См. также

| | |

Связанные темы