Extracción de funciones del codificador automático para regresión
Autoencoder es un tipo de red neuronal que se puede utilizar para aprender una representación comprimida de datos sin procesar.
Un codificador automático se compone de submodelos de codificador y decodificador. El codificador comprime la entrada y el decodificador intenta recrear la entrada a partir de la versión comprimida proporcionada por el codificador. Después del entrenamiento, el modelo del codificador se guarda y el decodificador se descarta.
Luego, el codificador se puede utilizar como técnica de preparación de datos para realizar la extracción de características en datos sin procesar que se pueden usar para entrenar un modelo de aprendizaje automático diferente.
En este tutorial, descubrirá cómo desarrollar y evaluar un codificador automático para predicción de regresión.
Después de completar este tutorial, sabrá:
- Un codificador automático es un modelo de red neuronal que se puede utilizar para aprender una representación comprimida de datos sin procesar.
- Cómo entrenar un modelo de codificador automático en un conjunto de datos de entrenamiento y guardar solo la parte del codificador del modelo.
- Cómo utilizar el codificador como paso de preparación de datos al entrenar un modelo de aprendizaje automático.
Empecemos.
Descripción general del tutorial
Este tutorial se divide en tres partes; ellos son:
- Codificadores automáticos para extracción de funciones
- Codificador automático para regresión
- Autocodificador como preparación de datos
Codificadores automáticos para extracción de funciones
Un codificador automático es un modelo de red neuronal que busca aprender una representación comprimida de una entrada.
Un codificador automático es una red neuronal entrenada para intentar copiar su entrada en su salida.
— Página 502, Aprendizaje profundo, 2016.
Son un método de aprendizaje no supervisado, aunque técnicamente se entrenan mediante métodos de aprendizaje supervisado, los denominados autosupervisados. Por lo general, se entrenan como parte de un modelo más amplio que intenta recrear la entrada.
Por ejemplo:
- X=modelo.predecir(X)
El diseño del modelo de codificador automático hace que esto sea un desafío al restringir la arquitectura a un cuello de botella en el punto medio del modelo, a partir del cual se realiza la reconstrucción de los datos de entrada.
Hay muchos tipos de codificadores automáticos y su uso varía, pero quizás el uso más común sea como modelo de extracción automática o aprendida de características.
En este caso, una vez que el modelo está ajustado, se puede descartar el aspecto de reconstrucción del modelo y se puede utilizar el modelo hasta el punto del cuello de botella. La salida del modelo en el cuello de botella es un vector de longitud fija que proporciona una representación comprimida de los datos de entrada.
Por lo general, están restringidos de manera que les permitan copiar solo aproximadamente y copiar solo entradas que se parezcan a los datos de entrenamiento. Debido a que el modelo se ve obligado a priorizar qué aspectos de la entrada deben copiarse, a menudo aprende propiedades útiles de los datos.
— Página 502, Aprendizaje profundo, 2016.
Luego, los datos de entrada del dominio se pueden proporcionar al modelo y la salida del modelo en el cuello de botella se puede utilizar como un vector de características en un modelo de aprendizaje supervisado, para visualización o, más generalmente, para reducción de dimensionalidad.
A continuación, exploremos cómo podríamos desarrollar un codificador automático para la extracción de características en un problema de modelado predictivo de regresión.
Codificador automático para regresión
En esta sección, desarrollaremos un codificador automático para aprender una representación comprimida de las características de entrada para un problema de modelado predictivo de regresión.
Primero, definamos un problema de modelado predictivo de regresión.
Usaremos la función scikit-learn make_regression() para definir una tarea de regresión sintética con 100 características de entrada (columnas) y 1000 ejemplos (filas). Es importante destacar que definiremos el problema de tal manera que la mayoría de las variables de entrada sean redundantes (90 del 100 o 90 por ciento), lo que permitirá que el codificador automático aprenda más tarde una representación comprimida útil.
El siguiente ejemplo define el conjunto de datos y resume su forma.
# synthetic regression dataset
from sklearn.datasets import make_regression
# define dataset
X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)
# summarize the dataset
print(X.shape, y.shape)
La ejecución del ejemplo define el conjunto de datos e imprime la forma de las matrices, confirmando el número de filas y columnas.
(1000, 100) (1000,)
A continuación, desarrollaremos un modelo de codificador automático de perceptrón multicapa (MLP).
El modelo tomará todas las columnas de entrada y luego generará los mismos valores. Aprenderá a recrear exactamente el patrón de entrada.
El codificador automático consta de dos partes: el codificador y el decodificador. El codificador aprende cómo interpretar la entrada y comprimirla en una representación interna definida por la capa de cuello de botella. El decodificador toma la salida del codificador (la capa de cuello de botella) e intenta recrear la entrada.
Una vez que se entrena el codificador automático, la decodificación se descarta y solo conservamos el codificador y lo usamos para comprimir ejemplos de entrada en vectores de salida por la capa de cuello de botella.
En este primer codificador automático, no comprimiremos la entrada en absoluto y usaremos una capa de cuello de botella del mismo tamaño que la entrada. Este debería ser un problema fácil que el modelo aprenderá casi a la perfección y tiene como objetivo confirmar que nuestro modelo esté implementado correctamente.
Definiremos el modelo utilizando la API funcional. Si esto es nuevo para ti, te recomiendo este tutorial:
- Cómo utilizar la API funcional de Keras para el aprendizaje profundo
Antes de definir y ajustar el modelo, dividiremos los datos en conjuntos de entrenamiento y prueba y escalaremos los datos de entrada normalizando los valores al rango 0-1, una buena práctica con MLP.
...
# split into train test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# scale data
t = MinMaxScaler()
t.fit(X_train)
X_train = t.transform(X_train)
X_test = t.transform(X_test)
Definiremos el codificador para que tenga una capa oculta con la misma cantidad de nodos que hay en los datos de entrada con normalización por lotes y activación ReLU.
A esto le sigue una capa de cuello de botella con el mismo número de nodos que columnas en los datos de entrada, p. sin compresión.
...
# define encoder
visible = Input(shape=(n_inputs,))
e = Dense(n_inputs*2)(visible)
e = BatchNormalization()(e)
e = ReLU()(e)
# define bottleneck
n_bottleneck = n_inputs
bottleneck = Dense(n_bottleneck)(e)
El decodificador se definirá con la misma estructura.
Tendrá una capa oculta con normalización por lotes y activación ReLU. La capa de salida tendrá la misma cantidad de nodos que columnas en los datos de entrada y utilizará una función de activación lineal para generar valores numéricos.
...
# define decoder
d = Dense(n_inputs*2)(bottleneck)
d = BatchNormalization()(d)
d = ReLU()(d)
# output layer
output = Dense(n_inputs, activation='linear')(d)
# define autoencoder model
model = Model(inputs=visible, outputs=output)
# compile autoencoder model
model.compile(optimizer='adam', loss='mse')
El modelo se ajustará utilizando la versión eficiente de Adam del descenso de gradiente estocástico y minimiza el error cuadrático medio, dado que la reconstrucción es un tipo de problema de regresión de múltiples salidas.
...
# compile autoencoder model
model.compile(optimizer='adam', loss='mse')
Podemos trazar las capas en el modelo del codificador automático para tener una idea de cómo fluyen los datos a través del modelo.
...
# plot the autoencoder
plot_model(model, 'autoencoder.png', show_shapes=True)
La siguiente imagen muestra un gráfico del codificador automático.
A continuación, podemos entrenar el modelo para reproducir la entrada y realizar un seguimiento del rendimiento del modelo en el conjunto de pruebas de reserva. El modelo está entrenado para 400 épocas y un tamaño de lote de 16 ejemplos.
...
# fit the autoencoder model to reconstruct input
history = model.fit(X_train, X_train, epochs=400, batch_size=16, verbose=2, validation_data=(X_test,X_test))
Después del entrenamiento, podemos trazar las curvas de aprendizaje para el tren y los conjuntos de prueba para confirmar que el modelo aprendió bien el problema de reconstrucción.
...
# plot loss
pyplot.plot(history.history['loss'], label='train')
pyplot.plot(history.history['val_loss'], label='test')
pyplot.legend()
pyplot.show()
Finalmente, podemos guardar el modelo del codificador para usarlo más adelante, si lo desea.
...
# define an encoder model (without the decoder)
encoder = Model(inputs=visible, outputs=bottleneck)
plot_model(encoder, 'encoder.png', show_shapes=True)
# save the encoder to file
encoder.save('encoder.h5')
Como parte de guardar el codificador, también trazaremos el modelo para tener una idea de la forma de la salida de la capa del cuello de botella, p. un vector de 100 elementos.
A continuación se proporciona un ejemplo de este gráfico.
Al unir todo esto, a continuación se enumera el ejemplo completo de un codificador automático para reconstruir los datos de entrada para un conjunto de datos de regresión sin ninguna compresión en la capa de cuello de botella.
# train autoencoder for regression with no compression in the bottleneck layer
from sklearn.datasets import make_regression
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import ReLU
from tensorflow.keras.layers import BatchNormalization
from tensorflow.keras.utils import plot_model
from matplotlib import pyplot
# define dataset
X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)
# number of input columns
n_inputs = X.shape[1]
# split into train test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# scale data
t = MinMaxScaler()
t.fit(X_train)
X_train = t.transform(X_train)
X_test = t.transform(X_test)
# define encoder
visible = Input(shape=(n_inputs,))
e = Dense(n_inputs*2)(visible)
e = BatchNormalization()(e)
e = ReLU()(e)
# define bottleneck
n_bottleneck = n_inputs
bottleneck = Dense(n_bottleneck)(e)
# define decoder
d = Dense(n_inputs*2)(bottleneck)
d = BatchNormalization()(d)
d = ReLU()(d)
# output layer
output = Dense(n_inputs, activation='linear')(d)
# define autoencoder model
model = Model(inputs=visible, outputs=output)
# compile autoencoder model
model.compile(optimizer='adam', loss='mse')
# plot the autoencoder
plot_model(model, 'autoencoder.png', show_shapes=True)
# fit the autoencoder model to reconstruct input
history = model.fit(X_train, X_train, epochs=400, batch_size=16, verbose=2, validation_data=(X_test,X_test))
# plot loss
pyplot.plot(history.history['loss'], label='train')
pyplot.plot(history.history['val_loss'], label='test')
pyplot.legend()
pyplot.show()
# define an encoder model (without the decoder)
encoder = Model(inputs=visible, outputs=bottleneck)
plot_model(encoder, 'encoder.png', show_shapes=True)
# save the encoder to file
encoder.save('encoder.h5')
La ejecución del ejemplo se ajusta al modelo e informa la pérdida en el tren y los equipos de prueba a lo largo del camino.
Nota: si tiene problemas para crear los gráficos del modelo, puede comentar la importación y llamar a la función plot_model().
Nota: Sus resultados pueden variar dada la naturaleza estocástica del algoritmo o procedimiento de evaluación, o diferencias en la precisión numérica. Considere ejecutar el ejemplo varias veces y comparar el resultado promedio.
En este caso, vemos que la pérdida disminuye pero no llega a cero (como podríamos haber esperado) sin compresión en la capa del cuello de botella. Quizás sea necesario ajustar más la arquitectura del modelo o aprender hiperparámetros.
...
Epoch 393/400
42/42 - 0s - loss: 0.0025 - val_loss: 0.0024
Epoch 394/400
42/42 - 0s - loss: 0.0025 - val_loss: 0.0021
Epoch 395/400
42/42 - 0s - loss: 0.0023 - val_loss: 0.0021
Epoch 396/400
42/42 - 0s - loss: 0.0025 - val_loss: 0.0023
Epoch 397/400
42/42 - 0s - loss: 0.0024 - val_loss: 0.0022
Epoch 398/400
42/42 - 0s - loss: 0.0025 - val_loss: 0.0021
Epoch 399/400
42/42 - 0s - loss: 0.0026 - val_loss: 0.0022
Epoch 400/400
42/42 - 0s - loss: 0.0025 - val_loss: 0.0024
Se crea un gráfico de las curvas de aprendizaje que muestra que el modelo logra un buen ajuste al reconstruir la entrada, que se mantiene estable durante todo el entrenamiento, sin sobreajuste.
Hasta ahora, todo bien. Sabemos cómo desarrollar un codificador automático sin compresión.
El codificador entrenado se guarda en el archivo “encoder.h5” que podemos cargar y usar más adelante.
A continuación, exploremos cómo podríamos utilizar el modelo de codificador entrenado.
Autocodificador como preparación de datos
En esta sección, usaremos el modelo de codificador entrenado del modelo de codificador automático para comprimir datos de entrada y entrenar un modelo predictivo diferente.
Primero, establezcamos una línea de base en el desempeño de este problema. Esto es importante ya que si la codificación comprimida no mejora el rendimiento de un modelo, entonces la codificación comprimida no agrega valor al proyecto y no debe usarse.
Podemos entrenar un modelo de regresión de vector de soporte (SVR) en el conjunto de datos de entrenamiento directamente y evaluar el rendimiento del modelo en el conjunto de prueba de reserva.
Como es una buena práctica, escalaremos tanto las variables de entrada como la variable objetivo antes de ajustar y evaluar el modelo.
El ejemplo completo se enumera a continuación.
# baseline in performance with support vector regression model
from sklearn.datasets import make_regression
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.svm import SVR
from sklearn.metrics import mean_absolute_error
# define dataset
X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)
# split into train test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# reshape target variables so that we can transform them
y_train = y_train.reshape((len(y_train), 1))
y_test = y_test.reshape((len(y_test), 1))
# scale input data
trans_in = MinMaxScaler()
trans_in.fit(X_train)
X_train = trans_in.transform(X_train)
X_test = trans_in.transform(X_test)
# scale output data
trans_out = MinMaxScaler()
trans_out.fit(y_train)
y_train = trans_out.transform(y_train)
y_test = trans_out.transform(y_test)
# define model
model = SVR()
# fit model on the training dataset
model.fit(X_train, y_train)
# make prediction on test set
yhat = model.predict(X_test)
# invert transforms so we can calculate errors
yhat = yhat.reshape((len(yhat), 1))
yhat = trans_out.inverse_transform(yhat)
y_test = trans_out.inverse_transform(y_test)
# calculate error
score = mean_absolute_error(y_test, yhat)
print(score)
La ejecución del ejemplo ajusta un modelo SVR en el conjunto de datos de entrenamiento y lo evalúa en el conjunto de prueba.
Nota: Sus resultados pueden variar dada la naturaleza estocástica del algoritmo o procedimiento de evaluación, o diferencias en la precisión numérica. Considere ejecutar el ejemplo varias veces y comparar el resultado promedio.
En este caso, podemos ver que el modelo logra un error absoluto medio (MAE) de aproximadamente 89.
Esperamos y esperamos que un modelo SVR se ajuste a una versión codificada de la entrada para lograr un error menor para que la codificación se considere útil.
89.51082036130629
Podemos actualizar el ejemplo para codificar primero los datos utilizando el modelo de codificador entrenado en la sección anterior.
Primero, podemos cargar el modelo de codificador entrenado desde el archivo.
...
# load the model from file
encoder = load_model('encoder.h5')
Luego podemos usar el codificador para transformar los datos de entrada sin procesar (por ejemplo, 100 columnas) en vectores de cuello de botella (por ejemplo, vectores de 100 elementos).
Este proceso se puede aplicar a los conjuntos de datos de entrenamiento y prueba.
...
# encode the train data
X_train_encode = encoder.predict(X_train)
# encode the test data
X_test_encode = encoder.predict(X_test)
Luego podemos usar estos datos codificados para entrenar y evaluar el modelo SVR, como antes.
...
# define model
model = SVR()
# fit model on the training dataset
model.fit(X_train_encode, y_train)
# make prediction on test set
yhat = model.predict(X_test_encode)
Uniendo esto, el ejemplo completo se enumera a continuación.
# support vector regression performance with encoded input
from sklearn.datasets import make_regression
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.svm import SVR
from sklearn.metrics import mean_absolute_error
from tensorflow.keras.models import load_model
# define dataset
X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)
# split into train test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
# reshape target variables so that we can transform them
y_train = y_train.reshape((len(y_train), 1))
y_test = y_test.reshape((len(y_test), 1))
# scale input data
trans_in = MinMaxScaler()
trans_in.fit(X_train)
X_train = trans_in.transform(X_train)
X_test = trans_in.transform(X_test)
# scale output data
trans_out = MinMaxScaler()
trans_out.fit(y_train)
y_train = trans_out.transform(y_train)
y_test = trans_out.transform(y_test)
# load the model from file
encoder = load_model('encoder.h5')
# encode the train data
X_train_encode = encoder.predict(X_train)
# encode the test data
X_test_encode = encoder.predict(X_test)
# define model
model = SVR()
# fit model on the training dataset
model.fit(X_train_encode, y_train)
# make prediction on test set
yhat = model.predict(X_test_encode)
# invert transforms so we can calculate errors
yhat = yhat.reshape((len(yhat), 1))
yhat = trans_out.inverse_transform(yhat)
y_test = trans_out.inverse_transform(y_test)
# calculate error
score = mean_absolute_error(y_test, yhat)
print(score)
Al ejecutar el ejemplo, primero se codifica el conjunto de datos utilizando el codificador, luego se ajusta un modelo SVR en el conjunto de datos de entrenamiento y se evalúa en el conjunto de prueba.
Nota: Sus resultados pueden variar dada la naturaleza estocástica del algoritmo o procedimiento de evaluación, o diferencias en la precisión numérica. Considere ejecutar el ejemplo varias veces y comparar el resultado promedio.
En este caso, podemos ver que el modelo alcanza un MAE de aproximadamente 69.
Este es un MAE mejor que el mismo modelo evaluado en el conjunto de datos sin procesar, lo que sugiere que la codificación es útil para nuestro modelo y arnés de prueba elegidos.
69.45890939600503
Lectura adicional
Esta sección proporciona más recursos sobre el tema si desea profundizar más.
Tutoriales
- Una suave introducción a los codificadores automáticos LSTM
- Cómo utilizar la API funcional de Keras para el aprendizaje profundo
- Tutorial de TensorFlow 2: Comience a aprender en profundidad con tf.keras
Libros
- Aprendizaje profundo, 2016.
API
- API sklearn.datasets.make_regression.
- API sklearn.model_selection.train_test_split.
Artículos
- Codificador automático, Wikipedia.
Resumen
En este tutorial, descubrió cómo desarrollar y evaluar un codificador automático para el modelado predictivo de regresión.
Específicamente, aprendiste:
- Un codificador automático es un modelo de red neuronal que se puede utilizar para aprender una representación comprimida de datos sin procesar.
- Cómo entrenar un modelo de codificador automático en un conjunto de datos de entrenamiento y guardar solo la parte del codificador del modelo.
- Cómo utilizar el codificador como paso de preparación de datos al entrenar un modelo de aprendizaje automático.
¿Tiene alguna pregunta?
Haga sus preguntas en los comentarios a continuación y haré todo lo posible para responderlas.