Machine learning do zero · Aula 5.6 · 31 de 33 aulas prontas · 12 min
Qual modelo, quando?
Em resumo
Cinco modelos, cinco conjuntos, 20 divisões. Nenhum modelo lidera em todos, e 0,3 ponto de diferença pode ser um empate: 10 contra 7.
Aquecimento Duas perguntas de aulas anteriores. Um minuto, e a aula nunca fica bloqueada.
Você já conhece cinco famílias de modelos: regressão logística, k vizinhos mais próximos (kNN), floresta aleatória, gradient boosting e SVM com kernel RBF. Qual escolher? A resposta honesta: aquele que se sai melhor na validação com os seus dados. Esta lição verifica o quanto o resultado depende dos dados e como distinguir uma diferença real do ruído. Montamos um zoológico de modelos: cada um dos cinco modelos com as configurações padrão, sem ajuste, em cinco conjuntos de dados, e em cada conjunto com as mesmas 20 divisões. Em cada uma, 75% das linhas servem para aprender e 25% para validar.
Escolha uma resposta e o seu grau de certeza.
Responda para liberar o experimento.
Experimento interativo
Este experimento interativo funciona em um navegador com JavaScript ativado. O texto ao redor descreve o que ele mostra.
Ver a resposta
Resposta certa: Não: a SVM vence a regressão nos dígitos e perde para ela nos pinguins
Não. Nos dígitos, a SVM acerta mais que a regressão logística em 17 das 20 divisões, e a regressão mais que a SVM em 3. Nos pinguins, a regressão acerta mais em 9 divisões, a SVM em nenhuma, e 11 empatam. A melhor média também fica com modelos diferentes em conjuntos diferentes, mas em quatro conjuntos o líder acerta mais que o segundo em no máximo 10 das 20 divisões. Quem lidera ali depende em grande parte das divisões.
Experimente você
- No início: dígitos, kNN contra SVM. A diferença das médias é menor que a dispersão do kNN entre as divisões. Em quantas das 20 divisões a SVM acerta mais?
- Mude para os tumores de mama e compare a SVM com o gradient boosting. Qual é a diferença das médias e como se repartem as divisões?
- Encontre um par de modelos em que um lidera nos dígitos e o outro nos pinguins.
- Em cada conjunto, veja a distância entre a pior e a melhor divisão do mesmo modelo.
Depois de conferir no lab, vamos pôr em palavras o que você vê.
A ideia em termos simples
O mesmo modelo no mesmo conjunto tem resultados diferentes conforme a divisão, porque a validação recebe ora exemplos mais fáceis, ora mais difíceis. Nos tumores, a regressão logística obtém de 89,4% a 96,5% em divisões isoladas. As diferenças entre modelos costumam ser bem menores. Por isso uma única divisão não basta para ordená-los.
É melhor comparar os modelos em pares: na mesma divisão, os dois têm a tarefa igualmente fácil ou difícil. Contamos em quantas divisões cada um acerta mais. Nos tumores, a SVM obtém 94,2% em média e o gradient boosting 93,9%. A SVM acerta mais em 10 divisões, o boosting em 7, e 3 empatam. Uma diferença assim de 0,3 ponto é um empate, não uma vitória. O inverso também acontece. Nos dígitos, a SVM está só 0,7 ponto à frente do kNN, enquanto o resultado do kNN salta de uma divisão para outra de 96,0% a 99,1%. Mesmo assim, a SVM acerta mais em 16 das 20 divisões, e o kNN em 2. O que conta é a vantagem se repetir, não o tamanho da média.
Quando uma vantagem se repete? Se os dois modelos fossem igualmente bons, cada divisão sem empate seria como cara ou coroa. Uma moeda dá 16 a 2 menos de uma vez em 100 séries, e 10 a 7 com frequência. O lab chama uma vantagem de repetida quando um resultado assim sairia menos de uma vez em 100 séries. É o teste dos sinais. Os empates não pesam nele: simplesmente não são contados.
O mais importante: a ordem depende dos dados. Nos dígitos, a SVM acerta mais que a regressão logística em 17 das 20 divisões, e a regressão mais que a SVM em 3. Nos pinguins é o contrário: a regressão acerta mais em 9 divisões, a SVM em nenhuma, e 11 empatam. As duas vantagens passam no teste dos sinais. Nos dígitos, a SVM acerta mais que cada um dos outros modelos em pelo menos 16 divisões.
Tudo isso com as configurações padrão, sem ajuste, em conjuntos pequenos (de 150 a 1797 linhas) só com variáveis numéricas. Não é um veredito sobre os modelos em geral. Em tabelas maiores, com variáveis de tipos variados e depois de ajustar, a ordem pode ser outra (o boosting é tema da lição 5.3). A conclusão é outra: uma classificação não se copia da tabela de outra pessoa, ela se verifica nos seus dados.
O líder também é fácil de superestimar. Pegue o modelo com a melhor média nas divisões 1–10 e veja quem lidera nas divisões 11–20. Nas íris, nos vinhos e nos pinguins, ali já lidera outro modelo. Quando vários modelos estão próximos, o ruído decide em boa parte qual fica na frente, como na escolha das configurações na lição 3.5.
Jak to policzono
- Dados: Iris (Fisher, 1936), Wine (Aeberhard e Forina, 1992), Breast Cancer Wisconsin (Wolberg et al., 1993; 10 medidas “mean”) e Digits (Alpaydin e Kaynak, 1998), todos da UCI sob licença CC BY 4.0; Palmer Penguins (Gorman et al., 2014; Horst et al., 2020; licença CC0 1.0), 342 pinguins com 4 medidas corporais.
- Modelos: configurações padrão do scikit-learn, sem ajuste. Regressão logística (C = 1), kNN (k = 5), floresta aleatória (100 árvores), gradient boosting (100 árvores, passo 0,1, profundidade 3), SVM com kernel RBF (C = 1). A regressão, o kNN e a SVM recebem variáveis escalonadas em cada divisão usando só a parte de aprendizado.
- Concordância com o scikit-learn nas mesmas 20 divisões: a SVM acerta as mesmas linhas em cada divisão, a regressão e o kNN diferem no máximo em 3 linhas por divisão. As árvores do lab cortam cada variável em no máximo 32 intervalos, enquanto o scikit-learn constrói árvores exatas, então aqui as diferenças são maiores: nos tumores, a floresta tem o mesmo resultado em 3 das 20 divisões, e o boosting em 4. Com árvores exatas, a melhor média nos tumores é a do boosting, não a da SVM. As conclusões desta lição sobre os pares saem iguais nas duas versões.
- Divisões: 20 divisões estratificadas, 75% para aprender e 25% para validar, as mesmas para cada modelo. Aqui não há teste. Os 500 resultados foram calculados pelo código do lab, e o teste os recalcula do zero. O teste dos sinais é bilateral, nas divisões sem empate, com limiar de 1%.
Por que funciona
O teorema “não existe almoço grátis” (Wolpert, 1996) diz que, na média sobre todas as tarefas possíveis, nenhum algoritmo de aprendizado é melhor que outro. Um modelo só ganha quando as suas suposições combinam com os dados em questão: fronteiras retas para a regressão logística, vizinhos parecidos para o kNN, limiares em variáveis isoladas para as árvores. Por isso escolher um modelo é uma medição, não um saber de tabela.
A comparação em pares funciona porque a dificuldade de uma divisão afeta os dois modelos ao mesmo tempo e se cancela na diferença. Uma ressalva: 20 divisões do mesmo conjunto compartilham linhas, então não são 20 lançamentos de moeda independentes. Os testes estatísticos usuais sobre esses resultados tendem a ser confiantes demais (Dietterich, 1998). Por isso o limiar é rígido, e uma vantagem repetida é um bom indício, não uma prova.
Um modelo também pode ter o seu próprio acaso. A floresta sorteia linhas e variáveis para cada árvore. Nos dígitos, nas mesmas 20 divisões, a floresta com semente aleatória 1 acerta mais que a regressão em 15 divisões e menos em 5, e com a semente 4 mais em 11 e menos em 9. Com nenhuma semente de 1 a 5 essa vantagem passa no teste dos sinais. Por isso os exemplos desta lição se apoiam em modelos sem acaso: a regressão, o kNN e a SVM.
O código abaixo faz o mesmo no scikit-learn, com outras divisões e árvores exatas. A liderança muda: lá a SVM tem a melhor média em quatro conjuntos e a regressão logística nos pinguins. A direção dos pares desta lição se mantém, mas nem toda vantagem passa lá no teste dos sinais. Mais um motivo para não chamar de vitória uma diferença dentro do ruído.
Um erro comum
Verdadeiro ou falso: “um modelo com média 0,3 ponto mais alta é melhor”. Falso. Nos tumores, a SVM obtém 94,2% e o gradient boosting 93,9%, mas a SVM só acerta mais em 10 das 20 divisões, e o boosting em 7. No código abaixo, o mesmo par reparte as divisões 10 a 7, e a diferença das médias é 0,002.
Um segundo erro comum: “use sempre boosting, por exemplo XGBoost”. Neste zoológico, com as configurações padrão, nos vinhos a regressão logística acerta mais que o gradient boosting em 15 das 20 divisões, e o boosting mais que ela em 2. Não é um veredito contra o boosting, só contra escolher sem validação.
Quiz
Três perguntas para você se testar. Escolha uma resposta ou abra a resposta embaixo de cada pergunta. No teclado: as setas escolhem, Enter ou Espaço confirma.
Pontos-chave
- Nenhum modelo lidera em todos: a SVM vence a regressão logística nos dígitos (17 divisões contra 3) e perde nos pinguins (9 contra 0).
- Só a divisão já desloca o resultado em alguns pontos, então uma diferença de médias de 0,3 ponto pode ser um empate (10 divisões contra 7).
- Compare os modelos nas mesmas divisões e conte onde cada um ganha; uma vantagem pequena mas repetida também conta (a SVM à frente do kNN nos dígitos: 0,7 ponto, 16 a 2).
- Escolha pela validação nos seus dados, fique com o modelo mais simples no empate e olhe o teste uma vez, no fim.
Mais a fundo: fórmula, código, prática
A matemática
Para as divisões k = 1, …, K, a diferença num par é d_k = acc_A(k) − acc_B(k); olhamos a média d̄ = (1/K) · Σ_k d_k e o número de divisões com d_k > 0.
Variância da diferença: Var(A − B) = Var(A) + Var(B) − 2 · Cov(A, B). Quando uma divisão é difícil para os dois modelos ao mesmo tempo, a covariância é grande, então a diferença varia bem menos que cada resultado sozinho.
Teste dos sinais: o modelo A ganha em w divisões, B em l, sem contar empates. Com modelos igualmente bons, o número de vitórias de A segue Bin(w + l, ½), e p = min(1, 2 · P(X ≤ min(w, l))). Para 16 a 2, dá p ≈ 0,001.
No código (Python)
O mesmo experimento no scikit-learn: cinco modelos com as configurações padrão em cinco conjuntos e 20 divisões, depois quatro pares divisão a divisão, com o teste dos sinais.
import pandas as pd
from scipy.stats import binomtest
from sklearn.datasets import load_iris, load_wine, load_breast_cancer, load_digits
from sklearn.model_selection import StratifiedShuffleSplit, cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.svm import SVC
body = ["bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g"]
peng = pd.read_csv("data/raw/penguins.csv").dropna(subset=body)
cancer = load_breast_cancer()
data = {"iris": load_iris(return_X_y=True), "wine": load_wine(return_X_y=True), "cancer": (cancer.data[:, :10], cancer.target),
"penguins": (peng[body].values, peng["species"].values), "digits": load_digits(return_X_y=True)}
# o scaler fica dentro de cada pipeline, então aprende as médias só com a parte de aprendizado de cada divisão
models = {"logistic": make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000)),
"kNN": make_pipeline(StandardScaler(), KNeighborsClassifier()),
"forest": RandomForestClassifier(random_state=0),
"boosting": GradientBoostingClassifier(random_state=0),
"SVM": make_pipeline(StandardScaler(), SVC())}
splits = StratifiedShuffleSplit(n_splits=20, test_size=0.25, random_state=0)
acc = {}
for name, (X, y) in data.items():
acc[name] = {m: cross_val_score(model, X, y, cv=splits) for m, model in models.items()}
row = " | ".join(f"{m} {a.mean():.3f}" for m, a in acc[name].items())
best = max(acc[name], key=lambda m: acc[name][m].mean())
print(f"{name:8s} {row} best: {best}")
# teste dos sinais: só as divisões sem empate; com modelos igualmente bons, cada uma seria cara ou coroa
for name, a, b in [("digits", "SVM", "kNN"), ("digits", "SVM", "logistic"), ("penguins", "logistic", "SVM"), ("cancer", "SVM", "boosting")]:
d = acc[name][a] - acc[name][b]
win, lose = (d > 0).sum(), (d < 0).sum()
print(f"{name}: {a} beats {b} in {win} of 20 splits, loses in {lose}; sign test p = {binomtest(win, win + lose).pvalue:.3f}; mean difference {d.mean():.3f}")
Saída
iris logistic 0.955 | kNN 0.945 | forest 0.949 | boosting 0.947 | SVM 0.959 best: SVM
wine logistic 0.982 | kNN 0.964 | forest 0.981 | boosting 0.946 | SVM 0.986 best: SVM
cancer logistic 0.931 | kNN 0.938 | forest 0.930 | boosting 0.939 | SVM 0.942 best: SVM
penguins logistic 0.988 | kNN 0.985 | forest 0.978 | boosting 0.973 | SVM 0.983 best: logistic
digits logistic 0.969 | kNN 0.974 | forest 0.975 | boosting 0.964 | SVM 0.979 best: SVM
digits: SVM beats kNN in 14 of 20 splits, loses in 4; sign test p = 0.031; mean difference 0.006
digits: SVM beats logistic in 17 of 20 splits, loses in 3; sign test p = 0.003; mean difference 0.010
penguins: logistic beats SVM in 7 of 20 splits, loses in 1; sign test p = 0.070; mean difference 0.005
cancer: SVM beats boosting in 10 of 20 splits, loses in 7; sign test p = 0.629; mean difference 0.002
As divisões e a implementação das árvores diferem das do lab, então a liderança também: a SVM tem a melhor média em quatro conjuntos, a regressão logística nos pinguins. Aqui também nenhum modelo ganha em todos. A direção dos pares da lição se mantém: nos dígitos, a SVM vence a regressão em 17 das 20 divisões e o kNN em 14, e nos pinguins a regressão vence a SVM em 7 e perde em 1. Aqui só o primeiro par passa no teste dos sinais (p = 0,003). Os outros dois têm a mesma direção, mas poucas vitórias nessas divisões, então vale conferir uma conclusão tirada de um conjunto de divisões em outro. A SVM e o boosting voltam a repartir as divisões dos tumores 10 a 7.
Baixar o notebook (.ipynb). Abra no Jupyter ou envie para o Google Colab; ele baixa sozinho os dados que faltarem.
Para quem pratica
- Comece por uma referência (lição 1.3) e depois pegue alguns modelos de tipos diferentes: linear, vizinhos, árvores, kernel. Avalie todos nas mesmas divisões (
cross_validatecom um únicocv) e com o pré-processamento num pipeline (lição 4.6). - Olhe a dispersão e os pares, não só as médias. Confira uma vantagem com o teste dos sinais (
binomtestdo SciPy) nas divisões sem empate. No empate, escolha o modelo mais barato de manter ou mais fácil de explicar. - Ajuste só os finalistas (lição 3.5). As configurações padrão podem estar longe das melhores, sobretudo no boosting e nas SVMs.
- Trate as classificações “qual modelo, quando” da internet como uma lista de candidatos para validar, não como um veredito. Guarde o teste para o fim e olhe-o uma vez.
Isto foi útil?
Obrigado! Isso nos ajuda a melhorar.
Vá mais fundo no Atlas
Verbetes da enciclopédia sobre as ideias desta aula: