Optimización de hiperparámetros con Hyperopt
Hyperopt es una biblioteca de Python de código abierto para el ajuste de hiperparámetros. Hyperopt se instala automáticamente cuando se crea un clúster con una variante de ML de Databricks Runtime. Siga estos pasos para usarla al entrenar un modelo:
- Defina una función objetivo para entrenar y evaluar un modelo.
- Definir el espacio de búsqueda de hiperparámetros.
- Especifique el algoritmo de búsqueda.
- Ejecute la función fmin de Hyperopt para optimizar la función de entrenamiento.
Definición de una función objetivo
Hyperopt funciona si se llama de manera iterativa a una función (a menudo denominada como la función objetivo) que devuelve un valor numérico y se ajustan los parámetros pasados a la función para que se minimice el valor devuelto; un enfoque que se conoce habitualmente como optimización. Por lo tanto, el primer requisito es encapsular la lógica de evaluación y entrenamiento del modelo en una función que:
- Acepte un parámetro que contenga una lista de valores de hiperparámetros.
- Entrene un modelo con los valores de hiperparámetros proporcionados.
- Evalúe el modelo en función de una métrica de destino para el rendimiento predictivo.
- Devuelva un valor numérico que refleje la métrica de rendimiento de modo que mejorar el rendimiento del modelo reduzca el valor devuelto.
Por ejemplo, la función siguiente entrena un modelo de Machine Learning con el algoritmo LogisticRegression de la biblioteca MLlib de Spark.
def objective(params):
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import MulticlassClassificationEvaluator
from hyperopt import STATUS_OK
data_df = get_training_data() # This is just an example!
splits = data_df.randomSplit([0.7, 0.3])
training_df = splits[0]
validation_df = splits[1]
# Train a model using the provided hyperparameter values
lr = LogisticRegression(labelCol="label", featuresCol="features",
maxIter=params['Iterations'],
regParam=params['Regularization'])
model = lr.fit(training_df)
# Evaluate the model
predictions = model.transform(validation_df)
eval = MulticlassClassificationEvaluator(labelCol="label",
predictionCol="prediction",
metricName="accuracy")
accuracy = eval.evaluate(predictions)
# Hyperopt *minimizes* the function, so return *negative* accuracy.
return {'loss': -accuracy, 'status': STATUS_OK}
En este ejemplo, el parámetro params es un diccionario que contiene valores para dos valores con nombre: Iteraciones y Regularización. Estos valores se asignan a los hiperparámetros maxIter y regParam del algoritmo de regresión logística que se usa para entrenar el modelo.
A continuación, la función evalúa el modelo entrenado para calcular su métrica de precisión, que es un valor entre 0,0 y 1,0 que indica la proporción de las predicciones que el modelo realizó que eran correctas.
Por último, la función devuelve un valor que Hyperopt debe minimizar a fin de mejorar el modelo. En este caso, la métrica de destino es la precisión, para la que un valor mayor indica un mejor modelo; por lo tanto, la función devuelve el negativo de este valor (por lo que cuanto mayor sea la precisión, menor será el valor devuelto).
Definir el espacio de búsqueda de hiperparámetros
Cada vez que se llama a la función objetivo, requiere que se pruebe un parámetro que contenga los valores de hiperparámetros. Para probar todas las combinaciones de valores posibles, debe definir un espacio de búsqueda para Hyperopt para seleccionar valores de para cada prueba.
Hyperopt proporciona expresiones que se pueden usar para definir un intervalo de valores para cada hiperparámetro, que incluyen:
hp.choice(label, options)
: devuelve uno de los valores deoptions
enumerados.hp.randint(label, upper)
: devuelve un entero aleatorio en el intervalo [0, superior].hp.uniform(label, low, high)
: devuelve un valor entrelow
yhigh
de manera uniforme.hp.normal(label, mu, sigma)
: devuelve un valor real que, normalmente, se distribuye con la mediamu
y la desviación estándarsigma
.
Sugerencia
Para obtener la lista de expresiones completa, consulte la documentación de Hyperopt.
El código de ejemplo siguiente define un espacio de búsqueda para los hiperparámetros usados en el ejemplo anterior:
from hyperopt import hp
search_space = {
'Iterations': hp.randint('Iterations', 10),
'Regularization': hp.uniform('Regularization', 0.0, 1.0)
}
Especificación del algoritmo de búsqueda
Hyperopt usa un algoritmo de búsqueda para seleccionar valores de hiperparámetros del espacio de búsqueda e intentar optimizar la función objetivo. Hay dos opciones principales en la forma en que los ejemplos de Hyperopt sobre el espacio de búsqueda:
hyperopt.tpe.suggest
: estimadores de Parzen estructurados en árbol (TPE), un enfoque bayesiano que selecciona de manera adaptable la configuración de hiperparámetros nueva en función de los resultados anteriores.hyperopt.rand.suggest
: búsqueda aleatoria, un enfoque no adaptable que hace un muestreo aleatorio en el espacio de búsqueda.
El código de ejemplo siguiente especifica el algoritmo TPE.
from hyperopt import tpe
algo = tpe.suggest
Ejecución de la función fmin de Hyperopt
Por último, para llevar a cabo una ejecución de Hyperopt, puede usar la función fmin, que llama repetidamente a la función objetivo mediante combinaciones de hiperparámetros desde el espacio de búsqueda en función del algoritmo de búsqueda. El objetivo de la función fmin es minimizar el valor que la función objetivo devuelve (y, por tanto, optimizar el rendimiento del modelo).
En el código de ejemplo siguiente se usa la función fmin para llamar a la función objetivo que se definió anteriormente. Se usan el espacio de búsqueda y el algoritmo definidos en ejemplos anteriores, y la función se evalúa hasta 100 veces antes de que la función fmin devuelva la combinación de valor de parámetro de mejor rendimiento que se encontró.
from hyperopt import fmin
argmin = fmin(
fn=objective,
space=search_space,
algo=algo,
max_evals=100)
print("Best param values: ", argmin)
La salida del código anterior es similar al ejemplo siguiente.
Best param values: {'Iterations': 6, 'Regularization': 0.5461699702338606}