В этом примере показано, как предсказать данные временных рядов с помощью сети долгой краткосрочной памяти (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, чтобы иметь 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 с заданными опциями обучения при помощи 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
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)
Здесь, предсказания более точны при обновлении сетевого состояния с наблюдаемыми величинами вместо ожидаемых значений.
trainNetwork
| trainingOptions
| lstmLayer
| sequenceInputLayer