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.
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.
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: 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
SVCdo 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.
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.
Baixar o notebook (.ipynb). Abra no Jupyter ou envie para o Google Colab; ele baixa sozinho os dados que faltarem.
Para quem pratica
- No scikit-learn:
SVC(kernel="linear")eSVC(kernel="rbf")(por padrãogamma="scale"), e para conjuntos grandesLinearSVC, que aprende muito mais rápido. Segundo a documentação, o tempo de treino doSVCcresce 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.
Isto foi útil?
Obrigado! Isso nos ajuda a melhorar.
Vá mais fundo no Atlas
Verbetes da enciclopédia sobre as ideias desta aula: