Para compreendermos a IA moderna, devemos começar com o machine learning clássico. Os princípios válidos para os modelos clássicos também são relevantes para as redes neurais mais avançadas. Exploraremos três modelos clássicos: vizinhos mais próximos, florestas aleatórias e máquinas de vetores de suporte. Neste primeiro artigo, apresentaremos os vizinhos mais próximos.
Vizinhos mais próximos
A figura a seguir mostra os exemplos de treinamento para um conjunto de dados composto de duas features (x0 e x1) e três classes (círculos, quadrados e triângulos). Cada forma na figura representa uma amostra do conjunto de treinamento. Essa figura é a ferramenta que usaremos para entender o modelo clássico vizinhos mais próximos.

Os classificadores chamados vizinhos mais próximos são os modelos mais simples, tão simples que nem têm modelo para treinar: os dados de treinamento são o modelo. Para atribuir um rótulo de classe a uma entrada nova e desconhecida, ele encontra a amostra de treinamento mais próxima à amostra desconhecida e retorna o rótulo dessa amostra.
A extensão natural do modelo vizinho mais próximo é “localiza as k amostras” de treinamento mais próximas da amostragem desconhecida. Comumente k é um número como 3, 5 ou 7, embora possa ser qualquer número. O modelo usa um sistema de votação da maioria: o rótulo de classe atribuído é o mais comum entre as k amostras de treinamento. Em caso de empate, o modelo seleciona aleatoriamente o rótulo.
Vamos classificar algumas entradas desconhecidas. A figura abaixo demonstra as amostras de treinamento, com duas amostras desconhecidas: losango e pentágono. Precisamos atribuir esses dois exemplos a uma das três classes: círculo, quadrado ou triângulo. A abordagem do modelo vizinho mais próximo recomenda localizar a amostra de treinamento mais próxima de cada amostra desconhecida. Para o losango, recomenda-se o quadrado em seu lado esquerdo; para o pentágono, o triângulo logo acima. O classificador vizinho mais próximo atribui a classe quadrado ao losango e a classe triângulo ao pentágono.

Vamos utilizar “localiza 3 amostras de treinamento mais próximas” para verificar o resultado do classificador. A classificação permanecerá a mesma? O código em Python a seguir demonstra a implementação do teste.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
# Configuração
np.random.seed(42)
num_samples = 30
# Gerar dados aleatórios para três classes
squares = np.random.rand(num_samples, 2)
circles = np.random.rand(num_samples, 2) + [1.5, 0]
triangles = np.random.rand(num_samples, 2) + [0.75, 1.5]
# Concatenar os dados e os rótulos
X = np.vstack([squares, circles, triangles])
y = ['quadrado'] * num_samples + ['circulo'] * num_samples + ['triangulo'] * num_samples
# Treinar o classificador KNN
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X, y)
# Posições fixas para losango e pentágono
diamond = np.array([[1.15, 0.75]])
type_diamond = knn.predict(diamond)[0]
pentagon = np.array([[1.75, 1.35]])
type_pentagon = knn.predict(pentagon)[0]
# Funções para desenhar formas personalizadas
def draw_shape(ax, shape, x, y, **kwargs):
if shape == 'square':
ax.add_patch(plt.Rectangle((x-0.05, y-0.05), 0.1, 0.1, fill=False, edgecolor='black'))
elif shape == 'circle':
ax.add_patch(plt.Circle((x, y), 0.05, fill=False, edgecolor='black'))
elif shape == 'triangle':
ax.add_patch(plt.Polygon([[x, y+0.06], [x-0.05, y-0.04], [x+0.05, y-0.04]],
closed=True, fill=False, edgecolor='black'))
elif shape == 'diamond':
ax.add_patch(plt.Polygon([[x, y+0.06], [x-0.05, y], [x, y-0.06], [x+0.05, y]],
closed=True, fill=True, edgecolor='black', facecolor='black'))
elif shape == 'pentagon':
angle = 2 * np.pi / 5
points = [(x + 0.06*np.cos(i*angle - np.pi/2), y + 0.06*np.sin(i*angle - np.pi/2)) for i in range(5)]
ax.add_patch(plt.Polygon(points, closed=True, fill=True, edgecolor='black', facecolor='black'))
# Plotagem
fig, ax = plt.subplots(figsize=(8, 8))
# Desenhar os dados de treino
for x, y_ in squares:
draw_shape(ax, 'square', x, y_)
for x, y_ in circles:
draw_shape(ax, 'circle', x, y_)
for x, y_ in triangles:
draw_shape(ax, 'triangle', x, y_)
# Desenhar o losango e pentágono
draw_shape(ax, 'diamond', diamond[0, 0], diamond[0, 1])
draw_shape(ax, 'pentagon', pentagon[0, 0], pentagon[0, 1])
# Adicionar texto de classificação
ax.text(diamond[0, 0]+0.05, diamond[0, 1], f'classificado como: {type_diamond}', fontsize=10)
ax.text(pentagon[0, 0]+0.05, pentagon[0, 1], f'classificado como: {type_pentagon}', fontsize=10)
# Configurando os rótulos dos eixos
plt.xlabel('$x_0$')
plt.ylabel('$x_1$')
# Configuração final do gráfico
ax.set_xlim(-0.2, 3)
ax.set_ylim(-0.2, 3)
ax.set_aspect('equal')
ax.set_title('Classificação com KNN (k=3)')
plt.grid(True)
plt.savefig('knn0.png', transparent=True)
plt.show()
O classificador atribui a classe quadrado ao losango, já que todas as três amostras de treinamento mais próximas são quadrados. Para o pentágono, os três vizinhos mais próximos são triângulos; o classificador atribui a classe triângulo ao pentágono.
Vamos retomar o conjunto de dados de algarismos, apresentado em Visão Geral da IA – Parte 2. Cada amostra de algarismo é um ponto único em um espaço de 784 dimensões. Temos 60 mil exemplos de treinamento e 10 mil amostras de teste, que utilizaremos para avaliar o modelo vizinho mais próximo. Aplicamos o treinamento 1-vizinho mais próximo com as 60 mil amostras de treinamento, depois com 6 mil, 600 e por último 60 amostras. Aplicamos as 10 mil amostras de teste em todos os diferentes conjuntos de amostras. A tabela a seguir apresenta a acurácia para cada tamanho de conjunto de treinamento.
| Tamanho do conjunto de treinamento | Acurácia (%) |
|---|---|
| 60.000 | 97 |
| 6.000 | 94 |
| 600 | 86 |
| 60 | 66 |
Para um teste com tamanho de somente 60 amostras, a acurácia de 66% é excelente! Mas como isso é possível? 60 amostras, em um espaço de 784 dimensões nos diz que o conjunto de treinamento tem poucos dados para preencher este espaço. Isso é conhecido como maldição da dimensionalidade: à medida que o número de dimensões aumenta, também aumenta (exponencialmente) o número de amostras necessárias para preencher o espaço.
Analisando a maldição da dimensionalidade, não deveria ser possível classificar corretamente algarismos quando temos apenas 60 amostras de treinamento em 784 dimensões. Então, como alcançamos bons resultados? Isso se deve ao conjunto de dados de algarismos e à similaridade entre os exemplos das diferentes classes. Todos os 5 se parecem 5. Embora existam 784 dimensões, a maioria dos algarismos de uma classe ficará relativamente próxima dos outros algarismos dessa classe. Os demais algarismos possivelmente estão agrupados de forma semelhante. Por isso, a amostra mais próxima tem mais chance de ser da mesma classe de algarismos. Ainda que tenhamos espaço de 784 dimensões, a dimensionalidade intrínseca está mais próxima a 21 dimensões, exigindo menos dados para um bom desempenho.
Isso não será sempre válido. Consideremos o CIFAR-10, um conjunto composto por 50 mil imagens pequenas e coloridas, de 32×32 pixels, com 10 classes diferentes (incluindo aviões, carros, caminhões, cachorros, gatos e pássaros). Se aplicarmos o classificador de vizinho mais próximo a ao CIFAR-10, os resultados serão muito inferiores (acurácia máxima de 35.4%, no conjunto total de amostras). Estas imagens são do tipo “imagem natural”, muito mais complexas do que as imagens simples dos algarismos MNIST: por isso devemos esperar que sejam de mais difícil classificação.
Nos dias de hoje, os modelos vizinhos mais próximos não são usados com frequência, por dois motivos. Primeiro, embora treinar um modelo vizinho mais próximo seja efetivamente instantâneo, já que não há nada para treinar, usá-lo é moroso, pois deve-se calcular a distância entre a amostra desconhecida e cada uma das amostras do conjunto de treinamento. E a operação de cálculo aumenta à medida que o número de amostras no conjunto de treinamento é elevado ao quadrado.
O segundo problema é comum a todos os modelos clássicos de machine learning. Estes modelos interpretam seus vetores de entrada como uma única entidade sem partes. Em muitos casos, não é o certo a se fazer. Por exemplo, ao escrever um 4, são usados múltiplos traços, e existem partes definidas que distinguem o número 4 do 8. Os modelos clássicos de machine learning não aprendem explicitamente essas partes ou em que local aparecem, ou que podem aparecer em múltiplos locais. Já as redes neurais convolucionais modernas aprendem. Resumindo, os modelos de vizinhos mais próximos são fáceis de entender e simples de treinar, mas lentos de usar e incapazes de compreender explicitamente a estrutura em suas entradas.
Referências
Kneusel, Ronald T.. Como a Inteligência Artificial Funciona: Da Magia à Ciência
Comments (0)