Algoritmo de optimización de búsqueda de cuadrícula en Python

A

Introducción

En este tutorial, vamos a hablar de un algoritmo de optimización (o automatización) muy poderoso, es decir, el algoritmo de búsqueda de cuadrícula. Se usa más comúnmente para el ajuste de hiperparámetros en modelos de Machine Learning. Aprenderemos cómo implementarlo usando Python, así como aplicarlo en una aplicación real para ver cómo puede ayudarnos a elegir los mejores parámetros para nuestro modelo y mejorar su precisión. Así que empecemos.

Prerrequisitos

Para seguir este tutorial, debe tener un conocimiento básico de Python o algún otro lenguaje de programación. Es preferible, pero no esencial, que también tenga algunos conocimientos básicos de Machine Learning. Aparte de eso, este artículo es para principiantes y cualquier persona puede seguirlo.

Instalación

Para seguir el tutorial, debe tener las siguientes bibliotecas / marcos instalados en su sistema:

Todos son bastante sencillos de instalar: puede hacer clic en cada uno para ir a sus respectivos sitios web donde se proporcionan instrucciones detalladas de instalación. Generalmente, los paquetes se pueden instalar usando pip:

$ pip install numpy pandas tensorflow keras scikit-learn

Si tiene algún problema, consulte la documentación oficial de cada paquete.

¿Qué es Grid Search?

La búsqueda de cuadrícula es esencialmente un algoritmo de optimización que le permite seleccionar los mejores parámetros para su problema de optimización de una lista de opciones de parámetros que usted proporciona, automatizando así el método de ‘prueba y error’. Aunque se puede aplicar a muchos problemas de optimización, es más conocido por su uso en el Machine Learning para obtener los parámetros en los que el modelo ofrece la mejor precisión.

Supongamos que su modelo toma los siguientes tres parámetros como entrada:

  • Número de capas ocultas [2, 4]
  • Número de neuronas en cada capa [5, 10]
  • Número de épocas [10, 50]

Si para cada entrada de parámetro deseamos probar dos opciones (como se menciona entre corchetes arriba), totaliza hasta 23 = 8 combinaciones diferentes (por ejemplo, una combinación posible es [2,5,10]). Hacer esto manualmente sería un dolor de cabeza.

Ahora imagine si tuviéramos 10 parámetros de entrada diferentes y quisiéramos probar 5 valores posibles para cada parámetro. Requeriría una entrada manual de nuestra parte cada vez que deseamos cambiar el valor de un parámetro, volver a ejecutar el código y realizar un seguimiento de los resultados de todas las combinaciones de parámetros. Grid Search automatiza ese proceso, ya que simplemente toma los valores posibles para cada parámetro y ejecuta el código para probar todas las combinaciones posibles, genera el resultado para cada combinación y genera la combinación que brinda la mejor precisión. Útil, ¿no?

Implementación de búsqueda en cuadrícula

Muy bien, suficiente charla. Apliquemos Grid Search en una aplicación real. Discutir la parte de Machine Learning y preprocesamiento de datos está fuera del alcance de este tutorial, por lo que simplemente ejecutaremos su código y hablaremos en profundidad sobre la parte donde entra Grid Search. ¡Comencemos!

Usaremos el conjunto de datos Pima Indian Diabetes, que contiene información sobre si un paciente es diabético o no en función de diferentes atributos, como la concentración de glucosa en sangre, la presión arterial, etc. Uso de Pandas read_csv() método puede importar directamente el conjunto de datos desde un recurso en línea.

El siguiente script importa las bibliotecas necesarias:

from sklearn.model_selection import GridSearchCV, KFold
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.wrappers.scikit_learn import KerasClassifier
from keras.optimizers import Adam
import sys
import pandas as pd
import numpy as np

La siguiente secuencia de comandos importa el conjunto de datos y establece los encabezados de columna para el conjunto de datos.

columns = ['num_pregnant', 'glucose_concentration', 'blood_pressure', 'skin_thickness',
           'serum_insulin', 'BMI', 'pedigree_function', 'age', 'class']

data_path = "https://raw.githubusercontent.com/mkhalid1/Machine-Learning-Projects-Python-/master/Grid%20Search/pima-indians-diabetes.csv"

df = pd.read_csv(data_path, names=columns)

Echemos un vistazo a las primeras 5 filas del conjunto de datos:

df.head()

Salida:

Como puede ver, estas 5 filas son etiquetas para describir cada columna (en realidad hay 9 de ellas), por lo que no nos sirven de nada. Comenzaremos eliminando estas filas que no son de datos y luego reemplazaremos todas las NaN valores con 0:

# Remove first 9 non-data rows
df = df.iloc[9:]

# Replace NaN (Not a Number) values with 0 in each column
for col in columns:
    df[col].replace(0, np.NaN, inplace=True)

df.dropna(inplace=True) # Drop all rows with missing values
dataset = df.values # Convert dataframe to numpy array

El siguiente script divide los datos en conjuntos de características y etiquetas y aplica la escala estándar en el conjunto de datos:

X = dataset[:,0:8]
Y = dataset[:, 8].astype(int)

# Normalize the data using sklearn StandardScaler
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler().fit(X)

# Transform and display the training data
X_standardized = scaler.transform(X)

data = pd.DataFrame(X_standardized)

El siguiente método crea nuestro modelo de aprendizaje profundo simple:

def create_model(learn_rate, dropout_rate):
    # Create model
    model = Sequential()
    model.add(Dense(8, input_dim=8, kernel_initializer="normal", activation='relu'))
    model.add(Dropout(dropout_rate))
    model.add(Dense(4, input_dim=8, kernel_initializer="normal", activation='relu'))
    model.add(Dropout(dropout_rate))
    model.add(Dense(1, activation='sigmoid'))

    # Compile the model
    adam = Adam(lr=learn_rate)
    model.compile(loss="binary_crossentropy", optimizer=adam, metrics=['accuracy'])
    return model

Este es todo el código que necesitaría ejecutar para cargar el conjunto de datos, preprocesarlo y crear su modelo de Machine Learning. Dado que solo nos interesa ver la funcionalidad de Grid Search, no he realizado la división de tren / prueba, y estaríamos ajustando el modelo en todo el conjunto de datos.

En la siguiente sección comenzaremos a ver cómo Grid Search nos facilita la vida optimizando nuestros parámetros.

Entrenamiento del modelo sin búsqueda de cuadrícula

En el código a continuación, crearemos un modelo usando valores de parámetros que decidimos al azar, o según nuestra intuición, y veremos cómo funciona nuestro modelo:

# Declare parameter values
dropout_rate = 0.1
epochs = 1
batch_size = 20
learn_rate = 0.001

# Create the model object by calling the create_model function we created above
model = create_model(learn_rate, dropout_rate)

# Fit the model onto the training data
model.fit(X_standardized, Y, batch_size=batch_size, epochs=epochs, verbose=1)

Salida:

Epoch 1/1
130/130 [==============================] - 0s 2ms/step - loss: 0.6934 - accuracy: 0.6000

La precisión que obtuvimos, como puede ver a continuación, es 60.00%. Esto es bastante bajo, ¡pero no hay nada de qué preocuparse! Todavía tenemos Grid Search para intentar salvar el día. Vamos a por ello.

Optimización de hiperparámetros usando Grid Search

Si no utiliza Grid Search, puede llamar directamente al fit() método en el modelo que hemos creado anteriormente. Sin embargo, para usar Grid Search, necesitamos pasar algunos parámetros a nuestro create_model() función. Además, necesitamos declarar nuestra cuadrícula con diferentes opciones que nos gustaría probar para cada parámetro. Hagámoslo en partes.

Primero modificamos nuestro create_model() función para aceptar parámetros de la función de llamada:

def create_model(learn_rate, dropout_rate):
    # Create model
    model = Sequential()
    model.add(Dense(8, input_dim=8, kernel_initializer="normal", activation='relu'))
    model.add(Dropout(dropout_rate))
    model.add(Dense(4, input_dim=8, kernel_initializer="normal", activation='relu'))
    model.add(Dropout(dropout_rate))
    model.add(Dense(1, activation='sigmoid'))

    # Compile the model
    adam = Adam(lr=learn_rate)
    model.compile(loss="binary_crossentropy", optimizer=adam, metrics=['accuracy'])
    return model

# Create the model
model = KerasClassifier(build_fn=create_model, verbose=1)

Ahora, estamos listos para implementar nuestro algoritmo Grid Search y ajustar el conjunto de datos en él:

# Define the parameters that you wish to use in your Grid Search along
# with the list of values that you wish to try out
learn_rate = [0.001, 0.02, 0.2]
dropout_rate = [0.0, 0.2, 0.4]
batch_size = [10, 20, 30]
epochs = [1, 5, 10]

seed = 42

# Make a dictionary of the grid search parameters
param_grid = dict(learn_rate=learn_rate, dropout_rate=dropout_rate, batch_size=batch_size, epochs=epochs )

# Build and fit the GridSearchCV
grid = GridSearchCV(estimator=model, param_grid=param_grid,
                    cv=KFold(random_state=seed), verbose=10)

grid_results = grid.fit(X_standardized, Y)

# Summarize the results in a readable format
print("Best: {0}, using {1}".format(grid_results.best_score_, grid_results.best_params_))

means = grid_results.cv_results_['mean_test_score']
stds = grid_results.cv_results_['std_test_score']
params = grid_results.cv_results_['params']

for mean, stdev, param in zip(means, stds, params):
    print('{0} ({1}) with: {2}'.format(mean, stdev, param))

Salida:

Best: 0.7959183612648322, using {'batch_size': 10, 'dropout_rate': 0.2, 'epochs': 10, 'learn_rate': 0.02}

En la salida, podemos ver que nos da la combinación de parámetros que produce la mejor precisión.

Es seguro decir que Grid Search fue bastante fácil de implementar en Python y nos ahorró mucho tiempo, en términos de trabajo humano. Puede simplemente enumerar todos los parámetros que le gustaría ajustar, declarar los valores que se probarán, ejecutar su código y olvidarse de él. No se requiere más información de su lado. Una vez que se haya encontrado la mejor combinación de parámetros, simplemente puede usarla para su modelo final.

Conclusión

En resumen, aprendimos qué es Grid Search, cómo puede ayudarnos a optimizar nuestro modelo y los beneficios que conlleva como la automatización. Además, aprendimos cómo implementarlo en unas pocas líneas de código usando Python Language. Para ver su efectividad, también entrenamos un modelo de Machine Learning con y sin realizar Grid Search, y la precisión fue un 19% mayor con Grid Search.

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