Crear una red para el pronóstico de series de tiempo con Deep Network Designer
Este ejemplo muestra cómo crear una red de memoria de corto-largo plazo (LSTM) para pronosticar datos de series de tiempo con la app Deep Network Designer.
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 crear una red de LSTM para pronosticar series de tiempo, utilice la app Deep Network Designer.
Esta figura muestra un ejemplo de secuencia con valores pronosticados mediante la predicción de lazo cerrado.
Cargar datos secuenciales
Cargue los datos de ejemplo de WaveformData
. Para acceder a los datos, abra el ejemplo como un script en vivo. El conjunto de datos con forma de onda contiene 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.
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 algunas de las secuencias.
idx = 1;
numChannels = size(data{idx},2);
figure
stackedplot(data{idx},DisplayLabels="Channel " + (1:numChannels))
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.
numObservations = numel(data); XData = cell(numObservations,1); TData = cell(numObservations,1); for n = 1:numObservations X = data{n}; XData{n} = X(1:end-1,:); TData{n} = X(2:end,:); end
Divida los datos en conjuntos de entrenamiento, validación y prueba. Utilice el 80% de los datos para el entrenamiento, el 10% para la validación y el 10% para la prueba. Para dividir los datos, use la función trainingPartitions
, incluida en este ejemplo como un archivo de soporte. Para acceder al archivo, abra el ejemplo como un script en vivo.
[idxTrain,idxValidation,idxTest] = trainingPartitions(numObservations,[0.8 0.1 0.1]); XTrain = XData(idxTrain); TTrain = TData(idxTrain); XValidation = XData(idxValidation); TValidation = TData(idxValidation); XTest = XData(idxTest); TTest = TData(idxTest);
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 validación y 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 los datos de entrenamiento 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
Normalice los datos de validación y prueba con las estadísticas calculadas a partir de los datos de entrenamiento.
for n = 1:numel(XValidation) XValidation{n} = (XValidation{n} - muX) ./ sigmaX; TValidation{n} = (TValidation{n} - muT) ./ sigmaT; end for n = 1:numel(XTest) XTest{n} = (XTest{n} - muX) ./ sigmaX; TTest{n} = (TTest{n} - muT) ./ sigmaT; end
Definir la arquitectura de red
Para crear la red, abra la app Deep Network Designer.
deepNetworkDesigner
Para crear una red de secuencia, en la sección Sequence Networks, deténgase en Sequence-to-Sequence y haga clic en Open.
Se abrirá una red preconstruida adecuada para problemas de clasificación de secuencias. La red contiene estas capas:
sequenceInputLayer
lstmLayer
dropoutLayer
fullyConnectedLayer
softmaxLayer
Puede convertir la red de clasificación en una red adecuada para el pronóstico de series de tiempo editando las capas finales. Primero, elimine la capa softmax.
A continuación, ajuste las propiedades de las capas para que sean adecuadas para el conjunto de datos con forma de onda. Dado que el objetivo es pronosticar puntos de datos futuros en una serie de tiempo, el tamaño de salida debe ser igual que el tamaño de entrada. En este ejemplo, los datos de entrada tienen tres canales de entrada, por lo que la salida de la red también debe tener tres canales de salida.
Seleccione la capa de entrada de secuencias input
y establezca InputSize en 3.
Seleccione la capa totalmente conectada fc
y establezca OutputSize en 3.
La capa de LSTM tiene 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. La capa de abandono ayuda a evitar el sobreajuste estableciendo aleatoriamente las entradas de la capa en cero y cambiando de forma efectiva la arquitectura de red entre iteraciones de entrenamiento. Una mayor probabilidad de abandono puede mejorar la generalización del modelo a costa de perder información y ralentizar el proceso de aprendizaje.
Para comprobar que la red está preparada para el entrenamiento, haga clic en Analyze. Dado que el analizador Deep Learning Network Analyzer no detecta ningún error o advertencia, la red está preparada para el entrenamiento. Para exportar la red, haga clic en Export. La app guarda la red en la variable net_1
.
Especificar las opciones de entrenamiento
Especifique las opciones de entrenamiento. Para escoger entre las opciones se requiere un análisis empírico. Para explorar diferentes configuraciones de opciones de entrenamiento mediante la ejecución de experimentos, puede utilizar la app Experiment Manager.
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.
Monitorice el sobreajuste con los datos de validación.
Monitorice el error cuadrático medio raíz.
Muestre el progreso del entrenamiento en una gráfica.
Deshabilite la salida detallada.
options = trainingOptions("adam", ... MaxEpochs=200, ... SequencePaddingDirection="left", ... Shuffle="every-epoch", ... ValidationData={XValidation,TValidation}, ... Metrics="rmse", ... Plots="training-progress", ... Verbose=false);
Entrenar una red neuronal
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,net_1,"mse",options);
Probar una red neuronal recurrente
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 eliminándolo antes de calcular el RMSE.
numObservationsTest = numel(XTest); 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.5304
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 = 3; X = XTest{idx}; T = TTest{idx}; figure stackedplot(X,DisplayLabels="Channel " + (1:numChannels)) xlabel("Time Step") title("Test Observation " + idx)
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.
Pronóstico de lazo abierto
Realice un pronóstico de lazo abierto.
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,:); 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
Realice un pronóstico de lazo cerrado.
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.