Grade, busca aleatória, otimização bayesiana, TPE, halving sucessivo e as duas maneiras como uma busca automática falha
trata a própria busca como um problema de otimização
leva a mesma ideia ao pipeline inteiro: pré-processamento, família, hiperparâmetros, o ensemble final
\(\lambda\): uma configuração. \(f(\lambda)\): o seu escore de validação cruzada (CV). Ajustar = encontrar o \(\lambda\) com o maior \(f(\lambda)\).
| ajustes | 5 embaralhamentos dos folds | média |
|---|---|---|
| valores padrão | 0,760 · 0,776 · 0,767 · 0,769 · 0,769 | 0,768 |
| árvores pequenas e lentas | 0,795 · 0,806 · 0,804 · 0,803 · 0,805 | 0,803 |
cada chamada são 5 ajustes; num projeto real, minutos ou horas. O orçamento é o número de chamadas.
de 0,760 a 0,776 para os mesmos ajustes: uma diferença de 0,01 talvez não seja real
não há gradiente em relação a min_samples_leaf; inteiros, categorias, botões condicionais
| taxa de aprendizado em | uniforme | log-uniforme |
|---|---|---|
| [0,001; 0,01) | 0,9% | 33,5% |
| [0,01; 0,1) | 9,1% | 33,2% |
| [0,1; 1) | 90,0% | 33,3% |
À mão: \(0{,}009 / 0{,}999 = 0{,}9\%\); na escala log, cada uma das 3 décadas recebe um terço.
C, alpha, número de folhas ou de vizinhos) ganha escala log: loguniform ou log=True no Optuna.C pertence à regressão logística, max_leaf_nodes ao boosting, gamma a um kernel RBF (de base radial).C com cada tamanho de árvore: a mesma regressão logística, ajustada repetidamente.if.| d | orçamento | grade | aleatória |
|---|---|---|---|
| 2 | 9 | 0,378 | 0,629 |
| 2 | 81 | 0,824 | 0,985 |
| 3 | 27 | 0,378 | 0,900 |
| 4 | 81 | 0,378 | 0,986 |
| 4 | 256 | 0,501 | 0,998 |
Melhor escore médio. A grade paga cada eixo irrelevante com uma multiplicação do seu custo; a busca aleatória não paga nada (Bergstra & Bengio, 2012).
Preveja. Orçamento 81: quantos valores distintos de \(x_1\) a grade 9 × 9 testa e quantos a busca aleatória testa?
A busca aleatória sorteia a 27.ª configuração exatamente como a primeira. Quando cada avaliação custa uma hora, isso é desperdício.
Um escore de mentira, com verdade conhecida: um pico largo de 0,78 em 0,25 e outro, mais alto e mais estreito, de 0,82 em 0,72.
Três avaliações até agora: 0,15 e 0,35 (0,72943), 0,95 (0,700). Melhor até agora: \(f^+ = 0{,}72943\).
| \(x\) | média \(\mu\) | dp \(\sigma\) | leitura |
|---|---|---|---|
| 0,25 | 0,73076 | 0,00419 | entre dois pontos: quase certo, logo acima de \(f^+\) |
| 0,55 | 0,72212 | 0,01246 | longe de qualquer ponto: abaixo de \(f^+\), três vezes mais incerto |
| 0,72 | 0,71390 | 0,01318 | o pico verdadeiro, mas o substituto não sabe nada dele |
| \(x\) | \(z\) | \((\mu - f^+)\Phi(z)\) | \(\sigma\varphi(z)\) | EI |
|---|---|---|---|---|
| 0,25 | +0,32 | +0,00083 | 0,00159 | 0,00242 |
| 0,55 | −0,59 | −0,00203 | 0,00417 | 0,00214 |
| 0,72 | −1,18 | −0,00185 | 0,00262 | 0,00077 |
1: explora localmente 0,25 → 0,780. 2: a EI ali desaba, então ela explora o vão → 0,72, 0,820. 3–4: refinam em 0,685 e 0,775. A busca aleatória precisaria de uns 28 sorteios para cair tão perto de 0,72.
100 rodadas a partir de trios iniciais aleatórios, 30 avaliações cada. Fração das rodadas que chegaram a 0,81:
| em até 10 | em até 20 | em até 30 | |
|---|---|---|---|
| bayesiana, escala de comprimento 0,15 | 40% | 65% | 65% |
| bayesiana, escala de comprimento 0,10 | 61% | 92% | 92% |
| busca aleatória | 37% | 54% | 65% |
| \(x\) | 0,1 | 0,25 | 0,5 | 0,7 | 0,9 |
|---|---|---|---|---|---|
| \(\ell / g\) | 0,03 | 1,24 | 0,45 | 5,73 | 0,09 |
Seis hiperparâmetros: um importa muito, um importa pouco, quatro não importam nada. Melhor possível: 0,870. 20 sementes.
| melhor médio depois de | 10 | 20 | 40 | 60 tentativas |
|---|---|---|---|---|
| aleatória | 0,812 | 0,819 | 0,830 | 0,843 |
| TPE | 0,812 | 0,847 | 0,857 | 0,860 |
Idênticos em 10: as 10 primeiras tentativas do TPE são aleatórias. Depois de 40, ele está acima do que a busca aleatória alcança depois de 60.
def build(trial):
family = trial.suggest_categorical('family', ['logistic', 'boosting'])
if family == 'logistic':
C = trial.suggest_float('C', 1e-3, 1e2, log=True)
return make_pipeline(FunctionTransformer(np.log1p), StandardScaler(),
LogisticRegression(C=C, max_iter=2000))
return HistGradientBoostingClassifier(
learning_rate=trial.suggest_float('learning_rate', 0.01, 0.5, log=True), ...)
C ≈ 0,03, 0,798, empatada com o boosting escolhido à mão; o TPE gastou 31 das 40 tentativas nela. Um espaço que deixa de fora o modelo simples nunca vai poder lhe dizer que você não precisava do complicado.trial.report).Comece \(n = 27\) configurações com um orçamento pequeno; fique com o melhor terço; dê aos sobreviventes 3 × mais; repita.
| rodada | configurações | árvores cada | custo |
|---|---|---|---|
| 1 | 27 | 10 | 270 |
| 2 | 9 | 30 | 270 |
| 3 | 3 | 90 | 270 |
| 4 | 1 | 270 | 270 |
| total | 1.080 |
HalvingRandomSearchCV).A ordem depois de um orçamento pequeno prevê a ordem depois do orçamento completo. Dois torneios: orçamento em árvores, orçamento em linhas.
| vencedor, orçamento em | escore completo | posição |
|---|---|---|
| árvores | 0,781 | 13.º de 27 |
| linhas | 0,787 | 5.º de 27 |
| melhor com o orçamento completo | 0,791 | 1.º |
Com uma taxa de aprendizado pequena, 10 árvores mal começaram: quem aprende devagar, o melhor com 270 árvores, foi todo eliminado na rodada 1.
Quão agressivo deve ser o torneio? O Hyperband roda brackets de agressividade diferente, cada um custando mais ou menos o mesmo (Li et al., 2018).
| bracket | rodadas (configurações × orçamento) | custo |
|---|---|---|
| s = 3 | 27 × 1 → 9 × 3 → 3 × 9 → 1 × 27 | 108 |
| s = 2 | 12 × 3 → 4 × 9 → 1 × 27 | 99 |
| s = 1 | 6 × 9 → 2 × 27 | 108 |
| s = 0 | 4 × 27 (busca aleatória pura) | 108 |
Combined Algorithm Selection and Hyperparameter optimization: seleção do algoritmo e dos hiperparâmetros juntos (Thornton et al., 2013).
| sistema | como busca | o que devolve |
|---|---|---|
| auto-sklearn | otimização bayesiana, com partida a quente a partir de conjuntos de dados parecidos | um ensemble (ensemble selection) |
| TPOT | programação genética sobre árvores de pipeline | o melhor pipeline, como código scikit-learn |
| AutoGluon-Tabular | pouca busca: bagging e empilhamento em várias camadas | um ensemble empilhado |
| FLAML | atenta ao custo: configurações baratas primeiro | o melhor modelo único num orçamento de tempo |
bug_reports: preenchida depois do lançamento; o modelo precisa apontar módulos arriscados antes do lançamento, quando a contagem é zero para todo mundo.
| ROC AUC | |
|---|---|
| melhor CV, sem a coluna / com ela | 0,792 / 0,916 |
| teste, vencedor com vazamento, coluna preenchida | 0,962 |
| teste, vencedor honesto | 0,804 |
teste, vencedor com vazamento, como será usado (bug_reports = 0) | 0,782 |
Toda verificação automática passa. O vazamento está nos dados: só quem sabe quando cada coluna é registrada consegue pegá-lo.
1.687 linhas, de 10 para 150 tentativas: CV de 0,803 para 0,808, teste de 0,804 para 0,809. Honesto.
300 linhas: CV de 0,772 para 0,788, teste de 0,765 para 0,769. Três quartos do ganho relatado são sorte.
o que é previsto, para quem, em que momento e quanto custa um erro
84,5% dos módulos do kc1 são limpos: uma busca por acurácia aprova um modelo que nunca aponta nada
grupos, ordem no tempo e vazamentos são explorados pela busca, não corrigidos
remover uma coluna vazada mudou a precisão média em 0,18; o ajuste, em 0,007
E a implantação: um ensemble empilhado de 40 modelos pode ser o mais difícil de servir, explicar e retreinar.
cv.phoneme: 5.404 vogais, orais ou nasais. Grade, busca aleatória, TPE e halving recebem 27 avaliações cada.
Escolhido (melhor CV): o vencedor do halving, CV 0,9528, teste 0,9455; os valores padrão caem o mesmo tanto (0,9468 → 0,9374).
Busca aleatória: best_score_ 0,9499; estimativa aninhada 0,9472 ± 0,0067.
Rode !pip install optuna antes. Notebook do lab (Jupyter ou Colab, Arquivo → Fazer upload de notebook).