Blog
Proyecto: Regresión del precio de la vivienda en Londres
- Publicado por: Rafael Fernandez
- Categoría: Deep Learning
-En este tutorial descubrirá cómo desarrollar y evaluar modelos de redes neuronales usando Keras para un problema de regresión.
-Cómo cargar un conjunto de datos CSV y ponerlo a disposición de Keras.
-Cómo crear un modelo de red neuronal con Keras para un problema de regresión.
-Cómo usar scikit-learn con Keras para evaluar modelos usando validación cruzada.
-Cómo realizar la preparación de datos para mejorar la habilidad con los modelos Keras.
-Cómo sintonizar la topología de red de los modelos con Keras.
Conjunto de datos de precios de Pisos en Londres
El problema que veremos en este tutorial es el conjunto de datos del precio de la vivienda en Londres. El conjunto de datos describe propiedades de casas en los suburbios de Londres y queremos modelar el precio de casas en estos barrios en miles de euros. Como tal, esto es un modelo predictivo de regresión. Hay 13 variables de entrada que describen las propiedades de un determinado barrio de Londres. La lista completa de atributos en este conjunto de datos es la siguiente:
- CRIM: tasa de criminalidad per cápita.
- ZN: proporción de terreno residencial dividido en zonas para lotes de más de 25,000 pies cuadrados.
- INDUS: proporción de negocios no minoristas.
- CHAS: Variable ficticia del río (= 1 si el tramo limita con el río; 0 en caso contrario).
- NOX: concentración de óxidos nítricos (10 ppm).
- RM: número medio de habitaciones por vivienda.
- EDAD: proporción de viviendas ocupadas por sus propietarios construidas antes de 1940.
- DIS: distancias ponderadas a los centros de empleo de Londres.
- RAD: índice de accesibilidad a carreteras radiales.
- IMPUESTO: tasa del impuesto sobre el valor total de la propiedad por cada 10,000 euros.
- PTRATIO: número de alumnos por docente y ciudad.
- B: 1000(B 0:63) 2 donde B es la proporción de inmigrantes.
- LSTAT: % de menor estatus de la población.
- MEDV: Valor medio de las viviendas ocupadas por sus propietarios en miles de euros.
Este es un problema bien estudiado en Machine Learning y es conveniente trabajar con él porque todos los atributos de entrada y salida son numéricos y hay 500 instancias con las que trabajar. A continuación se presenta una muestra de las primeras 4 filas del conjunto de datos:
0.02731 0.00 7.070 0 0.4690 6.4210 78.90 4.9671 2 242.0 17.80 396.90 9.14 21.60 0.02729 0.00 7.070 0 0.4690 7.1850 61.10 4.9671 2 242.0 17.80 392.83 4.03 34.70 0.03237 0.00 2.180 0 0.4580 6.9980 45.80 6.0622 3 222.0 18.70 394.63 2.94 33.40 0.06905 0.00 2.180 0 0.4580 7.1470 54.20 6.0622 3 222.0 18.70 396.90 5.33 36.20
El conjunto de datos está disponible aquí. Un rendimiento razonable para los modelos evaluados utilizando Mean Squared Error (MSE) son de alrededor de 20 000 euros cuadrados (o 4.500 euros si usted toma la raíz cuadrada). Este es un buen objetivo para apuntar con nuestro modelo de red neuronal.
Desarrollar un Modelo de Red Neuronal de Línea de Base
En esta sección crearemos un modelo básico de red neuronal para el problema de regresión. Vamos a importar todas las funciones y objetos que necesitaremos para este tutorial.
import numpy from pandas import read_csv from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasRegressor from sklearn.model_selection import cross_val_score from sklearn.model_selection import KFold from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline
Ahora podemos cargar nuestro conjunto de datos. Podemos cargar esto fácilmente usando la librería de Pandas. Entonces podemos dividir la entrada (X) y los atributos de salida (Y) para que sean más fáciles de modelar con Keras y scikit-learn.
# cargamos los datos dataframe = read_csv("housing.csv", delim_whitespace=True, header=None) dataset = dataframe.values # dividimos los datos entre las entradas y las salidas X = dataset[:,0:13] Y = dataset[:,13]
Podemos crear modelos Keras y evaluarlos con scikit-learn usando un práctico envoltorio de objetos proporcionados por la biblioteca Keras. Esto es deseable, porque scikit-learn sobresale en la evaluación y nos permitirá utilizar potentes esquemas de preparación de datos y evaluación de modelos con muy pocas líneas de código. La clase de envoltura Keras requiere una función como argumento. Esta función que debemos definir es responsable de crear el modelo de red neuronal a evaluar.
A continuación se detalla la función para crear el modelo a evaluar. Es un simple modelo que tiene una sola capa oculta completamente conectada con el mismo número de neuronas que la entrada (13). La red utiliza buenas prácticas como la función de activación de rectier para la capa oculta. No se utiliza ninguna función de activación para la capa de salida porque es una regresión y estamos interesados en predecir valores numéricos directamente sin transformación. Se utiliza el algoritmo de optimización de ADAM y una función de pérdida de error media al cuadrado optimizada. Esta será la misma métrica que usaremos para evaluar el desempeño del modelo. Es una métrica deseable porque al tomar la raíz cuadrada de un valor de error nos da un valor de resultado que podemos entender directamente en el contexto del problema con las unidades en miles de euros.
# define el modelo base def baseline_model(): # crea el modelo model = Sequential() model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu')) model.add(Dense(1, kernel_initializer='normal')) # Compila el modelo model.compile(loss='mean_squared_error', optimizer='adam') return model
El objeto envoltorio de Keras para usar en scikit-learn es como un estimador de regresión y se llama KerasRegressor. Creamos una instancia y le pasamos tanto el nombre de la función para crear el modelo de red neuronal como algunos parámetros para pasar a la función fit() del modelo más tarde, como el número de epoch y el batch_size. Ambos están configurados con valores predeterminados razonables. También inicializamos el generador de números aleatorios con una semilla aleatoria constante, un proceso que repetiremos para cada modelo evaluado en este tutorial. Esto es para asegurar que comparamos modelos consistentemente y que los resultados sean reproducibles.
# semilla random seed = 7 numpy.random.seed(seed) # evaluamos el modelo estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0)
El paso fundamental es evaluar este modelo de línea de base. Usaremos una validación cruzada 10 veces para evaluar el modelo.
kfold = KFold(n_splits=10, random_state=seed) results = cross_val_score(estimator, X, Y, cv=kfold) print("Baseline: %.2f (%.2f) MSE" % (results.mean(), results.std()))
El código completo de este post sobre la regresión con redes neuronales es:
# Regresion con redes neuronales import numpy from pandas import read_csv from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasRegressor from sklearn.model_selection import cross_val_score from sklearn.model_selection import KFold # cargamos los datos dataframe = read_csv("viviendalondres.csv", delim_whitespace=True, header=None) dataset = dataframe.values # dividimos los datos entre los inputs y variables X = dataset[:,0:13] Y = dataset[:,13] # se define el modelo base def baseline_model(): # creamos el modelo model = Sequential() model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu')) model.add(Dense(1, kernel_initializer='normal')) # Compilamos el modelo model.compile(loss='mean_squared_error', optimizer='adam') return model # semilla de aletoriedad seed = 7 numpy.random.seed(seed) # evalua el modelo estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0) kfold = KFold(n_splits=10, random_state=seed) results = cross_val_score(estimator, X, Y, cv=kfold) print("Baseline: %.2f (%.2f) MSE" % (results.mean(), results.std()))
La ejecución de este código nos da una estimación del rendimiento del modelo en el problema de los datos no vistos. El resultado reporta el error promedio al cuadrado incluyendo el promedio y la desviación estándar (varianza promedio) a través de los 10 pliegues de la evaluación de validación cruzada.
Baseline: -27.63 (16.36) MSE
Elevar el rendimiento estandarizando del conjunto de datos
Una preocupación importante con el conjunto de datos del precio de la vivienda de Londres es que todos los atributos de entrada varían en sus escalas porque miden cantidades diferentes. Casi siempre es una buena práctica preparar sus datos antes de modelarlos utilizando un modelo de red neuronal. Continuando desde el modelo Baseline, podemos reevaluar el mismo modelo utilizando una versión estandarizada del conjunto de datos de entrada.
Podemos usar el Pipeline de scikit-learn para llevar a cabo la estandarización del proyecto durante el proceso de evaluación del modelo, dentro de cada pliegue de la validación cruzada. Esto asegura que no hay fugas de datos de cada pliegue de validación cruzada del conjunto de pruebas en los datos de formación. El código a continuación crea un Pipeline de scikit-learn que primero estandariza el conjunto de datos y luego crea y evalúa el modelo de baseline de la red neuronal.
# Regresion ejemplo londresvivienda Dataset: Standardized import numpy from pandas import read_csv from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasRegressor from sklearn.model_selection import cross_val_score from sklearn.model_selection import KFold from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline # cargamos los datos dataframe = read_csv("viviendalondres.csv", delim_whitespace=True, header=None) dataset = dataframe.values # dividimos entre entradas y salidas X = dataset[:,0:13] Y = dataset[:,13] # se define el modelo base def baseline_model(): # se crea el modelo model = Sequential() model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu')) model.add(Dense(1, kernel_initializer='normal')) # se Compila el modelo model.compile(loss='mean_squared_error', optimizer='adam') return model # semilla aleatoria seed = 7 numpy.random.seed(seed) # se evalua el modelo con el standardized dataset estimators = [] estimators.append(('standardize', StandardScaler())) estimators.append(('mlp', KerasRegressor(build_fn=baseline_model, epochs=50, batch_size=5, verbose=0))) pipeline = Pipeline(estimators) kfold = KFold(n_splits=10, random_state=seed) results = cross_val_score(pipeline, X, Y, cv=kfold) print("Standardized: %.2f (%.2f) MSE" % (results.mean(), results.std()))
La ejecución del ejemplo proporciona un rendimiento mejorado sobre el modelo de línea de base sin datos estandarizados, eliminando el error.
Standardized: -27.79 (25.98) MSE
Otra ampliación de esta sección consistiría en aplicar de manera similar un reajuste de la escala a la salida como normalizarlo al rango de 0 a 1 y usar una activación Sigmoidea o similar en la capa de salida para reducir las predicciones de salida al mismo rango.
Afinamos la topología de la red neuronal
Hay muchas cosas que pueden ser optimizadas para un modelo de red neuronal. Tal vez el punto de mayor apalancamiento es la estructura de la propia red, incluyendo el número de capas y el número de neuronas en cada capa. En esta sección evaluaremos dos redes adicionales para mejorar aún más el rendimiento del modelo. Nos fijaremos tanto en un una topología de red más profunda y más amplia.
Evaluar una topología de red más profunda
Una forma de mejorar el rendimiento de una red neuronal es añadir más capas. Esto podría permitir que el modelo extraiga y recombine características de orden superior incrustadas en los datos. En este evaluaremos la posibilidad de añadir una capa oculta más al modelo. Esto es tan fácil como como definir una nueva función que creará este modelo más profundo, copiado de nuestro modelo de línea de base más arriba. Podemos entonces insertar una nueva línea después de la primera capa oculta. En este caso con aproximadamente la mitad del número de neuronas. Nuestra topología de red ahora parece:
13 entradas –> [13 –> 6]] –> 1 salida
Podemos evaluar esta topología de red de la misma manera que arriba, al mismo tiempo que utilizamos la estandarización del conjunto de datos que se ha demostrado que mejora el rendimiento.
# Regresion ejemplo con vivienda londres Dataset: Standardized y topologia mas profunda import numpy from pandas import read_csv from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasRegressor from sklearn.model_selection import cross_val_score from sklearn.model_selection import KFold from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline # cargamos los datos dataframe = read_csv("viviendalondres.csv", delim_whitespace=True, header=None) dataset = dataframe.values # dividimos los datos de entrada (X) y los de salida (Y) X = dataset[:,0:13] Y = dataset[:,13] # se define el modelo def larger_model(): # creamos el modelo model = Sequential() model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu')) model.add(Dense(6, kernel_initializer='normal', activation='relu')) model.add(Dense(1, kernel_initializer='normal')) # se Compila el modelo model.compile(loss='mean_squared_error', optimizer='adam') return model # semilla aleatoria seed = 7 numpy.random.seed(seed) # se evalua el modelo con standardized estimators = [] estimators.append(('standardize', StandardScaler())) estimators.append(('mlp', KerasRegressor(build_fn=larger_model, epochs=50, batch_size=5, verbose=0))) pipeline = Pipeline(estimators) kfold = KFold(n_splits=10, random_state=seed) results = cross_val_score(pipeline, X, Y, cv=kfold) print("mas profunda: %.2f (%.2f) MSE" % (results.mean(), results.std()))
La ejecución de este modelo muestra una mejora adicional en el rendimiento de la MSE.
mas profunda: -23.26 (27.04) MSE
Evaluar una topología de red más amplia
Otro enfoque para aumentar la capacidad de representación del modelo es crear una red más amplia. En esta sección evaluamos la posibilidad de mantener una arquitectura de red poco profunda y casi duplicar el número de neuronas en una capa oculta. Una vez más, todo lo que tenemos que hacer es definir una nueva función que crea nuestro modelo de red neuronal. En este sentido, hemos aumentado el número en la capa oculta en comparación con el modelo base de 13 a 20. La topología para nuestra red más amplia puede resumirse de la siguiente manera:
13 entradas –> [20]–> 1 salida
Ahora vamos a evaluar una topología de red mas amplia con el siguiente código:
# Regresion ejemplo con viviendalondres Dataset: Standardized y red mas amplia import numpy from pandas import read_csv from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasRegressor from sklearn.model_selection import cross_val_score from sklearn.model_selection import KFold from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline # cargamos los datos dataframe = read_csv("viviendalondres.csv", delim_whitespace=True, header=None) dataset = dataframe.values # dividimos entre las entradas (X) y las salidas (Y) X = dataset[:,0:13] Y = dataset[:,13] # define tu modelo mas amplio def wider_model(): # crea el modelo model = Sequential() model.add(Dense(20, input_dim=13, kernel_initializer='normal', activation='relu')) model.add(Dense(1, kernel_initializer='normal')) # Compila el modelo model.compile(loss='mean_squared_error', optimizer='adam') return model # semilla aleatoria seed = 7 numpy.random.seed(seed) # evalua el modelo estimators = [] estimators.append(('standardize', StandardScaler())) estimators.append(('mlp', KerasRegressor(build_fn=wider_model, epochs=100, batch_size=5, verbose=0))) pipeline = Pipeline(estimators) kfold = KFold(n_splits=10, random_state=seed) results = cross_val_score(pipeline, X, Y, cv=kfold) print("Red mas amplia: %.2f (%.2f) MSE" % (results.mean(), results.std()))
La construcción del modelo no ve una caída adicional en el error cerca de 21 mil euros cuadrados. Este no es un mal resultado para este problema.
Red mas amplia: -22.05 (22.77) MSE
Habría sido difícil adivinar que una red más amplia superaría a una red más profunda en este problema. Los resultados demuestran la importancia de las pruebas ensayo y error cuando se trata de desarrollar modelos de redes neuronales.
Resumen del post de Regresión con redes Neuronales
En esta lección descubrió la biblioteca de aprendizaje profundo de Keras para modelar problemas de regresión. A través de este tutorial usted aprendió a desarrollar y evaluar modelos de redes neuronales, incluyendo:
- Cómo cargar datos y desarrollar un modelo de línea de base.
- Cómo mejorar el rendimiento utilizando técnicas de preparación de datos como la estandarización.
- Cómo diseñar y evaluar redes con diferentes topologías sobre un problema.
➡ Aprende mas de Deep Learning con nuestro curso: