Paralelizar a otimização de hiperparâmetros com o Hyperopt

Nota

A versão de código aberto do Hyperopt não está mais sendo mantida.

O Hyperopt não está incluído no Databricks Runtime for Machine Learning após o 16.4 LTS ML. O Azure Databricks recomenda usar o Optuna para otimização de nó único ou RayTune para uma experiência semelhante à funcionalidade preterida de ajuste de hiperparâmetro distribuído do Hyperopt. Saiba mais sobre como usar RayTune no Azure Databricks.

Este caderno de exemplo mostra como escalar a afinação de hiperparâmetros de uma única máquina para um cluster de Azure Databricks usando Hyperopt com SparkTrials. Ao ajustar um classificador SVM scikit-learn no conjunto de dados Iris, primeiro constrói-se um fluxo de trabalho de uma única máquina fmin() e depois paraleliza-o entre os trabalhadores do Spark, enquanto o MLflow acompanha automaticamente cada tentativa.

Importar pacotes necessários e carregar o conjunto de dados

from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC

from hyperopt import fmin, tpe, hp, SparkTrials, STATUS_OK, Trials

# If you are running Databricks Runtime for Machine Learning, `mlflow` is already installed and you can skip the following line.
import mlflow
# Load the iris dataset from scikit-learn
iris = iris = load_iris()
X = iris.data
y = iris.target

Parte 1. Fluxo de trabalho Hyperopt de máquina única

Aqui estão os passos num fluxo de trabalho Hyperopt:

  1. Defina uma função a minimizar.
  2. Defina um espaço de pesquisa sobre hiperparâmetros.
  3. Selecione um algoritmo de pesquisa.
  4. Executa o algoritmo de afinação com Hyperopt fmin().

Para mais informações, consulte a documentação do Hyperopt.

Defina uma função para minimizar

Neste exemplo, utilizamos uma máquina de vetores de suporte para classificar. O objetivo é encontrar o melhor valor para o parâmetro Cde regularização .

A maior parte do código para um fluxo de trabalho Hyperopt está na função objetivo. Este exemplo utiliza o classificador de vetores de suporte do scikit-learn.

Se o seu cluster usa Databricks Runtime ML 11.3, edite o classificador de vetor de suporte para tomar um argumento posicional, clf = SVC(C).

def objective(C):
    # Create a support vector classifier model
    clf = SVC(C=C)

    # Use the cross-validation accuracy to compare the models' performance
    accuracy = cross_val_score(clf, X, y).mean()

    # Hyperopt tries to minimize the objective function. A higher accuracy value means a better model, so you must return the negative accuracy.
    return {'loss': -accuracy, 'status': STATUS_OK}

Defina o espaço de pesquisa sobre hiperparâmetros

Consulte a documentação do Hyperopt para detalhes sobre como definir um espaço de pesquisa e expressões de parâmetros.

search_space = hp.lognormal('C', 0, 1.0)

Selecione um algoritmo de pesquisa

As duas principais escolhas são:

  • hyperopt.tpe.suggest: Tree of Parzen Estimators, uma abordagem bayesiana que seleciona iterativa e adaptativamente novas definições de hiperparâmetros para explorar com base em resultados anteriores
  • hyperopt.rand.suggest: Pesquisa aleatória, uma abordagem não adaptativa que amostra dentro do espaço de pesquisa
algo=tpe.suggest

Execute o algoritmo de afinação com Hyperopt fmin()

Definido max_evals para o número máximo de pontos no espaço de hiperparâmetros a testar, ou seja, o número máximo de modelos a ajustar e avaliar.

argmin = fmin(
  fn=objective,
  space=search_space,
  algo=algo,
  max_evals=16)
# Print the best value found for C
print("Best value found: ", argmin)

Parte 2. Afinação distribuída usando Apache Spark e MLflow

Para distribuir a afinação, adicione mais um argumento a fmin(): uma Trials classe chamada SparkTrials.

SparkTrials Aceita 2 argumentos opcionais:

  • parallelism: Número de modelos a ajustar e avaliar simultaneamente. O padrão é o número de espaços disponíveis para tarefas do Spark.
  • timeout: Tempo máximo (em segundos) que fmin() pode funcionar. O padrão é não ter limite máximo de tempo.

Este exemplo utiliza a função objetivo muito simples definida no Cmd 7. Neste caso, a função corre rapidamente e a sobrecarga de iniciar os trabalhos do Spark domina o tempo de cálculo, pelo que os cálculos no caso distribuído demoram mais tempo. Para problemas típicos do mundo real, a função objetivo é mais complexa, e o uso do SparkTrails para distribuir os cálculos é mais rápido do que o ajuste de uma única máquina.

O rastreio automático do fluxo de ML está ativado por defeito. Para o usar, chame mlflow.start_run() antes de chamar fmin() , como mostrado no exemplo.

from hyperopt import SparkTrials

# To display the API documentation for the SparkTrials class, uncomment the following line.
# help(SparkTrials)
spark_trials = SparkTrials()

with mlflow.start_run():
  argmin = fmin(
    fn=objective,
    space=search_space,
    algo=algo,
    max_evals=16,
    trials=spark_trials)
# Print the best value found for C
print("Best value found: ", argmin)

Para visualizar a experiência MLflow associada ao caderno, clique no ícone Experimento na barra de contexto do caderno no canto superior direito. Lá, pode ver todas as corridas. Para visualizar as execuções na interface do MLflow, clique no ícone na extrema direita do lado de Execuções de Experiência.

Para examinar o efeito da afinação C:

  1. Selecione as sequências resultantes e clique em Comparar.
  2. No Gráfico de Dispersão, selecione C para o eixo X e perda para o eixo Y.

Depois de executar as ações na última célula do bloco de anotações, a interface do usuário do MLflow deve exibir:

Demonstração do Hyperopt MLflow

Bloco de notas de exemplo

Paralelizar a otimização de hiperparâmetros com o Hyperopt

Obtenha caderno