PDI+VC · Exercício de Programação

EP07_02 — 🟡 Normalização Z-score e Robustez do k-NN a Escalas Distintas

7.18.2 EP07_02 🟡 Normalização Z-score e Robustez do k-NN a Escalas Distintas

Este exercício revisita o classificador implementado no EP07_01, desta vez sob a ótica discutida na seção O Impacto da Escala e a Normalização de Características do capítulo: o k-NN decide com base na distância entre vetores, de modo que uma característica medida em uma escala muito maior do que as demais tende a dominar o cálculo da distância, mesmo quando ela não é a mais relevante para separar as classes.

Um sistema de inspeção registra, para cada peça, sua área (em pixels, podendo chegar a centenas ou milhares) e sua circularidade (sempre entre \(0\) e \(1\)). Você foi encarregado de classificar novas peças por k-NN de duas formas — com e sem a padronização Z-score apresentada no capítulo — e de reportar em quais casos as duas abordagens divergem.

7.18.2.1 📋 Diretrizes de Implementação

  1. Quantidade e parâmetro: Ler o inteiro \(N\) (número de exemplos de treinamento) e o inteiro ímpar \(k\).
  2. Exemplos de treinamento: Para cada um dos \(N\) exemplos, ler três valores: a área \(x_1\) (real), a circularidade \(x_2\) (real) e o rótulo \(r\) (inteiro, \(0\) ou \(1\)).
  3. Consultas: Ler o inteiro \(Q\) e, em seguida, as coordenadas \(x_1, x_2\) de cada consulta.
  4. Classificação sem normalização: Para cada consulta, classifique-a por k-NN diretamente sobre \((x_1, x_2)\), com distância euclidiana e as mesmas regras de desempate do EP07_01 (ordem de leitura para distâncias empatadas; vizinho mais próximo entre classes empatadas na votação).
  5. Parâmetros de normalização: Calcule a média \(\mu_j\) e o desvio-padrão populacional \(\sigma_j\) (divisão por \(N\), não por \(N-1\) — a mesma convenção adotada pela classe StandardScaler) de cada característica \(j \in \{1,2\}\), exclusivamente sobre o conjunto de treinamento.
  6. Padronização: Transforme cada característica de treinamento e de consulta por \[ z_j = \frac{x_j - \mu_j}{\sigma_j}. \] Se \(\sigma_j = 0\) (característica constante no treinamento), defina \(z_j = 0\) para todas as amostras dessa característica, evitando a divisão por zero.
  7. Classificação com normalização: Repita a classificação k-NN do item 4, agora sobre os vetores padronizados \((z_1, z_2)\), com as mesmas regras de desempate.
  8. Saída: Para cada consulta, na ordem de entrada, imprimir as duas classes previstas. Ao final, imprimir o número de consultas em que as duas classificações divergem.

7.18.2.2 📌 Restrições Computacionais

  • Ajuste apenas no treino: \(\mu_j\) e \(\sigma_j\) são calculados unicamente a partir do conjunto de treinamento e reaplicados às consultas — nunca recalculados a partir delas. Essa prática evita o vazamento de dados (data leakage), mencionado na seção de normalização do capítulo.
  • Desvio-padrão populacional: utilize \(\sigma_j = \sqrt{\frac{1}{N}\sum_i (x_{i,j}-\mu_j)^2}\), e não a versão amostral (divisão por \(N-1\)).
  • Característica constante: trate \(\sigma_j = 0\) como caso especial (item 6); não deve ocorrer erro de divisão por zero.
  • Regras de desempate: reutilize exatamente as convenções do EP07_01, tanto na seleção dos \(k\) vizinhos quanto na votação majoritária.

7.18.2.3 🧠 Fundamentação Teórica

Elemento Papel
Padronização Z-score Reescala cada característica para média \(0\) e desvio-padrão \(1\), tornando escalas heterogêneas comparáveis
Ajuste (fit) apenas no treino Garante que a avaliação sobre as consultas reflita apenas o que o modelo aprendeu no treinamento
Distância euclidiana sem normalização Dominada pela característica de maior amplitude — aqui, a área
Predição divergente Evidencia que a escala das características, e não apenas o algoritmo ou os dados, pode determinar a fronteira de decisão do k-NN

Este exercício reforça, de forma controlada, a razão pela qual o StandardScaler é aplicado antes do k-NN ao longo do capítulo: sem essa etapa, características de circularidade — mesmo sendo altamente discriminativas — podem ser praticamente ignoradas pelo classificador diante de uma característica de área com amplitude centenas de vezes maior.

7.18.2.4 📦 Especificação de Entrada e Saída (VPL)

Entrada:

  • Linha 1: Inteiros \(N\) e \(k\), separados por espaço.
  • Próximas \(N\) linhas: três valores por linha — \(x_1\), \(x_2\) (reais) e \(r\) (inteiro \(\in \{0,1\}\)), separados por espaço.
  • Próxima linha: inteiro \(Q\).
  • Próximas \(Q\) linhas: dois valores por linha — \(x_1\), \(x_2\) (reais) da consulta, separados por espaço.

Saída:

  • \(Q\) linhas, no formato SemNorm=<0|1> ComNorm=<0|1>, na ordem de entrada das consultas.
  • Última linha: Divergiu: <int>.

7.18.2.5 📌 Exemplos

Entrada Saída Observação
4 3
10 0.9 0
12 0.85 0
900 0.2 1
950 0.25 1
1
500 0.88
SemNorm=1 ComNorm=0
Divergiu: 1
Sem normalização, a área (escala de centenas) domina a distância e a consulta é classificada como classe 1. Após a padronização, a circularidade — muito mais próxima das amostras de classe 0 — passa a pesar de forma comparável, e a predição muda para 0.
2 1
0 0.5 0
100 0.5 1
1
60 0.5
SemNorm=1 ComNorm=1
Divergiu: 0
A circularidade é constante no treinamento (\(\sigma_2=0\)); pela regra do item 6, \(z_2=0\) para todas as amostras, e a classificação depende apenas da área em ambos os casos.
🎮 Simulador EP07_02: Normalização Z-score e Distância k-NN Padronização de Características
Cada exemplo possui duas características: área (px) e circularidade [0, 1]. Alterne a normalização e observe a mudança na classe prevista.
–
Figura 7.22: Simulador EP07_02: Efeito da Normalização Z-score na Distância k-NN
%%writefile EP07_02.py
# Código Python
Writing EP07_02.py
TestSuite("EP07_02.py").run()
✔️ EP07_02.cases já existe em casos/
📋 5 caso(s) carregado(s) de casos/EP07_02.cases

🔍 Testando Python: EP07_02.py
⚠️ EP07_02.py: Arquivo sem conteúdo (menos de 3 linhas). Testes ignorados.