En este anterior post ya os describimos todos los fundamentos teóricos de los proceso de optimización de hiper-parámetros mediante los cuales podíamos mejorar las capacidades de nuestros modelos de razonamiento basados en Aprendizaje Automático. Ahora, os contamos cómo construir y ejecutar un proceso de optimización de hiper-parámetros sobre una red de neuronas profunda construida mediante la utilización de Keras. Para la ejecución de procesos de optimización de hiper-parámetros sobre keras es posible utilizar Keras Tuner. Esta librería nos ofrece un entorno de trabajo sencillo para la realización de procesos de optimización de hiper-parámetros sobre redes de neuronas de tipo profundo basadas en TensorFlow y Keras.

Instalación de Keras Tuner

Para poder utilizar esta librería es necesario realizar una instalación previa mediante el sistema de instalación de paquetes que python (Pip) de la siguiente manera:

Paso 1 - Instalación de keras tuner mediante Pip

Antes de poder utilizar el sistema de construcción de procesos de optimización es necesario instalar las librerías específicas mediante el sistemas de instalación genérico de paquetes de Python.

!pip install -q -U keras-tuner

El comando que se presenta a continuación se corresponde con la instalación sobre un Jupyter Notebook, en caso de que quieras programar sobre un editor tendrás que modificar parte de los comandos de instalación.

Paso 2 - Carga/importación de librerías básicas.

Una vez ejecutados los procesos de instalación necesarios podemos cargar las librerías básicas necesarias para la ejecución de los procesos de optimización mediante el siguiente fragmento de código:

import tensorflow as tf # Librería TensorFlow
from tensorflow import keras # Librería Keras
import kerastuner as kt # Librería Keras Tuner

Aunque está disponible el código fuente para descarga e instalación. Además esto nos permitirá incluir nuevas funcionalidades si así lo deseamos o sólo visualizar la estructura del propio código. En caso de querer descargar el código fuente, lo podemos hacer mediante su repositorio en git.

git clone https://github.com/keras-team/keras-tuner.git

Definición de hiper-parámetros

Una vez que hemos instalado las diferentes librerías necesarias podemos comenzar con la fase de definición de hiper-parámetros a optimizar. Para ello es necesario definir las propiedades de cada uno de los hiper-parámetros a optimizar mediante un proceso de construcción de los modelos en base a los valores permitidos. Keras Tuner nos ofrece una clase denominada HyperModel que deberemos extender mediante la creación de una nueva clase, que denominaremos MyHyperModel, para definir el proceso de creación de los modelos mediante un método denominado build como se muestra continuación:

from kerastuner import HyperModel

class MyHyperModel(HyperModel):

    def build(self, hp):

        hp_units = hp.Int('dense_1_units',
                          min_value = 9,
                          max_value = 27,
                          step = 3,
                          default = 12)

        layers = [keras.layers.Flatten(name = 'input', 
                                       input_shape = (9,)),
                  keras.layers.Dense(name = 'hidden',
                                     units = hp_units,
                                     activation = 'relu'),
                  keras.layers.Dense(name = 'output',
                                     units=1, 
                                     activation=tf.nn.sigmoid)]

        model = keras.Sequential(layers, name="example")

        model.compile(optimizer = 'sgd',
                      loss = 'binary_crossentropy',
                      metrics = ['accuracy'])

        return model

En el ejemplo presentado en el fragmento de código hemos desarrollado un proceso de construcción de modelos que utiliza un hiper-parámetro para definir el número de neuronas/unidades de la capa oculta de la red. Para la definición del hiper-parámetro hemos utilizado un objeto de tipo Int que nos permite construir parámetros de tipo entero, incluyendo ciertos parámetros de configuración que nos permiten definir cómo se realizará la optimización de los valores del hiper-parámetro:

Es posible incluir otros tipos de objetos para la selección de los valores de los hiper-parámetros dependiendo del tipo de parámetro que tengamos que asignar al hiper-parámetro. Por ejemplo, podemos definir parámetro de tipo real de la siguiente manera:

hp_learning_rate = hp.Float('lr',
                            min_value = 0.001,
                            max_value = 0.020,
                            step =  0.0005,
                            default = 0.003)

En este caso hemos creado un objeto para optimizar el valor de la tasa de aprendizaje. Keras Tuner nos ofrece diferentes tipo de objetos para la definición de los valores de nuestros hiper-parámetros siendo los más importantes:

Además, dependiendo del tipo de hiper-parámetro que vayamos a utilizar tendremos una serie de propiedades específicas para cada uno. El proceso de generación de hiper-parámetros también permite construir secuencias de hiper-parámetros mediante bucles; por ejemplo, podríamos crear un bucle en el proceso de construcción (build) que incluyen un determinado número de capas.

Definición del algoritmo de búsqueda

A continuación, podemos seleccionar nuestro algoritmo de búsqueda y todos los parámetros de configuración del mismo. Keras Tuner nos ofrece diferentes tipos de algoritmos de búsqueda: (1) búsqueda aleatoria (RandomSearch), (2) búsqueda mediante hiper-banda (Hyperband), búsqueda mediante optimización bayesiana (BayesianOptimization) y (4) búsqueda mediante el método de SKLearn (Sklearn). Para nuestro ejemplo vamos a utilizar la búsqueda aleatoria de la siguiente manera:


hypermodel = MyHyperModel()

tuner = RandomSearch(
    hypermodel,
    objective = 'val_accuracy',
    seed = 232,
    max_trials = 50, 
    executions_per_trial = 3,
    directory = 'random_search',
    project_name = 'example')

tuner.search_space_summary()

Para este ejemplo hemos configurado algunos de los elementos del algoritmo de búsqueda de la siguiente manera:

Al igual que otras librerías relacionadas con TensorFlow o Keras es posible obtener un resumen de la estructura del espacio de búsqueda en base a los diferentes hiper-parámetros que hemos definido mediante la utilización de la función search_space_summary que genera un informe similar al que se presenta a continuación


Search space summary
Default search space size: 3
dense_1_units (Int)
{'default': 12, 'conditions': [], 'min_value': 9, 'max_value': 27, 'step': 3, 'sampling': None}
dense_1_activation (Choice)
{'default': 'relu', 'conditions': [], 'values': ['relu', 'tanh'], 'ordered': False}
learning_rate (Float)
{'default': 0.001, 'conditions': [], 'min_value': 0.001, 'max_value': 0.02, 'step': 0.0005, 'sampling': None}


En este caso el espacio de búsqueda está formado por tres tipos de hiper-parámetros mediante los cuales podemos definir el número de neuronas de una capa totalmente conectada, el tipo de función de activación que se aplicará sobre una capa y el valor del factor de aprendizaje.

Ejecución del proceso de búsqueda

Una vez que definimos todos los elementos manuales de nuestro proceso de optimización podemos ejecutar el proceso de búsqueda mediante la utilización del método search.


tuner.search(X_train, 
             y_train, 
             epochs = 15, 
             validation_split = 0.12)

Para la ejecución del proceso de búsqueda es necesario incluir el conjunto de entrenamiento (X, y), el número de iteraciones (epochs) que se ejecutará cada fase de entrenamiento y el tamaño del conjunto de validación que es el que será utilizado para la evaluación del modelo generado y cuyo valor será utilizado como resultado de la función objetivo para definir la calidad del modelo.

Selección del modelo final

Tras la ejecución del proceso de búsqueda y los diferentes procesos de entrenamiento y validación, habremos generado un conjunto de modelos que estarán ordenados en base al “acurracy” obtenido sobre el conjunto de validación. Además, podremos obtener un resumen de las 10 mejores ejecuciones del proceso de búsqueda mediante la utilización de la función results_summary de nuestro objeto tuner. Este método siempre muestra por defecto las 10 mejores ejecuciones.

tuner.results_summary()

Results summary
Results in random_search/examples_paradigma
Showing 10 best trials
Objective(name='val_accuracy', direction='max')

Trial summary
Hyperparameters:
dende_1_units: 15
dense_1_activation: relu
learning_rate: 0.008520876742029873
Score: 0.9662162363529205

Trial summary
Hyperparameters:
dende_1_units: 15
dense_1_activation: relu
learning_rate: 0.0019815016575264635
Score: 0.9594594836235046

En este caso solo mostramos un extracto del resumen con las dos mejores ejecuciones de entre las 10 mejores almacenadas en el ranking temporal definido por Keras Tuner. Para cada uno de los modelos se indican los valores que han sido seleccionados para los hiper-parámetros, así como el tipo de valor que está siendo optimizada por la función objetivo que, en este caso, está maximizada la precisión (accuracy). Una vez finalizado el proceso de optimización es posible acceder a cualquiera de los diferentes modelos que han sido generados mediante la función get_best_models, donde es posible indicar el número de modelos que serán devueltos por la función mediante el parámetro num_models como se muestra a continuación donde queremos mostrar los 3 mejores modelos.

models = tuner.get_best_models(num_models=3)
best_model = models[0]

Los modelos resultantes se encuentran almacenados en un array de modelos ordenados por la puntuación. El proceso de selección del mejor modelo suele ser de tipo manual debido a que en la selección pueden incluir más criterios además de la puntuación, pero lo ideal sería automatizarlo en base a una serie de parámetros que permitirán a nuestro sistema de optimización ofrecer el mejor modelo en base a esos parámetros de configuración definidos por el diseñador. O, al menos, automatizar el proceso de almacenamiento de los mejores modelos en un registro de modelos para que un humano o un sistema de MLOps pudiera seleccionarlos de manera sencilla para su despliegue posterior.

Conclusiones

Keras Tuner es una librería muy sencilla de utilizar que simplifica en gran medida la complejidad de aplicar proceso de optimización de hiper-parámetros sobre redes de neuronas profundas construidas mediante Keras, ofreciéndonos un amplio grado de versatilidad para optimizar tanto la estructura de nuestra red como la configuración de los parámetros de algunos de los algoritmos implicados en el proceso de entrenamiento. Es verdad que ofrece pocos algoritmos de búsqueda para realizar el proceso de búsqueda y no es posible configurar muchas de las posibles opciones de esto; sin embargo, es muy sencillo incluir mejoras en el código fuente con el objetivo de añadir, por ejemplo, nuevos algoritmos de búsqueda.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete