Pronóstico de series de tiempo mediante deep learning
Este ejemplo muestra cómo pronosticar datos de series de tiempo mediante una red de memoria de corto-largo plazo (LSTM).
Una red de LSTM es una red neuronal recurrente (RNN) que procesa datos de entrada formando un lazo con las unidades de tiempo y actualizando el estado de la RNN. El estado de la RNN contiene información recordada durante todas las unidades de tiempo anteriores. Puede utilizar una red neuronal de LSTM para pronosticar valores posteriores de una serie de tiempo o secuencia utilizando las unidades de tiempo anteriores como entrada. Para entrenar una red neuronal de LSTM para el pronóstico de series de tiempo, entrene una red neuronal de regresión de LSTM con salida secuencial, donde las respuestas (objetivos) son las secuencias de entrenamiento con valores desplazados una unidad de tiempo. En otras palabras, en cada unidad de tiempo de la secuencia de entrada, la red neuronal de LSTM aprende a predecir el valor de la siguiente unidad de tiempo.
Existen dos métodos para pronosticar: pronóstico de lazo abierto y de lazo cerrado.
Pronóstico de lazo abierto: prediga la siguiente unidad de tiempo en una secuencia utilizando solo datos de entrada. Cuando se hacen predicciones para unidades de tiempo posteriores, se recopilan valores reales de la fuente de datos y se utilizan como entrada. Por ejemplo, imagine que desea predecir el valor para la unidad de tiempo de una secuencia con datos recopilados en las unidades de tiempo desde 1 hasta . Para hacer predicciones para la unidad de tiempo , espere hasta que registre el valor real de la unidad de tiempo y utilícelo como entrada para hacer la siguiente predicción. Utilice el pronóstico de lazo abierto cuando tenga valores reales que proporcionar a la RNN antes de hacer la siguiente predicción.
Pronóstico de lazo cerrado: prediga unidades de tiempo posteriores en una secuencia utilizando las predicciones previas como entrada. En este caso, el modelo no requiere los valores reales para realizar la predicción. Por ejemplo, imagine que desea predecir los valores para las unidades de tiempo desde hasta de la secuencia con datos recopilados en las unidades de tiempo desde 1 hasta únicamente. Para hacer predicciones para la unidad de tiempo , utilice el valor predicho para la unidad de tiempo como entrada. Utilice el pronóstico de lazo cerrado para pronosticar varias unidades de tiempo posteriores o cuando no tenga valores reales que proporcionar a la RNN antes de hacer la siguiente predicción.
Esta figura muestra un ejemplo de secuencia con valores pronosticados mediante la predicción de lazo cerrado.
Este ejemplo utiliza el conjunto de datos con forma de onda, que contiene 2000 formas de onda generadas de forma sintética de diferentes longitudes con tres canales. En este ejemplo se entrena una red neuronal de LSTM para pronosticar valores futuros de las formas de onda, dados los valores de unidades de tiempo anteriores, mediante pronósticos tanto de lazo cerrado como de lazo abierto.
Cargar datos
Cargue los datos de ejemplo de WaveformData.mat
. Los datos son un arreglo de celdas de numObservations
por 1 de secuencias, donde numObservations
es el número de secuencias. Cada secuencia es un arreglo numérico de numTimeSteps
por -numChannels
, donde numTimeSteps
es el número de unidades de tiempo y numChannels
es el número de canales de la secuencia.
load WaveformData
Visualice los tamaños de las primeras secuencias.
data(1:4)
ans=4×1 cell array
{103×3 double}
{136×3 double}
{140×3 double}
{124×3 double}
Visualice el número de canales. Para entrenar la red neuronal de LSTM, cada secuencia debe tener el mismo número de canales.
numChannels = size(data{1},2)
numChannels = 3
Visualice las primeras secuencias en una gráfica.
figure tiledlayout(2,2) for i = 1:4 nexttile stackedplot(data{i}) xlabel("Time Step") end
Divida los datos en conjuntos de prueba y de entrenamiento. Utilice el 90% de las observaciones para el entrenamiento y el resto para la prueba.
numObservations = numel(data); idxTrain = 1:floor(0.9*numObservations); idxTest = floor(0.9*numObservations)+1:numObservations; dataTrain = data(idxTrain); dataTest = data(idxTest);
Preparar datos para el entrenamiento
Para pronosticar los valores de unidades de tiempo futuras de una secuencia, especifique los objetivos como las secuencias de entrenamiento con valores desplazados una unidad de tiempo. No incluya la unidad de tiempo final en las secuencias de entrenamiento. En otras palabras, en cada unidad de tiempo de la secuencia de entrada, la red neuronal de LSTM aprende a predecir el valor de la siguiente unidad de tiempo. Los predictores son las secuencias de entrenamiento sin la unidad de tiempo final.
numObservationsTrain = numel(dataTrain); XTrain = cell(numObservationsTrain,1); TTrain = cell(numObservationsTrain,1); for n = 1:numObservationsTrain X = dataTrain{n}; XTrain{n} = X(1:end-1,:); TTrain{n} = X(2:end,:); end
Para un mejor ajuste y para evitar que el entrenamiento diverja, normalice los predictores y los objetivos para que los canales tengan media cero y varianza unitaria. Cuando haga predicciones, también deberá normalizar los datos de prueba con las mismas estadísticas que los datos de entrenamiento.
Calcule la media por canal y los valores de desviación estándar de las secuencias. Para calcular fácilmente la media y la desviación estándar de los datos de entrenamiento, cree arreglos numéricos que contengan las secuencias concatenadas utilizando la función cell2mat
.
muX = mean(cell2mat(XTrain)); sigmaX = std(cell2mat(XTrain),0); muT = mean(cell2mat(TTrain)); sigmaT = std(cell2mat(TTrain),0);
Normalice las secuencias utilizando la media y los valores de desviación estándar calculados.
for n = 1:numel(XTrain) XTrain{n} = (XTrain{n} - muX) ./ sigmaX; TTrain{n} = (TTrain{n} - muT) ./ sigmaT; end
Definir la arquitectura de red neuronal de LSTM
Cree una red neuronal de regresión de LSTM.
Utilice una capa de entrada de secuencias con un tamaño de entrada que coincida con el número de canales de los datos de entrada.
Utilice una capa de LSTM con 128 unidades ocultas. El número de unidades ocultas determina cuánta información aprende la capa. Utilizar más unidades ocultas puede producir resultados más precisos, pero es más probable que se produzca un sobreajuste de los datos de entrenamiento.
Para generar secuencias con el mismo número de canales que los datos de entrada, incluya una capa totalmente conectada con un tamaño de salida que coincida con el número de canales de los datos de entrada.
layers = [ sequenceInputLayer(numChannels) lstmLayer(128) fullyConnectedLayer(numChannels)];
Especificar las opciones de entrenamiento
Especifique las opciones de entrenamiento.
Entrene utilizando la optimización de Adam.
Entrene durante 200 épocas. Para conjuntos de datos más grandes, puede que no sea necesario entrenar durante tantas épocas para conseguir un buen ajuste.
En cada minilote, rellene a la izquierda las secuencias para que tengan la misma longitud. Rellenar a la izquierda evita que la RNN prediga valores de relleno al final de las secuencias.
Cambie el orden de los datos en cada época.
Muestre el progreso del entrenamiento en una gráfica.
Deshabilite la salida detallada.
options = trainingOptions("adam", ... MaxEpochs=200, ... SequencePaddingDirection="left", ... Shuffle="every-epoch", ... Plots="training-progress", ... Verbose=false);
Entrenar una red neuronal recurrente
Entrene la red neuronal de LSTM con la función trainnet
. Para la regresión, utilice la pérdida de error cuadrático medio. De forma predeterminada, la función trainnet
usa una GPU en caso de que esté disponible. Para utilizar una GPU se requiere una licencia de Parallel Computing Toolbox™ y un dispositivo GPU compatible. Para obtener información sobre los dispositivos compatibles, consulte GPU Computing Requirements (Parallel Computing Toolbox). De lo contrario, la función usa la CPU. Para especificar el entorno de ejecución, utilice la opción de entrenamiento ExecutionEnvironment
.
net = trainnet(XTrain,TTrain,layers,"mse",options);
Probar una red neuronal recurrente
Prepare los datos de prueba para la predicción utilizando los mismos pasos que para los datos de entrenamiento.
Normalice los datos de prueba con las estadísticas calculadas a partir de los datos de entrenamiento. Especifique los objetivos como secuencias de prueba con valores desplazados una unidad de tiempo y los predictores como secuencias de prueba sin la unidad de tiempo final.
numObservationsTest = numel(dataTest); XTest = cell(numObservationsTest,1); TTest = cell(numObservationsTest,1); for n = 1:numObservationsTest X = dataTest{n}; XTest{n} = (X(1:end-1,:) - muX) ./ sigmaX; TTest{n} = (X(2:end,:) - muT) ./ sigmaT; end
Realice predicciones con la función minibatchpredict
. De forma predeterminada, la función minibatchpredict
usa una GPU en caso de que esté disponible. Rellene las secuencias con las mismas opciones de relleno que para el entrenamiento. Para las tareas de secuencia a secuencia con secuencias de diferentes longitudes, devuelva las predicciones como un arreglo de celdas configurando la opción UniformOutput
en false
.
YTest = minibatchpredict(net,XTest, ... SequencePaddingDirection="left", ... UniformOutput=false);
En cada secuencia de prueba, calcule el error cuadrático medio raíz (RMSE) entre las predicciones y los objetivos. Ignore cualquier valor de relleno en las secuencias predichas utilizando las longitudes de las secuencias objetivo como referencia.
for n = 1:numObservationsTest T = TTest{n}; sequenceLength = size(T,1); Y = YTest{n}(end-sequenceLength+1:end,:); err(n) = rmse(Y,T,"all"); end
Visualice los errores en un histograma. Cuanto más bajos sean los valores, mayor será la precisión.
figure histogram(err) xlabel("RMSE") ylabel("Frequency")
Calcule el RMSE medio en todas las observaciones de prueba.
mean(err,"all")
ans = single
0.5099
Pronosticar unidades de tiempo futuras
Dada una serie de tiempo o una secuencia de entrada, para pronosticar los valores de varias unidades de tiempo futuras, utilice la función predict
para predecir unidades de tiempo una por una y actualizar el estado de la RNN en cada predicción. Para cada predicción, utilice la predicción anterior como la entrada para la función.
Visualice una de las secuencias de prueba en una gráfica.
idx = 2; X = XTest{idx}; T = TTest{idx}; figure stackedplot(X,DisplayLabels="Channel " + (1:numChannels)) xlabel("Time Step") title("Test Observation " + idx)
Pronóstico de lazo abierto
El pronóstico de lazo abierto predice la siguiente unidad de tiempo en una secuencia utilizando solo datos de entrada. Cuando se hacen predicciones para unidades de tiempo posteriores, se recopilan valores reales de la fuente de datos y se utilizan como entrada. Por ejemplo, imagine que desea predecir el valor para la unidad de tiempo de una secuencia con datos recopilados en las unidades de tiempo desde 1 hasta . Para hacer predicciones para la unidad de tiempo , espere hasta que registre el valor real de la unidad de tiempo y utilícelo como entrada para hacer la siguiente predicción. Utilice el pronóstico de lazo abierto cuando tenga valores reales que proporcionar a la RNN antes de hacer la siguiente predicción.
Inicialice el estado de la RNN restableciendo primero el estado mediante la función resetState
. A continuación, realice una predicción inicial con las primeras unidades de tiempo de los datos de entrada. Actualice el estado de la RNN con las primeras 75 unidades de tiempo de los datos de entrada.
net = resetState(net); offset = 75; [Z,state] = predict(net,X(1:offset,:)); net.State = state;
Para pronosticar más predicciones, forme un bucle con las unidades de tiempo y haga predicciones mediante la función predict
. Después de cada predicción, actualice el estado de la RNN. Pronostique los valores para las unidades de tiempo restantes de la observación de prueba formando un lazo con las unidades de tiempo de los datos de entrada y utilícelos como entrada para la RNN. La última unidad de tiempo de la predicción inicial es la primera unidad de tiempo pronosticada.
numTimeSteps = size(X,1); numPredictionTimeSteps = numTimeSteps - offset; Y = zeros(numPredictionTimeSteps,numChannels); Y(1,:) = Z(end,1); for t = 1:numPredictionTimeSteps-1 Xt = X(offset+t,:); [Y(t+1,:),state] = predict(net,Xt); net.State = state; end
Compare las predicciones con los valores de entrada.
figure t = tiledlayout(numChannels,1); title(t,"Open Loop Forecasting") for i = 1:numChannels nexttile plot(X(:,i)) hold on plot(offset:numTimeSteps,[X(offset,i) Y(:,i)'],"--") ylabel("Channel " + i) end xlabel("Time Step") nexttile(1) legend(["Input" "Forecasted"])
Pronóstico de lazo cerrado
El pronóstico de lazo cerrado predice unidades de tiempo posteriores en una secuencia utilizando las predicciones previas como entrada. En este caso, el modelo no requiere los valores reales para realizar la predicción. Por ejemplo, imagine que desea predecir el valor para las unidades de tiempo desde hasta de la secuencia con datos recopilados en las unidades de tiempo desde 1 hasta únicamente. Para hacer predicciones para la unidad de tiempo , utilice el valor predicho para la unidad de tiempo como entrada. Utilice el pronóstico de lazo cerrado para pronosticar varias unidades de tiempo posteriores o cuando no tenga valores reales que proporcionar a la RNN antes de hacer la siguiente predicción.
Inicialice el estado de la RNN restableciendo primero el estado mediante la función resetState
. A continuación, realice una predicción inicial Z
con las primeras unidades de tiempo de los datos de entrada. Actualice el estado de la RNN con todas las unidades de tiempo de los datos de entrada.
net = resetState(net); offset = size(X,1); [Z,state] = predict(net,X(1:offset,:)); net.State = state;
Para pronosticar más predicciones, forme un bucle con las unidades de tiempo y haga predicciones mediante la función predict
. Después de cada predicción, actualice el estado de la RNN. Pronostique las próximas 200 unidades de tiempo pasando iterativamente el valor predicho anteriormente a la RNN. Dado que la RNN no requiere los datos de entrada para realizar más predicciones, puede especificar cualquier número de unidades de tiempo que desee pronosticar. La última unidad de tiempo de la predicción inicial es la primera unidad de tiempo pronosticada.
numPredictionTimeSteps = 200; Y = zeros(numPredictionTimeSteps,numChannels); Y(1,:) = Z(end,:); for t = 2:numPredictionTimeSteps [Y(t,:),state] = predict(net,Y(t-1,:)); net.State = state; end
Visualice los valores pronosticados en una gráfica.
numTimeSteps = offset + numPredictionTimeSteps; figure t = tiledlayout(numChannels,1); title(t,"Closed Loop Forecasting") for i = 1:numChannels nexttile plot(X(1:offset,i)) hold on plot(offset:numTimeSteps,[X(offset,i) Y(:,i)'],"--") ylabel("Channel " + i) end xlabel("Time Step") nexttile(1) legend(["Input" "Forecasted"])
El pronóstico de lazo cerrado permite pronosticar un número arbitrario de unidades de tiempo, pero puede resultar menos preciso en comparación con el pronóstico de lazo abierto, ya que la RNN no tiene acceso a los valores reales durante el proceso de pronóstico.
Consulte también
trainnet
| trainingOptions
| dlnetwork
| lstmLayer
| sequenceInputLayer
Temas relacionados
- Generate Text Using Deep Learning
- Clasificación de secuencias mediante deep learning
- Clasificación secuencia a secuencia mediante deep learning
- Regresión de secuencia a secuencia mediante deep learning
- Regresión de secuencia a uno mediante deep learning
- Redes neuronales de memoria de corto-largo plazo
- Deep learning en MATLAB