Modelos para datos estructurados
Creando modelos para datos estructurados usando FastAI.
En este notebook se muestra cómo crear un modelo de clasificación para un dataset estructurado que contiene características categóricas usando una red neuronal. Para ello usaremos la librería FastAI.
Aunque para esta práctica no es necesario el uso de GPU, las pruebas serán más rápidas si tienes esta opción activada.
!pip install fastai -Uq
Cargamos a continuación las librerías que necesitaremos en esta práctica que son la parte de datos estructurados de la librería fastAI y la librería pandas.
from fastai.tabular.all import *
import pandas as pd
import random
Dataset
Para este ejemplo vamos a usar el Adult Data Set. Con este dataset se pretende ser capaz de predecir si una persona cobra más de 50000 dolares al año a partir de las siguientes características:
columns = ['age','workclass','fnlwgt','education',
'education-num','marital-status',
'occupation', 'relationship', 'race',
'sex','capital-gain','capital-loss',
'hours-per-week','native-country','income']
Vamos a descargar el dataset usando los siguientes comandos. Debemos descargar tanto el conjunto de entrenamiento como el de test.
!wget https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data -O train.csv
!wget https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.test -O test.csv
Si inspeccionais el fichero de test veremos que la primera línea no proporciona información útil, y además los valores de la columna del salario incluyen un punto. Los siguientes comandos se encargan de eliminar la primera línea del fichero y de eliminar los puntos.
!sed '1d' test.csv > tmpfile; mv tmpfile test.csv
!sed 's/\.//' test.csv > tmpfile; mv tmpfile test.csv
df_train = pd.read_csv('train.csv',header=None,names=columns)
df_test = pd.read_csv('test.csv',header=None,names=columns)
Para crear un modelo con datos estructurados en FastAI debemos:
- Indicar la columna que queremos predecir, es decir la variable dependiente.
- Las transformaciones que queremos aplicar a nuestro dataset.
- Las características que son categóricas y continuas.
Nuestra variable dependiente va a ser el salario:
dep_var = 'income'
Las transformaciones que vamos a aplicar nuestro dataset son:
- Categorizar las variables categoricas de manera que se use un embedding.
- Reemplazar aquellos valores que faltan en el dataset por la media del resto de valores de ese descriptor.
- Normalizar los datos.
Esto se consigue definiendo la siguiente lista de transformaciones.
procs = [Categorify, FillMissing,Normalize]
Por último debemos indicar qué variables son continuas (números) o categóricas. De esto se encarga automáticamente la función cont_cat_split
.
cont,cat = cont_cat_split(df_train, 1, dep_var=dep_var)
Podemos ver a hora que realmente las variables continuas y categóricas han sido separadas de forma correcta.
cat
cont
Entrenando un modelo
El proceso para entrenar un modelo es el mismo que hemos visto para los modelos de clasificación de imágenes y podemos usar toda la funcionalidad vista hasta ahora. Comenzamos definiendo un dataloader usando el método estático from_df
de la clase TabularDataLoaders
. Como siempre debemos definir un conjunto de validación, para ello debemos indicar los índices del dataset que tomaremos como conjunto de validación. En este caso vamos a tomar un 20% de los índices de manera aleatoria.
dlsTrain = TabularDataLoaders.from_df(df_train,'.',procs=procs,
cat_names=cat,cont_names=cont,y_names='income',
valid_idx=random.sample(range(0,len(df_train)),int(len(df_train)*0.2)),bs=64)
Ahora definimos nuestro learner que va a ser una red neuronal, a la cual le tenemos que indicar el número de capas y neuronas con las que queremos trabajar. En este caso usaremos una red neuronal con dos capas ocultas la primera con 500 neuronas y la segunda con 250.
learn = tabular_learner(dlsTrain, layers=[500,250],metrics=[accuracy])
Podemos ver la estructura del modelo que acabamos de construir.
learn.model
Podemos ver que tenemos un TabularModel
con una serie de embeddings. La siguiente celda nos sirve para ver qué es lo que hace un TabularModel
.
??TabularModel
Como hemos dicho tenemos toda la batería de funciones que ya conocemos, así que vamos a buscar el learning rate más adecuado.
learn.lr_find()
Pasamos ahora a entrenar nuestro modelo.
learn.fit(10, 1e-3)
Evaluación
Hemos logrado una accuracy del 84.50 en el conjunto de validación, pero nos interesa ver el rendimiento de nuestro modelo en el conjunto de test. Para ello debemos primero combinar el conjunto de train y el conjunto de test para crear un dataloader en el que el conjunto de validación esté formado por todos los elementos del conjunto de test.
dfAll = pd.concat([df_train,df_test])
dlsTest = TabularDataLoaders.from_df(dfAll,'.',procs=procs,
cat_names=cat,cont_names=cont,y_names='income',
valid_idx=list(range(len(df_train)+1,len(dfAll))),bs=64)
Cambiamos ahora el dataloader del learner.
learn.dls=dlsTest
Y procedemos a obtener la accuracy de nuestro modelo en el conjunto de test.
learn.validate()
También podemos usar nuestro modelo para hacer predicciones concretas con un ejemplo usando la función predict
esto nos devolverá tres elementos: los datos sobre los que se ha realizado la predicción, la clase, y las probabilidades.
learn.predict(df_test.iloc[0][:-1])