Esta seção corresponde à seção 2.2.3 de James et al. (2023).
A seção anterior mediu o ajuste em distância: o quanto \(\hat f(x)\) erra de um \(y\) numérico. Quando \(Y\) é uma classe — doente ou não, spam ou não —, distância deixa de fazer sentido, e a régua muda: o que conta é se a previsão acertou o rótulo ou errou.
A taxa de erro
O análogo do MSE, para uma resposta qualitativa, é a taxa de erro: a fração das previsões que erram o rótulo.
\(\mathbb{1}(y_i \neq \hat y_i)\) vale 1 quando o classificador erra a observação \(i\) e 0 quando acerta; a média sobre as \(n\) observações é a proporção de erros. A mesma ressalva da seção anterior continua valendo, ponto por ponto: a taxa de erro que interessa é a de teste, medida sobre dado que não ajustou o classificador — a de treino só diz o quanto o classificador decorou o que já tinha visto, e cai mesmo quando essa memorização não ensinou nada sobre dado novo.
O classificador de Bayes
Existe uma regra que minimiza a taxa de erro esperada, e ela é simples de enunciar: para cada ponto \(x_0\), atribuir a classe mais provável dado \(X = x_0\).
Nenhuma outra regra faz melhor — atribuir qualquer classe que não seja a mais provável só pode aumentar a chance de errar aquele ponto. É por isso que essa regra tem nome próprio, classificador de Bayes, e sua taxa de erro tem nome próprio também: taxa de erro de Bayes, o piso que nenhum classificador fura, o análogo exato do \(\mathrm{Var}(\epsilon)\) da seção anterior.
Só que descrever o classificador de Bayes é mais fácil do que construí-lo: ele exige conhecer \(P(Y = j \mid X = x_0)\) de verdade, para todo \(x_0\) — a distribuição condicional exata de \(Y\) dado \(X\). Com dado real, ninguém tem essa distribuição; o que existe são \(n\) observações, e a distribuição que as gerou permanece desconhecida. É por isso que o classificador de Bayes, fora de um material como este, é inatingível: um padrão contra o qual comparar, nunca um classificador que alguém constrói. Aqui é diferente pelo mesmo motivo da seção anterior — o dado vai ser simulado, e quem simula escolhe \(P(Y \mid X)\).
Dois preditores, \(X_1\) e \(X_2\), uniformes em \([0, 10]\); a probabilidade condicional de \(Y=1\) é uma logística sobre uma combinação deles — tendência linear em \(x_2\) mais uma oscilação de seno em \(x_1\), a mesma forma de combinar reta e seno que gerou \(f\) na seção anterior:
O rótulo \(Y\) sai de um sorteio com essa probabilidade — rng.uniform(size=n) < p é exatamente um Bernoulli\((p)\). Trezentos pontos para treino, na mesma ordem de grandeza da seção anterior; vinte mil para teste, maior do que os cinco mil de lá, e a razão para o tamanho vem mais adiante, quando o teto de Bayes precisar ser medido com precisão contra o k-NN.
A fronteira de Bayes — onde \(P(Y=1\mid X=x)=1/2\), e as duas classes empatam — fica onde o argumento da logística zera: \(x_2 = 3\sin(x_1) + 5\), uma curva, não uma reta. Fora dessa curva, uma classe é sempre mais provável que a outra, mas nunca com certeza: em quase todo ponto do domínio, \(P(Y=1\mid X=x)\) fica entre 0 e 1, nunca exatamente em 0 ou 1 — há sempre uma chance da classe menos provável aparecer, e é essa sobreposição que faz a taxa de erro de Bayes ser maior que zero.
A taxa de erro de Bayes não precisa de nenhum sorteio para ser calculada: em cada ponto \(x\), o classificador de Bayes ainda erra com probabilidade \(\min\big(P(Y{=}1\mid X{=}x),\, 1 - P(Y{=}1\mid X{=}x)\big)\) — a chance da classe que ele não escolheu. A média dessa quantidade sobre o domínio inteiro, calculada numa grade fina, dá 13,26%: o piso exato, porque \(P(Y\mid X)\) é conhecida ponto a ponto. Aplicar a mesma regra de Bayes aos 20.000 pontos de teste — prever a classe mais provável em cada um, e comparar com o \(y\) que de fato saiu do sorteio — dá 13,32%, quase o mesmo número: a diferença é só o ruído de um sorteio finito em volta do valor exato.
k-vizinhos mais próximos
O classificador de Bayes conhece \(P(Y \mid X)\); o k-NN não conhece nada disso, e estima. Para um ponto \(x_0\), ele olha os \(k\) pontos de treino mais próximos e vota: a classe que aparece mais entre os vizinhos é a prevista. Essa votação é uma estimativa da própria quantidade que o classificador de Bayes usaria — a fração de vizinhos da classe 1 aproxima \(P(Y{=}1\mid X{=}x_0)\) —, só que calculada localmente, com \(k\) pontos, em vez de conhecida de antemão.
\(k\) decide o quanto essa estimativa é local. Com \(k\) pequeno, a vizinhança é minúscula, às vezes um só ponto, e a fronteira persegue cada observação de treino individualmente — variância alta, porque trocar a amostra de treino move a fronteira inteira. Com \(k\) grande, a vizinhança cresce até deixar de ser vizinhança: pontos distantes do \(x_0\) que está sendo classificado entram na votação, dilutem qualquer estrutura local, e a fronteira endurece até quase virar uma reta — viés alto, o mesmo preço que a reta pagava na seção anterior.
Setenta e cinco valores de \(k\) varridos, de 1 a 297, de quatro em quatro. Em \(k=1\), o erro de treino é 0% — cada ponto de treino é o próprio vizinho mais próximo de si mesmo, então a votação sempre acerta o rótulo que já tinha. O erro de teste em \(k=1\) não acompanha: a fronteira que decorou cada ponto de treino erra a vizinhança de um ponto novo com muito mais frequência. O menor erro de teste do varrimento inteiro sai em \(k=9\): 15,08%. Em nenhum dos 75 valores de \(k\) a taxa de erro de teste desce abaixo dos 13,26% calculados acima — nem no ponto que mais se aproxima, \(k=9\), que fica 1,82 ponto percentual acima (margem_pp). Com um conjunto de teste de poucas centenas de pontos, essa distância teria variância grande o bastante para a taxa de teste cruzar o piso por sorte da amostra, o mesmo risco que levou a seção anterior a medir o MSE contra cinco mil pontos em vez dos noventa que já tinha; vinte mil pontos de teste bastam para essa comparação não depender do sorteio.
A fronteira que cada k desenha
Três valores de \(k\), bem separados, mostram o que a tabela de erros já contou em número: \(k=1\), o mínimo do varrimento (\(k=9\)), e \(k=199\), perto do outro extremo.
k_grande =199k_tres = [1, k_minimo, k_grande]modelos_tres = [ KNeighborsClassifier(n_neighbors=k).fit(X_treino, y_treino) for k in k_tres]tabela_k = pd.DataFrame( {"treino": [float(np.mean(m.predict(X_treino) != y_treino)) for m in modelos_tres],"teste": [float(np.mean(m.predict(X_teste) != y_teste)) for m in modelos_tres], }, index=[f"k={k_tres[0]}", f"k={k_tres[1]} (menor erro de teste)", f"k={k_tres[2]}"],)tabela_k.round(4)
treino
teste
k=1
0.0000
0.2092
k=9 (menor erro de teste)
0.1433
0.1508
k=199
0.2667
0.2303
\(k=1\) decora o treino (0% de erro) e erra 20,92% do teste; \(k=199\) erra 26,67% do treino e 23,03% do teste, rígido demais para acompanhar a curva de \(3\sin(x_1) + 5\); \(k=9\) fica entre os dois em treino (14,33%) e vence os dois no teste (15,08%) — nem tão preso ao ruído de cada ponto quanto \(k=1\), nem tão achatado quanto \(k=199\).
Figura 41.1: Fronteiras de decisão do k-NN para k=1, k=9 e k=199 (verde), sobre os mesmos 300 pontos de treino coloridos pela classe verdadeira, com a fronteira de Bayes (roxo tracejado) por cima. k=1 dobra atrás de cada ponto; k=199 quase não acompanha a curvatura da fronteira verdadeira; k=9 é o que chega mais perto dela.
É a mesma curva em U da seção anterior, só que medida em taxa de erro em vez de MSE: \(k\) pequeno decora o treino e erra o teste por variância, \(k\) grande simplifica demais e erra por viés, e o meio-termo — aqui \(k=9\) — não elimina nenhuma das duas parcelas, só encontra a combinação que soma menos, sem nunca descer abaixo do piso que o classificador de Bayes marca. O compromisso é o mesmo; muda só a métrica que o mede.
James, Gareth, Daniela Witten, Trevor Hastie, Robert Tibshirani, e Jonathan Taylor. 2023. An Introduction to Statistical Learning with Applications in Python. Springer.