Tensorflow 2.0: solución de problemas de clasificación y regresión

T

Después de mucha publicidad, Google finalmente lanzó TensorFlow 2.0 que es la última versión de la plataforma insignia de aprendizaje profundo de Google. Se han introducido muchas funciones tan esperadas en TensorFlow 2.0. Este artículo cubre muy brevemente cómo puedes desarrollar modelos simples de clasificación y regresión con TensorFlow 2.0.

Clasificación con Tensorflow 2.0

Si alguna vez ha trabajado con la biblioteca de Keras, está de enhorabuena. TensorFlow 2.0 ahora usa la API de Keras como su biblioteca predeterminada para entrenar modelos de clasificación y regresión. Antes de TensorFlow 2.0, una de las principales críticas a las que se enfrentaban las versiones anteriores de TensorFlow se debía a la complejidad de la creación del modelo. Anteriormente, necesita unir gráficos, sesiones y marcadores de posición para crear incluso un modelo de regresión logística simple. Con TensorFlow 2.0, la creación de modelos de clasificación y regresión se ha convertido en pan comido.

Entonces, sin más preámbulos, desarrollemos un modelo de clasificación con TensorFlow.

El conjunto de datos

El conjunto de datos para el ejemplo de clasificación se puede descargar libremente de este enlace. Descarga el archivo en formato CSV. Si abre el archivo CSV descargado, verá que el archivo no contiene ningún encabezado. El detalle de las columnas está disponible en Repositorio de Machine Learning de UCI. Le recomendaré que lea la información del conjunto de datos en detalle desde el enlace de descarga. Resumiré brevemente el conjunto de datos en esta sección.

El conjunto de datos consta básicamente de 7 columnas:

  • precio (el precio de compra del coche)
  • maint (el costo de mantenimiento)
  • puertas (número de puertas)
  • personas (la capacidad de asientos)
  • lug_capacity (la capacidad del equipaje)
  • seguridad (que tan seguro es el auto)
  • salida (el estado del coche)

Dadas las primeras 6 columnas, la tarea es predecir el valor de la séptima columna, es decir, la salida. La columna de salida puede tener uno de los tres valores, es decir, “unacc” (inaceptable), “acc” (aceptable), bueno y muy bueno.

Importación de bibliotecas

Antes de importar el conjunto de datos a nuestra aplicación, necesitamos importar las bibliotecas necesarias.

import pandas as pd
import numpy as np
import tensorflow as tf

import matplotlib.pyplot as plt
%matplotlib inline

import seaborn as sns
sns.set(style="darkgrid")

Antes de continuar, quiero que se asegure de tener la última versión de TensorFlow, es decir, TensorFlow 2.0. Puedes verificar tu versión de TensorFlow con el siguiente comando:

print(tf.__version__)

Si no tiene TensorFlow 2.0 instalado, puede actualizar a la última versión mediante el siguiente comando:

$ pip install --upgrade tensorflow

Importar el conjunto de datos

El siguiente script importa el conjunto de datos. Cambie la ruta a su archivo de datos CSV según.

cols = ['price', 'maint', 'doors', 'persons', 'lug_capacity', 'safety','output']
cars = pd.read_csv(r'/content/drive/My Drive/datasets/car_dataset.csv', names=cols, header=None)

Dado que el archivo CSV no contiene encabezados de columna de forma predeterminada, pasamos una lista de encabezados de columna al pd.read_csv() método.

Veamos ahora las primeras 5 filas del conjunto de datos a través de la head() método.

cars.head()

Salida:

Puede ver las 7 columnas en el conjunto de datos.

Análisis y preprocesamiento de datos

Analicemos brevemente el conjunto de datos trazando un gráfico circular que muestre la distribución de la salida. La siguiente secuencia de comandos aumenta el tamaño de trazado predeterminado.

plot_size = plt.rcParams["figure.figsize"]
plot_size [0] = 8
plot_size [1] = 6
plt.rcParams["figure.figsize"] = plot_size

Y el siguiente script traza el gráfico circular que muestra la distribución de salida.

cars.output.value_counts().plot(kind='pie', autopct="%0.05f%%", colors=['lightblue', 'lightgreen', 'orange', 'pink'], explode=(0.05, 0.05, 0.05,0.05))

Salida:

El resultado muestra que la mayoría de los automóviles (70%) están en condiciones inaceptables mientras que el 20% de los automóviles están en condiciones aceptables. La relación de coches en buen y muy buen estado es muy baja.

Todas las columnas de nuestro conjunto de datos son categóricas. El aprendizaje profundo se basa en algoritmos estadísticos y los algoritmos estadísticos funcionan con números. Por lo tanto, necesitamos convertir la información categórica en columnas numéricas. Hay varios enfoques para hacer eso, pero uno de los enfoques más comunes es la codificación one-hot. En la codificación one-hot, para cada valor único en la columna categórica, se crea una nueva columna. Para las filas de la columna real donde existía el valor único, se agrega un 1 a la fila correspondiente de la columna creada para ese valor en particular. Esto puede parecer complejo, pero el siguiente ejemplo lo aclarará.

El siguiente script convierte columnas categóricas en columnas numéricas:

price = pd.get_dummies(cars.price, prefix='price')
maint = pd.get_dummies(cars.maint, prefix='maint')

doors = pd.get_dummies(cars.doors, prefix='doors')
persons = pd.get_dummies(cars.persons, prefix='persons')

lug_capacity = pd.get_dummies(cars.lug_capacity, prefix='lug_capacity')
safety = pd.get_dummies(cars.safety, prefix='safety')

labels = pd.get_dummies(cars.output, prefix='condition')

Para crear nuestro conjunto de características, podemos fusionar las primeras seis columnas horizontalmente:

X = pd.concat([price, maint, doors, persons, lug_capacity, safety] , axis=1)

Veamos cómo se ve nuestra columna de etiquetas ahora:

labels.head()

Salida:

La columna de etiquetas es básicamente una versión codificada en caliente de la columna de salida que teníamos en nuestro conjunto de datos. La columna de salida tenía cuatro valores únicos: unacc, acc, good y very good. En el conjunto de datos de etiquetas codificadas en caliente, puede ver cuatro columnas, una para cada uno de los valores únicos en la columna de salida. Puede ver 1 en la columna para el valor único que existía originalmente en esa fila. Por ejemplo, en las primeras cinco filas de la columna de salida, el valor de la columna era unacc. En la columna de etiquetas, puede ver 1 en las primeras cinco filas de la columna condition_unacc.

Ahora convierta nuestras etiquetas en una matriz numpy, ya que los modelos de aprendizaje profundo en TensorFlow aceptan matriz numpy como entrada.

y = labels.values

El último paso antes de que podamos entrenar nuestro modelo de clasificación de TensorFlow 2.0 es dividir el conjunto de datos en conjuntos de entrenamiento y de prueba:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)

Entrenamiento de modelos

Para entrenar el modelo, importemos las clases de TensorFlow 2.0. Ejecute el siguiente script:

from tensorflow.keras.layers import Input, Dense, Activation,Dropout
from tensorflow.keras.models import Model

Como dije anteriormente, TensorFlow 2.0 usa la API de Keras para entrenar el modelo. En el script anterior básicamente importamos Input, Dense, Activationy Dropout clases de tensorflow.keras.layers módulo. Del mismo modo, también import la Model clase de la tensorflow.keras.models módulo.

El siguiente paso es crear nuestro modelo de clasificación:

input_layer = Input(shape=(X.shape[1],))
dense_layer_1 = Dense(15, activation='relu')(input_layer)
dense_layer_2 = Dense(10, activation='relu')(dense_layer_1)
output = Dense(y.shape[1], activation='softmax')(dense_layer_2)

model = Model(inputs=input_layer, outputs=output)
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=['acc'])

Como puede verse en el guión, el modelo contiene tres capas densas. Las dos primeras capas densas contienen 15 y 10 nodes, respectivamente con relu función de activación. La capa densa final contiene 4 nodes (y.shape[1] == 4) y softmax función de activación ya que se trata de una tarea de clasificación. El modelo se entrena usando categorical_crossentropy función de pérdida y adam optimizador. La métrica de evaluación es la precisión.

El siguiente script muestra el resumen del modelo:

print(model.summary())

Salida:

Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         [(None, 21)]              0
_________________________________________________________________
dense (Dense)                (None, 15)                330
_________________________________________________________________
dense_1 (Dense)              (None, 10)                160
_________________________________________________________________
dense_2 (Dense)              (None, 4)                 44
=================================================================
Total params: 534
Trainable params: 534
Non-trainable params: 0
_________________________________________________________________
None

Finalmente, para entrenar el modelo ejecute el siguiente script:

history = model.fit(X_train, y_train, batch_size=8, epochs=50, verbose=1, validation_split=0.2)

El modelo se entrenará durante 50 épocas, pero aquí por el bien del espacio, se muestra el resultado de solo las últimas 5 épocas:

Epoch 45/50
1105/1105 [==============================] - 0s 219us/sample - loss: 0.0114 - acc: 1.0000 - val_loss: 0.0606 - val_acc: 0.9856
Epoch 46/50
1105/1105 [==============================] - 0s 212us/sample - loss: 0.0113 - acc: 1.0000 - val_loss: 0.0497 - val_acc: 0.9856
Epoch 47/50
1105/1105 [==============================] - 0s 219us/sample - loss: 0.0102 - acc: 1.0000 - val_loss: 0.0517 - val_acc: 0.9856
Epoch 48/50
1105/1105 [==============================] - 0s 218us/sample - loss: 0.0091 - acc: 1.0000 - val_loss: 0.0536 - val_acc: 0.9856
Epoch 49/50
1105/1105 [==============================] - 0s 213us/sample - loss: 0.0095 - acc: 1.0000 - val_loss: 0.0513 - val_acc: 0.9819
Epoch 50/50
1105/1105 [==============================] - 0s 209us/sample - loss: 0.0080 - acc: 1.0000 - val_loss: 0.0536 - val_acc: 0.9856

Al final de la quincuagésima época, tenemos una precisión de entrenamiento del 100% mientras que la precisión de validación es del 98.56%, lo cual es impresionante.

Finalmente, evaluemos el desempeño de nuestro modelo de clasificación en el conjunto de prueba:

score = model.evaluate(X_test, y_test, verbose=1)

print("Test Score:", score[0])
print("Test Accuracy:", score[1])

Aquí está el resultado:

WARNING:tensorflow:Falling back from v2 loop because of error: Failed to find data adapter that can handle input: <class 'pandas.core.frame.DataFrame'>, <class 'NoneType'>
346/346 [==============================] - 0s 55us/sample - loss: 0.0605 - acc: 0.9740
Test Score: 0.06045335989359314
Test Accuracy: 0.9739884

Nuestro modelo alcanza una precisión del 97,39% en el equipo de prueba. Aunque es un poco menor que la precisión de entrenamiento del 100%, sigue siendo muy bueno dado el hecho de que elegimos aleatoriamente el número de capas y los nodes. Puede agregar más capas al modelo con más nodes y ver si puede obtener mejores resultados en los conjuntos de validación y prueba.

Regresión con TensorFlow 2.0

En el problema de regresión, el objetivo es predecir un valor continuo. En esta sección, verá cómo resolver un problema de regresión con TensorFlow 2.0

El conjunto de datos

El conjunto de datos de este problema se puede descargar gratuitamente desde este enlace. Descarga el archivo CSV.

El siguiente script importa el conjunto de datos. No olvide cambiar la ruta a su propio archivo de datos CSV.

petrol_cons = pd.read_csv(r'/content/drive/My Drive/datasets/petrol_consumption.csv')

Imprimamos las primeras cinco filas del conjunto de datos mediante el head() función:

petrol_cons.head()

Salida:

Puede ver que hay cinco columnas en el conjunto de datos. El modelo de regresión se entrenará en las primeras cuatro columnas, es decir, Petrol_tax, Average_inome, Paved_Highways y Population_Driver_License (%). Se predecirá el valor de la última columna, es decir, Petrol_Consumption. Como puede ver, no hay un valor discreto para la columna de salida, sino que el valor predicho puede ser cualquier valor continuo.

Preprocesamiento de datos

En el paso de preprocesamiento de datos, simplemente dividiremos los datos en características y etiquetas, y luego dividiremos los datos en conjuntos de prueba y entrenamiento. Finalmente se normalizarán los datos. Para problemas de regresión en general y para problemas de regresión con aprendizaje profundo, se recomienda encarecidamente que normalice su conjunto de datos. Finalmente, dado que todas las columnas son numéricas, aquí no es necesario realizar una codificación en caliente de las columnas.

X = petrol_cons.iloc[:, 0:4].values
y = petrol_cons.iloc[:, 4].values

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

En el script anterior, en el conjunto de funciones X, se incluyen las primeras cuatro columnas del conjunto de datos. En el conjunto de etiquetas y, solo se incluye la quinta columna. A continuación, el conjunto de datos se divide en entrenamiento y tamaño de prueba a través del train_test_split método del sklearn.model_selection módulo. El valor de la test_size El atributo es 0.2, lo que significa que el conjunto de prueba contendrá el 20% de los datos originales y el conjunto de entrenamiento consistirá en el 80% restante del conjunto de datos original. Finalmente, el StandardScaler clase de la sklearn.preprocessing El módulo se utiliza para escalar el conjunto de datos.

Entrenamiento de modelos

El siguiente paso es entrenar nuestro modelo. Este proceso es bastante similar al entrenamiento de la clasificación. El único cambio será en la función de pérdida y el número de nodes en la capa densa de salida. Dado que ahora estamos prediciendo un único valor continuo, la capa de salida solo tendrá 1 node.

input_layer = Input(shape=(X.shape[1],))
dense_layer_1 = Dense(100, activation='relu')(input_layer)
dense_layer_2 = Dense(50, activation='relu')(dense_layer_1)
dense_layer_3 = Dense(25, activation='relu')(dense_layer_2)
output = Dense(1)(dense_layer_3)

model = Model(inputs=input_layer, outputs=output)
model.compile(loss="mean_squared_error" , optimizer="adam", metrics=["mean_squared_error"])

Nuestro modelo consta de cuatro capas densas con 100, 50, 25 y 1 node, respectivamente. Para los problemas de regresión, una de las funciones de pérdida más utilizadas es mean_squared_error. El siguiente script imprime el resumen del modelo:

Model: "model_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_4 (InputLayer)         [(None, 4)]               0
_________________________________________________________________
dense_10 (Dense)             (None, 100)               500
_________________________________________________________________
dense_11 (Dense)             (None, 50)                5050
_________________________________________________________________
dense_12 (Dense)             (None, 25)                1275
_________________________________________________________________
dense_13 (Dense)             (None, 1)                 26
=================================================================
Total params: 6,851
Trainable params: 6,851
Non-trainable params: 0

Finalmente, podemos entrenar el modelo con el siguiente script:

history = model.fit(X_train, y_train, batch_size=2, epochs=100, verbose=1, validation_split=0.2)

Aquí está el resultado de las últimas 5 épocas de entrenamiento:

Epoch 96/100
30/30 [==============================] - 0s 2ms/sample - loss: 510.3316 - mean_squared_error: 510.3317 - val_loss: 10383.5234 - val_mean_squared_error: 10383.5234
Epoch 97/100
30/30 [==============================] - 0s 2ms/sample - loss: 523.3454 - mean_squared_error: 523.3453 - val_loss: 10488.3036 - val_mean_squared_error: 10488.3037
Epoch 98/100
30/30 [==============================] - 0s 2ms/sample - loss: 514.8281 - mean_squared_error: 514.8281 - val_loss: 10379.5087 - val_mean_squared_error: 10379.5088
Epoch 99/100
30/30 [==============================] - 0s 2ms/sample - loss: 504.0919 - mean_squared_error: 504.0919 - val_loss: 10301.3304 - val_mean_squared_error: 10301.3311
Epoch 100/100
30/30 [==============================] - 0s 2ms/sample - loss: 532.7809 - mean_squared_error: 532.7809 - val_loss: 10325.1699 - val_mean_squared_error: 10325.1709

Para evaluar el rendimiento de un modelo de regresión en un conjunto de prueba, una de las métricas más utilizadas es el error cuadrático medio de la raíz. Podemos encontrar el error cuadrático medio entre los valores predichos y reales mediante el mean_squared_error clase de la sklearn.metrics módulo. Entonces podemos sacar la raíz cuadrada del error cuadrático medio resultante. Mira el siguiente guión:

from sklearn.metrics import mean_squared_error
from math import sqrt

pred_train = model.predict(X_train)
print(np.sqrt(mean_squared_error(y_train,pred_train)))

pred = model.predict(X_test)
print(np.sqrt(mean_squared_error(y_test,pred)))

El resultado muestra el error cuadrático medio para los conjuntos de entrenamiento y prueba. Los resultados muestran que el rendimiento del modelo es mejor en el conjunto de entrenamiento, ya que el valor de error cuadrático medio del conjunto de entrenamiento es menor. Nuestro modelo está sobreajustado. La razón es obvia, solo teníamos 48 registros en el conjunto de datos. Intente entrenar modelos de regresión con un conjunto de datos más grande para obtener mejores resultados.

50.43599665058207
84.31961060849562

Conclusión

TensorFlow 2.0 es la última versión de la biblioteca TensorFlow de Google para el aprendizaje profundo. Este artículo cubre brevemente cómo crear modelos de clasificación y regresión con TensorFlow 2.0. Para tener una experiencia práctica, le sugiero que practique los ejemplos que se dan en este artículo y trate de crear modelos simples de regresión y clasificación con TensorFlow 2.0 utilizando algunos otros conjuntos de datos.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad