Você já se perguntou como tunar os hiperparâmetros do CatBoost para obter o melhor desempenho possível?

O ajuste de hiperparâmetros é a chave para desbloquear todo o potencial do seu modelo.

Mas olhando a documentação do CatBoost, você pode se sentir sobrecarregado com a quantidade de hiperparâmetros disponíveis.

Isso acaba hoje!

A Optuna é uma biblioteca de otimização de hiperparâmetros poderosa e fácil de usar que pode ajudar a encontrar os melhores hiperparâmetros para o seu modelo CatBoost.

Depois de dominar as dicas e truques apresentados neste tutorial, você estará equipado com as habilidades para tunar efetivamente qualquer modelo CatBoost.

Vamos começar!

Instalando CatBoost e Optuna

Primeiro, vamos instalar ambas as bibliotecas:

pip install catboost optuna

Ou, se você estiver usando Anaconda, execute:

conda install -c anaconda catboost
conda install -c conda-forge optuna

O Optuna usa uma técnica inteligente chamada otimização Bayesiana para encontrar os melhores hiperparâmetros para o seu modelo.

Usar a otimização Bayesiana é como ter um navegador experiente te guiando por águas desconhecidas.

Em vez de navegar sem rumo em direções aleatórias (busca aleatória) ou mapear meticulosamente cada ponto manualmente (busca em grade), o navegador dirige o navio com expertise, usando experiências passadas e conhecimento das correntes para encontrar a melhor rota até seu destino.

Neste tutorial, usarei o conjunto de dados Red Wine Quality da UCI.

É um conjunto de dados real com propriedades químicas de vinhos tintos, e nosso objetivo é prever a qualidade do vinho.

import pandas as pd
from sklearn.model_selection import train_test_split

url = "https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv"
data = pd.read_csv(url, delimiter=";")

X = data.drop("quality", axis=1)
y = data["quality"]

X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
fixed acidity volatile acidity citric acid residual sugar chlorides free sulfur dioxide total sulfur dioxide density pH sulphates alcohol
8.7 0.69 0.31 3 0.086 23 81 1.0002 3.48 0.74 11.6
6.1 0.21 0.4 1.4 0.066 40.5 165 0.9912 3.25 0.59 11.9
10.9 0.39 0.47 1.8 0.118 6 14 0.9982 3.3 0.75 9.8
8.8 0.685 0.26 1.6 0.088 16 23 0.99694 3.32 0.47 9.4
8.4 1.035 0.15 6 0.073 11 54 0.999 3.37 0.49 9.9

Podemos tratar esse problema como regressão ou classificação, mas neste tutorial, vamos focar na regressão.

Quais Hiperparâmetros do CatBoost Devo Ajustar?

Ao ajustar o CatBoost, há seis hiperparâmetros principais para focar:

Número de Árvores (iterations)

O número de iterações no CatBoost representa os passos (ou rodadas de refinamento) que o algoritmo realiza para criar um modelo mais preciso que aprende com os dados.

No caso de algoritmos GBDT (Gradient Boosted Decision Trees), cada iteração adiciona uma nova árvore de decisão ao modelo.

O melhor valor para o número de iterações depende do seu problema específico e conjunto de dados.

Se seu modelo for executado em tempo real, você vai querer manter o número de iterações baixo (mais rápido), mas se você só precisa fazer previsões semanalmente, pode se permitir usar mais árvores.

Eu gosto de usar números fixos, como 100-200 para aplicações em tempo real e 1000-2000 para aplicações sem requisitos rigorosos de latência.

Na prática, gosto de sempre colocar o máximo de iterações possível e tunar a taxa de aprendizado para controlar o impacto de cada árvore.

Isso deixa as previsões mais estáveis.

Taxa de Aprendizado (learning_rate)

No geral, um modelo de gradient boosting faz uma soma ponderada das previsões de várias árvores de decisão para chegar a uma previsão final.

A taxa de aprendizado determina a contribuição de cada árvore de decisão para gerenciar o equilíbrio geral e a precisão do modelo.

Uma taxa de aprendizado menor significa que cada árvore oferece uma contribuição menor, ou uma atualização menor ao modelo, resultando em um aprendizado gradual.

Isso pode levar a uma maior precisão, mas aumenta o risco de underfitting e tempos de treinamento mais longos.

Por outro lado, uma taxa de aprendizado maior significa que cada árvore tem um impacto mais significativo no modelo, acelerando o processo de aprendizagem.

No entanto, uma taxa de aprendizado alta pode resultar em overfitting ou instabilidade do modelo.

Um intervalo de 0,001 a 0,1 é um bom ponto de partida.

Profundidade da Árvore (depth)

Você pode pensar na depth como a complexidade ou “altura” das árvores de decisão no seu modelo CatBoost.

Uma profundidade maior pode capturar padrões mais complexos nos seus dados, levando a um melhor desempenho.

Mas há um porém - quanto mais profunda a árvore, mais tempo leva para treinar, e maior o risco de overfitting.

Ao ajustar a profundidade, é uma boa ideia experimentar valores entre 1 e 10.

Subamostragem (subsample)

A subamostragem é uma técnica usada para escolher aleatoriamente uma fração do conjunto de dados ao construir cada árvore.

Isso promove diversidade entre as árvores e ajuda a reduzir o overfitting.

O intervalo do parâmetro subsample que eu recomendo vai de 0,05 a 1.

Valores mais baixos aumentam a diversidade, mas podem resultar em underfitting.

Amostragem de Features por Nível (colsample_bylevel)

colsample_bylevel é a fração de features a serem escolhidas ao determinar a melhor divisão para cada nó em um nível específico durante o processo de construção de cada árvore.

A ideia é a mesma que com subsample, mas desta vez, estamos amostrando features em vez de linhas.

Eu gosto de usar valores entre 0,05 e 1,0 no espaço de busca.

Dados Mínimos nos Nós (min_data_in_leaf)

min_data_in_leaf especifica o número mínimo de amostras necessárias para criar um nó, efetivamente controlando o processo de criação de árvores.

Pense nisso como: quantos pontos de dados a árvore usará para estimar uma previsão?

Valores mais altos geram árvores menos complexas, reduzindo riscos de overfitting, mas podem resultar em underfitting. Valores mais baixos levam a árvores mais complexas que podem fazer overfitting.

Eu gosto de considerar valores entre 1 e 100.

Código para Tunar Hiperparâmetros do CatBoost com Optuna

Agora que você conhece os hiperparâmetros críticos, vamos aprender como otimizá-los usando o Optuna.

Primeiro, vamos definir a função objetivo, que o Optuna visa otimizar.

import catboost as cb
from sklearn.metrics import mean_squared_error
import optuna

def objective(trial):
    params = {
        "iterations": 1000,
        "learning_rate": trial.suggest_float("learning_rate", 1e-3, 0.1, log=True),
        "depth": trial.suggest_int("depth", 1, 10),
        "subsample": trial.suggest_float("subsample", 0.05, 1.0),
        "colsample_bylevel": trial.suggest_float("colsample_bylevel", 0.05, 1.0),
        "min_data_in_leaf": trial.suggest_int("min_data_in_leaf", 1, 100),
    }

    model = cb.CatBoostRegressor(**params, silent=True)
    model.fit(X_train, y_train)
    predictions = model.predict(X_val)
    rmse = mean_squared_error(y_val, predictions, squared=False)
    return rmse

Nosso objetivo principal é minimizar a raiz do erro quadrático médio (RMSE) no conjunto de validação.

O dicionário params dentro da função objetivo contém os hiperparâmetros do CatBoost a serem ajustados pelo Optuna.

Os métodos trial.suggest_* definem o espaço de busca para cada hiperparâmetro de acordo com os valores que sugeri acima.

Por exemplo, learning_rate é pesquisado dentro de uma escala logarítmica de 1e-3 a 0,1, e depth é pesquisado dentro de um intervalo inteiro de 1 a 10.

Por que logarítmica? Assim vamos testar valores menores com mais frequência, pois eles tendem a dar um resultado melhor.

Uma vez que o modelo é treinado, ele gera previsões no conjunto de validação e calcula o RMSE.

Para executar a otimização, criamos um objeto de estudo e passamos a função objetivo para o método de otimização.

study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=30)

O parâmetro direction especifica se queremos minimizar ou maximizar a função objetivo.

Como um RMSE menor indica um modelo melhor, nosso objetivo é minimizá-lo.

O parâmetro n_trials define o número de vezes que o modelo será treinado com diferentes valores de hiperparâmetros.

Na prática, cerca de 30 tentativas são suficientes para encontrar um conjunto sólido de hiperparâmetros.

Durante a otimização, o Optuna exibirá os melhores hiperparâmetros descobertos até o momento, junto com a pontuação RMSE.

[I 2023-04-19 12:06:08,041] Trial 0 finished with value: 0.5924479493712448 and parameters: {'learning_rate': 0.004223041167235877, 'depth': 7, 'subsample': 0.7417292559386053, 'colsample_bylevel': 0.8745350089011158, 'min_data_in_leaf': 13}. Best is trial 0 with value: 0.5924479493712448.
[I 2023-04-19 12:06:09,555] Trial 1 finished with value: 0.5614677547730352 and parameters: {'learning_rate': 0.02103994077207402, 'depth': 5, 'subsample': 0.22061724636372576, 'colsample_bylevel': 0.5059245643597533, 'min_data_in_leaf': 48}. Best is trial 1 with value: 0.5614677547730352.
[I 2023-04-19 12:06:10,126] Trial 2 finished with value: 0.6902916540317992 and parameters: {'learning_rate': 0.0041358521262659514, 'depth': 6, 'subsample': 0.6463635383371191, 'colsample_bylevel': 0.06872124261390113, 'min_data_in_leaf': 90}. Best is trial 1 with value: 0.5614677547730352.

Depois que a otimização estiver concluída, podemos ver os melhores hiperparâmetros e a pontuação RMSE com os seguintes métodos:

print('Melhores hiperparâmetros:', study.best_params)
print('Melhor RMSE:', study.best_value)

Melhores hiperparâmetros: {'learning_rate': 0.044248358418971304, 'depth': 10, 'subsample': 0.860245768257485, 'colsample_bylevel': 0.2813359918917325, 'min_data_in_leaf': 23}
Melhor RMSE: 0.5248051919337918

Agora você pode usar esses valores em seu modelo CatBoost para fazer previsões mais precisas.

Uma dica adicional: se a maioria das melhores tentativas utilizar um hiperparâmetro específico próximo ao valor mínimo ou máximo, considere expandir o espaço de busca para esse hiperparâmetro.

Por exemplo, se a maioria das melhores tentativas usar learning_rate próximo a 0,001, você provavelmente deve reiniciar a otimização com o espaço de busca trial.suggest_float("learning_rate", 1e-4, 1e-2, log=True).

Usando este método, você obterá um excelente conjunto de hiperparâmetros, permitindo que você se concentre em outras tarefas com um maior impacto no desempenho do modelo, como engenharia de features.

Seja o primeiro a saber das novidades em Machine Learning. Me siga no LinkedIn.