Como Tunar Hiperparâmetros com Otimização Bayesiana

BENICIO WIGGERS JUNIOR
6 min readJul 14, 2020

Se você estuda ou trabalha com Data Science e Machine Learning com certeza já chegou no momento de um projeto onde teve que definir os valores de seus hiperparâmetros.

Hiperparâmetros são parâmetros do modelo que devem ser definidos pelo profissional antes da aplicação do mesmo, e não são aprendidos durante o processo de treino. Por exemplo, o número de árvores em um modelo de Random Forest é um hiperparâmetro, enquanto os pesos em uma rede neural são parâmetros aprendidos durante o treinamento do modelo.

Existem algumas maneiras de escolher os melhores hiperparâmetros para seu modelo: de forma manual, Grid Search, Random Search e Otimização Bayesiana.

Escolher manualmente significa você rodar seu modelo com uma configuração, pegar o resultado, rodar com outra configuração, pegar o resultado e ir comparando para cada vez que você muda os valores dos parâmetros e roda seu modelo novamente. Este método não só parece como é muito trabalhoso.

Com o Grid Search você define uma quantidade arbitrária de valores fixos para cada hiperparâmetro, ele testa todas as combinações diferentes e retorna a que apresentou o melhor resultado para a métrica de avaliação selecionada. No Random Search, no entanto, em vez de passar valores fixos, você define faixas de valores que ele deve usar. Sendo assim, o algoritmo vai selecionar um valor aleatoriamente da faixa passada para cada hiperparâmetro e rodar o modelo, obtendo uma avaliação. Ele realiza essa operação um número de vezes definido pelo usuário e retorna qual a configuração que obteve o melhor resultado.

A grande questão desses dois algoritmos é que eles “não aprendem” a cada iteração, ou seja, um valor que já foi testado anteriormente e não apresentou bons resultados poderá ser testado novamente, o que não parece muito eficiente, não é mesmo?

Aí entra em cena a Otimização Bayesiana.

Assim como para o modelo de Random Search, você passa faixas de valores a serem testados e uma métrica de avaliação a ser maximizada. Porém, após um número pré-definido de iterações com valores aleatórios, o algoritmo cria um modelo surrogate que estima a função objetivo da métrica selecionada. Cada ponto nessa função representa a probabilidade de se um obter uma determinada pontuação para a métrica de avaliação dado um valor de hiperparâmetro (em termos matemáticos: P(pontuação| hiperparâmetro)).

Além disso, ele utiliza uma função de aquisição (ou seleção) para selecionar o próximo ponto a ser testado. Essa função representa o critério que será utilizado para escolher o valor de hiperparâmetro da próxima iteração. Geralmente se usa o Expected Improvement (Melhoria Esperada), que indica a probabilidade de um valor de hiperparâmetro obter um resultado melhor que o atual. Sendo assim, estamos interessados no valor de hiperparâmetro que maximizará essa função.

Na imagem abaixo, a curva sombreada com verde representa a função de aquisição e a curva sombreada de azul, a função surrogate. A linha vermelha indica o valor máximo da função de aquisição, sendo assim, o valor do hiperparâmetro em seu ponto correspondente na função surrogate (ponto vermelho) será o próximo a ser testado.

Função surrogate na parte superior e função de aquisição na metade inferior. Imagem retirada de: https://miro.medium.com/max/436/1*9EszMI-ff2PbEPl38LpMQw.png

Após o teste, a função surrogate será atualizada com a pontuação real obtida para aquele valor de hiperparâmetro. Portanto, a cada iteração a função surrogate será aperfeiçoada e o algoritmo tenderá a encontrar os melhores valores para os hiperparâmetros que queremos otimizar.

Como vimos, diferente dos outros métodos, a Otimização Bayesiana “aprende” com cada teste feito, sendo mais eficaz na seleção da melhor combinação de hiperparâmetros.

Exemplo de Aplicação

Ok, entendi porque a Otimização Bayesiana é melhor, mas como que eu faço pra aplicar no meu projeto?

Bom, felizmente temos uma biblioteca que permite a aplicação da Otimização Bayesiana de uma maneira relativamente simples: a scikit-optimize. Ela tem uma documentação bem completa que você pode acessar neste link.

Neste artigo sobre previsão de fraudes em cartão de crédito, eu explico a importância das métricas de avaliação dos modelos de aprendizado de máquina e como utilizá-las para selecionar o melhor modelo. Vamos usar a Otimização Bayesiana no modelo de XGBoost que foi o que apresentou os melhores resultados. Na imagem abaixo podemos ver os valores obtidos para as principais métricas de avaliação para esse modelo com os valores padrão de hiperparâmetros.

Para isso, devemos começar importando o BayesSearchCV da biblioteca do scikit-optimize que irá realizar a otimização de nossos hiperparâmetros e utilizará cross-validation para avaliação. Os principais parâmetros do otimizador são o estimator (modelo utilizado para classificação) e o search_space (dicionário com os nomes dos parâmetros a serem otimizados e os valores inicial e final da faixa de cada parâmetro). Além disso, pode ser passado o número de iterações que ele irá realizar (em geral em torno de 30 já é o suficiente), o número de divisões (k) para o cross-validation e a métrica de avaliação que ele deve considerar para a otimização, nesse caso será o F1-Score devido ao desbalanceamento dos dados.

# importando o BayesSearchCVfrom skopt import BayesSearchCVfrom skopt.space import Real, Categorical, Integer# instanciando o algoritmo de classificação XGBoostclf = XGBClassifier(random_state=42, n_estimators=100)# definindo as faixas de valores a serem testadas para cada hiperparâmetro a ser otimizadospace = {'max_depth': Integer(1, 25),'learning_rate': Real(1e-3, 1e-1, 'log-uniform'),'gamma': Real(0.05, 1.0),'min_child_weight': Integer(1, 50),'subsample': Real(0.05, 1.0),'colsample_bytree': Real(0.06, 1.0)}# instanciando o algoritmo de otimização e definindo alguns parâmetros deleopt = BayesSearchCV(clf, space, n_iter=50, random_state=42, cv=5,return_train_score=True, scoring='f1', refit=True)# executando o modelo de otimizaçãoopt.fit(X_train, y_train)# aplicando o modelo nos dados de testey_pred_opt = opt.predict(X_test)opt_prob = opt.predict_proba(X_test)# calculando a curva precision-recallprecision, recall, threshold = precision_recall_curve(y_test, opt_prob[:, 1])# imprimindo os resultados de avaliaçãoprint(classification_report(y_test, y_pred_opt))print(f'AUC: {round(auc(recall, precision), 2)}')skplt.metrics.plot_confusion_matrix(y_test, y_pred_opt, figsize=(6,6));
Avaliação do XGBoost com hiperparâmetros tunados por Otimização Bayesiana

Podemos verificar que o F1-Score, que foi a métrica escolhida a ser maximizada pela Otimização Bayesiana, aumentou de 0,86 para 0,89. Isso ocorre devido ao aumento do Precision de 0,93 para 0,97 e do Recall de 0,81 para 0,83. Para um modelo de detecção de fraudes como esse, significa que detectaríamos mais fraudes e cometeríamos menos erros classificando transações regulares como fraudulentas. Isso acarretaria em uma maior satisfação dos clientes e menores gastos com fraudes.

Conclusão

Neste artigo, meu objetivo foi explicar de maneira simples o que é a Otimização Bayesiana, quais sua vantagens em relação aos outros métodos, assim como mostrar como ela pode ser aplicada. Espero que você tenha compreendido e consiga utilizá-la em seus projetos.

Caso deseje mais detalhes sobre o assunto, deixarei links para outros dois artigos que o explicam de maneira mais aprofundada:

Além disso, deixarei a recomendação deste vídeo do canal do Youtube do Mario Filho, onde ele explica como usar a função gpminimize do scikit-optimize para realizar a otimização Bayesiana.

--

--

BENICIO WIGGERS JUNIOR

Data Analytics | Business Intelligence | Ciência de Dados | Inteligência Artificial