ML Atlas

Machine learning do zero · Aula 5.5 · 30 de 33 aulas prontas · 12 min

Máquinas de vetores de suporte e kernels

Em resumo

Uma SVM procura a faixa mais larga entre as classes. Quando C sobe de 0,01 para 100, ela encolhe de 3,9 para 0,15 cm e o teste quase não se mexe.

Aquecimento Duas perguntas de aulas anteriores. Um minuto, e a aula nunca fica bloqueada.
Da aula 5.4: Naive Bayes: suposição falsa, boas decisões Em versicolor, o comprimento e a largura da pétala se correlacionam com r = 0,80, e o modelo acerta 93,3% das flores de teste. O que se conclui?

Ver a resposta

Resposta certa: Para decidir, basta que a espécie certa receba o maior produto

A suposição falsa muda os valores dos produtos, mas raramente a ordem deles quando as espécies estão longe. O modelo com correlações acerta em média só um pouco mais.

Da aula 5.3: Gradient boosting: árvores que corrigem erros Verdadeiro ou falso: “mais rodadas de boosting sempre ajudam”.

Ver a resposta

Resposta certa: Falso, porque depois de um tempo as rodadas extras só corrigem ruído

O treino cai a cada rodada, o teste não. Com passo 1, na validação o melhor é 1 árvore, e 200 árvores dão 5944 no teste.

Duas espécies de íris, duas medidas da pétala. No treino, muitas retas as separam igualmente bem. Uma máquina de vetores de suporte (SVM, do inglês support vector machine) escolhe aquela em volta da qual fica a faixa vazia mais larga, a margem. As flores na borda da faixa, dentro dela ou do lado errado são os vetores de suporte. Só elas definem a fronteira: daria para apagar todas as outras flores e a fronteira continuaria a mesma. Quando as classes se sobrepõem, a faixa não pode ficar vazia, então a SVM paga uma penalidade por cada flor dentro da faixa ou do lado errado. O número C define o preço dessa penalidade. Um C pequeno permite uma faixa larga com muitas violações; um C grande exige manter as flores do lado certo, mesmo ao custo de uma faixa estreita.

Preveja, depois confira Uma SVM linear distingue íris versicolor de virginica por duas medidas da pétala. Quando C sobe de 0,01 para 100, a faixa encolhe de 3,9 cm para 0,15 cm, e só 4 flores seguram a fronteira em vez de 70. O que acontece com a acurácia nas 30 flores de teste?
Qual é o seu grau de certeza?

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: Quase não muda: com qualquer C o modelo acerta 26 ou 27 das 30

Quase igual: com os 9 valores de C o teste dá 26 ou 27 de 30. A faixa fica 26 vezes mais estreita, e o resultado muda uma flor. Em outras 20 divisões, a acurácia de teste com diferentes C varia no máximo 2 flores de 30.

Experimente

  • Comece pelas pétalas com C = 100. Quantas flores seguram a fronteira, e qual a largura da faixa?
  • Diminua C. Com qual C a validação é melhor, e com qual a faixa é mais larga para quase o mesmo resultado?
  • Troque para as sépalas. Algum C separa as espécies aqui?
  • Vá para os vinhos. Compare “só x”, as variáveis √2·x e x², e o kernel (x·z + 1)². Depois passe ao kernel RBF e leve γ (a rapidez com que a semelhança de dois vinhos cai quando eles se afastam) até 1000.

Depois de conferir no lab, vamos dar nome ao que você vê.

A ideia em palavras simples

Uma SVM não calcula probabilidades como a regressão logística. Ela desenha uma fronteira e duas linhas paralelas a ela, uma de cada lado. A faixa entre elas deve ser a mais larga possível, e as flores devem ficar fora dela, do seu próprio lado. Uma flor que não se encaixa recebe uma penalidade igual a quanto ela entrou na faixa. É a perda de dobradiça (hinge loss). O modelo busca um equilíbrio: uma faixa larga de um lado, C vezes a soma das penalidades do outro.

Com C = 0,01 as penalidades quase não custam nada. A faixa tem 3,9 cm, e todas as 70 flores de treino são vetores de suporte: cada uma move a fronteira um pouco. Com C = 100 cada violação sai cara. A faixa tem 0,15 cm, e 4 flores coladas na fronteira a seguram. Enquanto isso, o teste muda uma flor. Nas pétalas, as espécies estão longe o bastante para que quase qualquer reta razoável acerte as mesmas flores.

C se escolhe como qualquer hiperparâmetro: pela validação, não pelo teste. O lab faz uma validação cruzada em 5 partes dentro das 70 flores de treino. A melhor sai com C = 10: 69 de 70. Com C = 0,1 são 68 de 70, e a faixa tem 1,4 cm em vez de 0,34 cm. Uma flor de diferença é ruído na validação, e uma faixa mais larga apoia a fronteira em mais flores. O menor C exagera no sentido oposto: 64 de 70.

A fronteira não precisa ser reta. Nos vinhos perguntamos só se um vinho é do cultivar 2 ou de outro, então há duas classes. O cultivar 2 fica no meio do eixo dos flavonoides: o cultivar 1 tem 2,98 em média, o cultivar 2 2,08 e o cultivar 3 0,78. Um único limiar não recorta o meio, então a SVM linear prefere não apontar o cultivar 2 em lugar nenhum. Validação: 60,0%, o mesmo que responder “sempre outro cultivar”. Vamos trocar x por duas variáveis: √2·x e x². Os vinhos caem numa parábola, e uma reta no plano (√2·x, x²) são dois limiares no eixo, ou seja, um intervalo. A validação sobe para 72,0%.

Um kernel faz o mesmo sem adicionar colunas. A SVM só precisa de produtos escalares de pares de exemplos. O produto escalar é a soma dos produtos das coordenadas correspondentes de dois exemplos; a SVM o usa como medida da semelhança entre eles. O kernel (x·z + 1)² dá exatamente o produto escalar dos vetores (1, √2·x, x²), então a fronteira sai idêntica à das variáveis √2·x e x². É o truque do kernel. O kernel RBF (de radial basis function, função de base radial) exp(−γ(x − z)²) mede a semelhança pela distância: γ diz a rapidez com que a semelhança cai quando dois vinhos se afastam. Ele equivale a infinitas variáveis desse tipo. Com γ = 3 a validação é 78,4%, a melhor dos oito valores de γ, e o teste dá depois 84,9%. Com γ = 0,3, 1 e 10 a validação é 76,8%, só 2 vinhos de 125 a menos. Como com C nas íris, é praticamente um empate. Com γ = 1000 o treino sobe para 89,6% e a validação cai para 69,6%. A fronteira então se parte em 11 intervalos ajustados a vinhos isolados. O teste mais alto, 86,8%, sai com γ = 100, mas escolher pelo teste é escolher com os dados que você usa para avaliar.

Jak to policzono
  • Íris: Iris (Fisher, 1936; UCI, licença CC BY 4.0), 100 flores versicolor e virginica. Medidas em centímetros sem escalonamento, porque as duas variáveis têm a mesma unidade. Divisão estratificada: 70 flores para aprender, 30 para o teste.
  • Vinhos: Wine (Aeberhard e Forina, 1992; UCI, licença CC BY 4.0), 178 vinhos, só o teor de flavonoides, C = 1. Divisão: 125 vinhos para aprender, 53 para o teste. Os escores z vêm só dos vinhos de aprendizado, e na validação dos vinhos de aprendizado de cada parte.
  • Validação: validação cruzada estratificada em 5 partes dentro do treino. Modelo: uma SVM de margem suave; os números batem com SVC do scikit-learn.

Por que funciona

Uma faixa larga é regularização, como a penalidade ridge da lição 3.4. A faixa tem largura 2/‖w‖, então faixa larga significa pesos pequenos e uma fronteira que depende menos de flores isoladas. A margem com penalidade por violações foi descrita por Cortes e Vapnik (1995). O truque do kernel chegou antes às SVMs, com Boser, Guyon e Vapnik (1992): como o modelo só usa produtos escalares, cada um pode ser trocado por um kernel.

Que C mude a geometria mais que o resultado não é acaso de uma divisão. Em outras 20 divisões das íris, a acurácia de teste com os 9 valores de C varia no máximo 2 flores de 30, enquanto a faixa encolhe de 3,8–4,1 cm para 0,17–0,36 cm.

O kernel RBF mede distâncias, então as unidades importam. Os vinhos têm 13 medidas: a prolina chega a 1680, e a tonalidade no máximo a 1,71. Sem escalonamento, a distância é quase só prolina. Uma SVM RBF com as 13 medidas acerta então, em 20 divisões, 67,2% dos vinhos de validação em média. Com um escalonamento aprendido só na parte de aprendizado: 97,9%.

Um erro comum

Verdadeiro ou falso: “use sempre o kernel RBF, ele é o mais flexível”. Falso. Nas pétalas das íris, uma SVM linear e uma SVM RBF, cada uma com as configurações escolhidas pela validação, acertam em média 28,5 de 30 flores de teste em 20 divisões. A RBF é melhor em 1 divisão e pior em 1. A fronteira aqui é quase reta, então a flexibilidade não traz nada e custa algo: dois hiperparâmetros para ajustar em vez de um e um sobreajuste mais fácil (γ = 1000 nos vinhos). No código abaixo a linear tem 0,950, a RBF 0,947, e a RBF é melhor em 2 divisões e pior em 4.

A lição prática: comece com um kernel linear ou com uma regressão logística. Recorra ao RBF quando a validação mostrar que a fronteira não é reta, como nos vinhos.

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.

1. Quais flores definem a fronteira de uma SVM linear?
Ver a resposta

Resposta certa: Os vetores de suporte: flores na borda, dentro da faixa ou além

As outras flores poderiam ser removidas sem mudar a fronteira. Com C = 100, 4 flores de 70 a seguram.

2. C sobe de 0,01 para 100, a faixa encolhe de 3,9 para 0,15 cm e o teste fica em 26–27 de 30. O que se conclui?
Ver a resposta

Resposta certa: C muda a geometria mais que o resultado: as espécies estão longe

Nas pétalas, quase qualquer reta razoável acerta as mesmas flores. Mesmo aqui o menor C tem na validação 64 de 70 contra as melhores 69, então escolha C pela validação de qualquer forma.

3. Verdadeiro ou falso: “use sempre o kernel RBF, ele é o mais flexível”.
Ver a resposta

Resposta certa: Falso: nas pétalas a linear acerta o mesmo, e o RBF exige mais ajuste

Em 20 divisões as duas acertam em média 28,5 de 30. Um γ grande leva ao sobreajuste: nos vinhos com γ = 1000, treino 89,6% e validação 69,6%.

Pontos-chave

  • Uma SVM escolhe a fronteira com a faixa mais larga; só os vetores de suporte a definem.
  • C é o preço das violações: de C = 0,01 a 100 a faixa encolhe de 3,9 para 0,15 cm e o teste quase não se mexe (26–27 de 30).
  • Um kernel dá fronteiras que não são retas sem calcular variáveis novas; (x·z + 1)² equivale exatamente às variáveis √2·x e x².
  • Escolha C, o kernel e γ pela validação. O RBF sobreajusta com γ grande e erra muito mais sem escalonamento.

Mais a fundo: fórmula, código, prática

A matemática

Margem suave: minimizamos ½‖w‖² + C · Σᵢ ξᵢ sujeito a yᵢ(w·xᵢ + b) ≥ 1 − ξᵢ e ξᵢ ≥ 0. A faixa tem largura 2/‖w‖, e ξᵢ = max(0, 1 − yᵢ f(xᵢ)) é a perda de dobradiça.

Na forma dual f(x) = Σᵢ αᵢ yᵢ K(xᵢ, x) + b com 0 ≤ αᵢ ≤ C; os vetores de suporte são os exemplos com αᵢ > 0. O kernel polinomial K(x, z) = (x·z + 1)² = φ(x)·φ(z) para φ(x) = (1, √2·x, x²), o kernel RBF K(x, z) = exp(−γ‖x − z‖²).

No código (Python)

O mesmo experimento no scikit-learn: a faixa e os vetores de suporte com três valores de C, depois uma SVM linear e uma RBF, cada uma com as configurações escolhidas pela validação, em 20 divisões, e por fim os vinhos sem e com escalonamento.

import numpy as np
from sklearn.datasets import load_iris, load_wine
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV, cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

iris = load_iris(as_frame=True)
keep = iris.target > 0
X, y = iris.data.loc[keep, ["petal length (cm)", "petal width (cm)"]], iris.target[keep]
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, stratify=y, random_state=0)
for C in [0.01, 1, 100]:
    m = SVC(kernel="linear", C=C).fit(X_tr, y_tr)
    print(f"C = {C:>6}: band {2 / np.linalg.norm(m.coef_):.2f} cm, {m.n_support_.sum()} support vectors of {len(y_tr)}, test {m.score(X_te, y_te):.3f}")
grids = {"linear": {"svc__kernel": ["linear"], "svc__C": [0.01, 0.1, 1, 10, 100]},
         "RBF": {"svc__kernel": ["rbf"], "svc__C": [0.1, 1, 10, 100], "svc__gamma": [0.01, 0.1, 1, 10]}}
test = {k: [] for k in grids}
for seed in range(20):
    X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, stratify=y, random_state=seed)
    cv = StratifiedKFold(5, shuffle=True, random_state=seed)
    for k, grid in grids.items():
        search = GridSearchCV(make_pipeline(StandardScaler(), SVC()), grid, cv=cv).fit(X_tr, y_tr)
        test[k].append(search.score(X_te, y_te))
lin, rbf = np.array(test["linear"]), np.array(test["RBF"])
print(f"20 splits, settings chosen in validation: test linear {lin.mean():.3f}, RBF {rbf.mean():.3f}; RBF better {(rbf > lin).sum()}, worse {(rbf < lin).sum()}, equal {(rbf == lin).sum()}")
wine = load_wine()
cv = StratifiedKFold(5, shuffle=True, random_state=0)
for name, model in [("raw", SVC()), ("scaled inside each fold", make_pipeline(StandardScaler(), SVC()))]:
    print(f"wine, RBF SVM, {name}: validation {cross_val_score(model, wine.data, wine.target, cv=cv).mean():.3f}")

Saída

C =   0.01: band 4.21 cm, 70 support vectors of 70, test 1.000
C =      1: band 0.71 cm, 22 support vectors of 70, test 1.000
C =    100: band 0.37 cm, 12 support vectors of 70, test 1.000
20 splits, settings chosen in validation: test linear 0.950, RBF 0.947; RBF better 2, worse 4, equal 14
wine, RBF SVM, raw: validation 0.657
wine, RBF SVM, scaled inside each fold: validation 0.983

A divisão é diferente da do lab, então os números também são um pouco diferentes. O quadro é o mesmo: a faixa encolhe de 4,21 para 0,37 cm e o teste não muda (1,000). Em 20 divisões o kernel RBF não supera o linear (0,947 contra 0,950). Sem escalonamento a SVM tem 0,657 nos vinhos; com escalonamento dentro de cada parte, 0,983.

Para quem pratica
  • No scikit-learn: SVC(kernel="linear") e SVC(kernel="rbf") (por padrão gamma="scale"), e para conjuntos grandes LinearSVC, que aprende muito mais rápido. Segundo a documentação, o tempo de treino do SVC cresce pelo menos de forma quadrática com o número de exemplos, então com dezenas de milhares de linhas ele pode ficar impraticável.
  • Escalone sempre as variáveis num pipeline: make_pipeline(StandardScaler(), SVC()). O escalonador do pipeline aprende só com a parte de aprendizado de cada validação (lição 4.6).
  • Ajuste C e γ juntos, numa grade em escala logarítmica (GridSearchCV, lição 3.5). Um C grande e um γ grande são dois caminhos para o sobreajuste.
  • Uma SVM não dá probabilidades diretamente. SVC(probability=True) as ajusta com uma calibração à parte na validação cruzada (lição 2.4), então demora mais para aprender.

Vá mais fundo no Atlas

Verbetes da enciclopédia sobre as ideias desta aula: