html
Compreendendo K-Vizinhos Mais Próximos (KNN) para Classificação e Regressão
Índice
- Introdução aos K-Vizinhos Mais Próximos
- Como o KNN Funciona
- Escolhendo o Valor de 'K' Adequado
- KNN para Classificação
- KNN para Regressão
- Vantagens e Desvantagens do KNN
- Implementando KNN em Python
- Exemplo Prático
- Conclusão
- Referências
1. Introdução aos K-Vizinhos Mais Próximos
K-Vizinhos Mais Próximos (KNN) é um algoritmo de aprendizado de máquina supervisionado simples, mas poderoso, usado para tarefas de classificação e regressão. A ideia central é prever o rótulo de um novo ponto de dados com base nos rótulos de seus 'K' vizinhos mais próximos no espaço de características.
Por que KNN?
- Simplicidade: Fácil de entender e implementar.
- Sem Fase de Treinamento: KNN é um aprendiz preguiçoso, o que significa que não treina explicitamente um modelo, mas toma decisões com base em todo o conjunto de dados.
- Versatilidade: Aplicável a vários tipos de problemas, incluindo classificação, regressão e até detecção de anomalias.
2. Como o KNN Funciona
O KNN opera com base no princípio de que pontos de dados semelhantes provavelmente terão resultados semelhantes. Aqui está uma explicação passo a passo de como o algoritmo funciona:
Representação de Dados
Imagine um espaço bidimensional onde cada ponto de dados representa um carro com base em duas características:
- Tempo de Fabricação (Eixo X)
- Custo de Fabricação (Eixo Y)
Os pontos de dados são codificados por cores:
- Pontos Vermelhos: Carros a Gasolina
- Pontos Azuis: Carros Elétricos
Métricas de Distância
Para determinar a "proximidade" dos pontos de dados, o KNN utiliza métricas de distância. As métricas mais comumente usadas são:
- Distância Euclidiana
\[
d(p, q) = \sqrt{\sum_{i=1}^{n} (q_i - p_i)^2}
\]
- Usado Quando: Os dados estão em um espaço contínuo.
- Dica Profissional: A distância euclidiana é a métrica padrão em muitas implementações de KNN, incluindo scikit-learn.
- Distância de Manhattan
\[
d(p, q) = \sum_{i=1}^{n} |q_i - p_i|
\]
- Usado Quando: Os dados são semelhantes a uma grade e o movimento é restrito a caminhos horizontais e verticais.
- Distância de Minkowski
Uma generalização tanto das distâncias Euclidiana quanto de Manhattan.
\[
d(p, q) = \left( \sum_{i=1}^{n} |q_i - p_i|^p \right)^{1/p}
\]
- Quando \( p = 1 \): Equivalente à distância de Manhattan.
- Quando \( p = 2 \): Equivalente à distância Euclidiana.
3. Escolhendo o Valor de 'K' Adequado
O parâmetro 'K' determina o número de vizinhos a serem considerados ao fazer uma previsão. Selecionar o valor de 'K' ideal é crucial para o desempenho do algoritmo KNN.
Impacto do 'K'
- 'K' Pequeno (e.g., K=1):
- Mais sensível a ruídos.
- Pode levar ao sobreajuste.
- 'K' Grande (e.g., K=20):
- Fronteira de decisão mais suave.
- Pode subajustar ao simplificar demais os dados.
Melhores Práticas
- Validação Cruzada: Use técnicas como validação cruzada para encontrar o valor de 'K' que proporciona a melhor acurácia.
- Números Ímpares: Ao lidar com classificação binária, usar valores ímpares de 'K' ajuda a evitar empates.
4. KNN para Classificação
Na classificação, o KNN atribui à nova ponto de dados a classe mais comum entre seus 'K' vizinhos mais próximos.
Exemplo de Cenário
Considere um novo ponto de dados de carro com tempo e custo específicos de fabricação. O algoritmo KNN irá:
- Calcular a distância deste ponto para todos os outros pontos no conjunto de dados.
- Identificar os 'K' vizinhos mais próximos.
- Atribuir a classe (Elétrico ou a Gasolina) com base na votação da maioria entre esses vizinhos.
Sensibilidade ao 'K'
Como demonstrado no transcrito, variar 'K' pode mudar o resultado da classificação. Por exemplo:
- K=1: O novo ponto é classificado com base em seu único vizinho mais próximo.
- K=5: A votação da maioria entre cinco vizinhos determina a classificação.
5. KNN para Regressão
Enquanto o KNN é predominantemente usado para classificação, ele também pode realizar tarefas de regressão ao prever o valor médio dos 'K' vizinhos mais próximos.
Desafios na Regressão
- Sobreajuste: Valores mais baixos de 'K' podem levar ao sobreajuste.
- Subajuste: Valores mais altos de 'K' podem simplificar demais o modelo.
Informações sobre Implementação
No Notebook Jupyter fornecido, a regressão KNN foi aplicada para prever preços de diamantes. Aqui está uma visão geral:
- Pré-processamento de Dados:
- Mapeou variáveis categóricas para valores numéricos.
- Escalou as características usando padronização.
- Treinamento do Modelo:
- Treinou o regressor KNN com valores variados de 'K' para determinar o desempenho ótimo.
- Avaliação:
- Alcançou uma pontuação de acurácia máxima de aproximadamente 98,05% em K=4.
- Visualizou preços reais vs. previstos usando Plotly para melhor interpretabilidade.
6. Vantagens e Desvantagens do KNN
Vantagens
- Simples e Intuitivo: Fácil de entender e implementar.
- Sem Fase de Treinamento: Reduz o custo computacional durante o treinamento.
- Adaptável: Adequado para tanto classificação quanto regressão.
Desvantagens
- Computacionalmente Intensivo: Faz previsões usando todo o conjunto de dados, o que pode ser lento para grandes conjuntos de dados.
- Sensível a Características Irrelevantes: Características irrelevantes ou redundantes podem degradar o desempenho.
- Escolha de 'K': Selecionar o valor ótimo de 'K' pode ser desafiador.
7. Implementando KNN em Python
Utilizar a biblioteca scikit-learn do Python simplifica a implementação do KNN. Abaixo, delineamos as etapas principais desde o pré-processamento de dados até a avaliação do modelo.
Pré-processamento de Dados
Antes de aplicar o KNN, é essencial preparar os dados:
- Tratamento de Variáveis Categóricas:
- Converter dados de texto categóricos em valores numéricos usando dicionários de mapeamento.
12345678
cut_dict = {'Fair': 1, 'Good': 2, 'Very Good': 3, 'Premium': 4, 'Ideal': 5}clarity_dict = {'I1': 1, 'SI2': 2, 'SI1': 3, 'VS2': 4, 'VS1': 5, 'VVS2': 6, 'VVS1': 7, 'IF': 8}color_dict = {'D':7, 'E':6, 'F':5, 'G':4, 'H':3, 'I':2, 'J':1} df['cut'] = df['cut'].map(cut_dict)df['clarity'] = df['clarity'].map(clarity_dict)df['color'] = df['color'].map(color_dict)df = df.drop('Unnamed: 0', axis=1)
- Escalamento de Características:
- Normalizar o conjunto de características para garantir que todas as características contribuam igualmente para os cálculos de distância.
123456
from sklearn import preprocessing X = df.drop(['price'], axis=1).valuesX = preprocessing.scale(X)y = df['price'].valuesy = preprocessing.scale(y)
Treinamento e Avaliação do Modelo
- Divisão do Conjunto de Dados:
12345678
from sklearn.utils import shuffle df = shuffle(df, random_state=42)test_size = 200X_train = X[:-test_size]y_train = y[:-test_size]X_test = X[-test_size:]y_test = y[-test_size:]
- Treinamento do Regressor KNN:
1234567
from sklearn.neighbors import KNeighborsRegressor score = []for k in range(1, 20): clf = KNeighborsRegressor(n_neighbors=k, weights='distance', p=1) clf.fit(X_train, y_train) score.append(clf.score(X_test, y_test))
- Visualizando o Desempenho:
12345678910111213141516
import plotly.graph_objs as gofrom plotly.offline import iplot trace0 = go.Scatter( y=score, x=np.arange(1, len(score)+1), mode='lines+markers', marker=dict(color='rgb(100, 200, 150)'))layout = go.Layout( title='Valor K vs. Acurácia', xaxis=dict(title='Valor K', tickmode='linear'), yaxis=dict(title='Pontuação'))fig = go.Figure(data=[trace0], layout=layout)iplot(fig, filename='basic-line')
- Determinando o 'K' Ótimo:
12
k_max = score.index(max(score)) + 1print(f"Em K = {k_max}, Máxima Acurácia = {max(score) * 100:.2f}%")
Saída:
1
Em K = 4, Máxima Acurácia = 98.05%
- Avaliação Final do Modelo:
1234
clf = KNeighborsRegressor(n_neighbors=50)clf.fit(X_train, y_train)print(clf.score(X_test, y_test))y_pred = clf.predict(X_test)
Saída:
1
0.9543611406331687
- Comparando Preços Reais vs. Previstos:
1234567891011121314151617181920212223242526
import plotly.graph_objs as gofrom plotly.offline import iplot trace0 = go.Scatter( y=y_test, x=np.arange(200), mode='lines+markers', name='Preço Real', marker=dict(color='rgb(110, 10, 150)')) trace1 = go.Scatter( y=y_pred, x=np.arange(200), mode='lines+markers', name='Preço Previsto', line=dict(color='rgb(200, 50, 10)', dash='dot')) layout = go.Layout( xaxis=dict(title='Índice'), yaxis=dict(title='Preço Normalizado')) figure = go.Figure(data=[trace0, trace1], layout=layout)iplot(figure)
Esta visualização ajuda na avaliação da precisão da previsão do modelo ao sobrepor os valores de preços reais e previstos.
8. Exemplo Prático
Vamos passar por uma implementação prática usando a biblioteca scikit-learn do Python, conforme delineado no Notebook Jupyter fornecido.
Passo 1: Importando Bibliotecas Necessárias
12345678
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsfrom sklearn import preprocessing, utilsfrom sklearn.neighbors import KNeighborsRegressorimport plotly.graph_objs as gofrom plotly.offline import iplot
Passo 2: Carregando e Explorando o Conjunto de Dados
1234
df = pd.read_csv('diamonds.csv')print(df.head())sns.FacetGrid(df, hue='cut', height=6).map(sns.distplot, 'price').add_legend()plt.show()
Passo 3: Pré-processamento de Dados
Converter variáveis categóricas para numéricas e escalar as características.
12345678
cut_dict = {'Fair': 1, 'Good': 2, 'Very Good': 3, 'Premium': 4, 'Ideal': 5}clarity_dict = {'I1': 1, 'SI2': 2, 'SI1': 3, 'VS2': 4, 'VS1': 5, 'VVS2': 6, 'VVS1': 7, 'IF': 8}color_dict = {'D':7, 'E':6, 'F':5, 'G':4, 'H':3, 'I':2, 'J':1} df['cut'] = df['cut'].map(cut_dict)df['clarity'] = df['clarity'].map(clarity_dict)df['color'] = df['color'].map(color_dict)df = df.drop('Unnamed: 0', axis=1)
Passo 4: Escalamento de Características e Embaralhamento de Dados
12345
df = utils.shuffle(df, random_state=42)X = df.drop(['price'], axis=1).valuesX = preprocessing.scale(X)y = df['price'].valuesy = preprocessing.scale(y)
Passo 5: Dividindo o Conjunto de Dados
12345
test_size = 200X_train = X[:-test_size]y_train = y[:-test_size]X_test = X[-test_size:]y_test = y[-test_size:]
Passo 6: Treinando o Regressor KNN e Avaliando o Desempenho
12345
score = []for k in range(1, 20): clf = KNeighborsRegressor(n_neighbors=k, weights='distance', p=1) clf.fit(X_train, y_train) score.append(clf.score(X_test, y_test))
Passo 7: Visualizando as Pontuações de Acurácia
12345678910111213
trace0 = go.Scatter( y=score, x=np.arange(1, len(score)+1), mode='lines+markers', marker=dict(color='rgb(100, 200, 150)'))layout = go.Layout( title='Valor K vs. Pontuação de Acurácia', xaxis=dict(title='Valor K', tickmode='linear'), yaxis=dict(title='Pontuação'))fig = go.Figure(data=[trace0], layout=layout)iplot(fig, filename='basic-line')
Passo 8: Determinando o Valor 'K' Ótimo
12
k_max = score.index(max(score)) + 1print(f"Em K = {k_max}, Máxima Acurácia = {max(score) * 100:.2f}%")
Passo 9: Treinamento Final do Modelo e Previsão
1234
clf = KNeighborsRegressor(n_neighbors=50)clf.fit(X_train, y_train)print(clf.score(X_test, y_test))y_pred = clf.predict(X_test)
Passo 10: Comparando Valores Reais vs. Previsto
1234567891011121314151617181920212223
trace0 = go.Scatter( y=y_test, x=np.arange(200), mode='lines+markers', name='Preço Real', marker=dict(color='rgb(110, 10, 150)')) trace1 = go.Scatter( y=y_pred, x=np.arange(200), mode='lines+markers', name='Preço Previsto', line=dict(color='rgb(200, 50, 10)', dash='dot')) layout = go.Layout( xaxis=dict(title='Índice'), yaxis=dict(title='Preço Normalizado')) figure = go.Figure(data=[trace0, trace1], layout=layout)iplot(figure)
Os gráficos gerados fornecem uma representação visual de quão bem o modelo KNN prevê os preços dos diamantes com base no valor de 'K' selecionado.
9. Conclusão
O algoritmo K-Vizinhos Mais Próximos é uma ferramenta de aprendizado de máquina versátil e direta, adequada para várias aplicações em classificação e regressão. Sua eficácia depende amplamente da escolha de 'K' e da métrica de distância utilizada. O pré-processamento adequado dos dados e o escalonamento de características são etapas cruciais para melhorar o desempenho do modelo. Embora o KNN seja computacionalmente intensivo para conjuntos de dados grandes, sua simplicidade o torna um excelente ponto de partida para profissionais de aprendizado de máquina.
10. Referências
Esperamos que este guia tenha proporcionado uma compreensão clara do algoritmo K-Vizinhos Mais Próximos. Fique ligado para mais tutoriais aprofundados e insights sobre técnicas de aprendizado de máquina.