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

    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.

     

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *