Evaluation and Metrics
# ================================================
# PROJETO DE CLASSIFICAÇÃO: KNN e K-MEANS
# Dataset: Global Tech Gadget Consumption
# Variável alvo: E-WASTE (Baixo, Médio, Alto)
# Bibliotecas: pandas, numpy, matplotlib, sklearn
# ================================================
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.cluster import KMeans
from sklearn.metrics import (
accuracy_score,
confusion_matrix,
classification_report
)
from sklearn.decomposition import PCA
# ===========================================================
# 1. EXPLORAÇÃO DOS DADOS
# ===========================================================
df = pd.read_csv("/content/Global_Tech_Gadget_Consumption.csv")
print("Preview da base:")
display(df.head())
print("\nInformações gerais:")
print(df.info())
print("\nResumo estatístico:")
display(df.describe())
# Criar variável categórica-alvo
df["EWaste_Class"] = pd.qcut(
df["E-Waste Generated (Metric Tons)"],
q=3,
labels=["Baixo", "Medio", "Alto"]
)
print("\nDistribuição da classe alvo:")
print(df["EWaste_Class"].value_counts())
# Visualização da distribuição
df["EWaste_Class"].value_counts().plot(kind="bar")
plt.title("Distribuição das Classes de E-Waste")
plt.show()
# ===========================================================
# 2. PREPARAÇÃO DOS DADOS
# ===========================================================
# Features numéricas
X = df.select_dtypes(include=[np.number]).drop(
columns=["E-Waste Generated (Metric Tons)"], # evitar leakage
errors="ignore"
)
y = df["EWaste_Class"]
# Normalização
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Separação treino/teste
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.3, random_state=42, stratify=y
)
# ===========================================================
# 3. MODELO KNN (Supervisionado)
# ===========================================================
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
y_pred_knn = knn.predict(X_test)
print("\n===== RESULTADOS KNN =====")
print("Acurácia:", accuracy_score(y_test, y_pred_knn))
print("\nMatriz de Confusão:")
print(confusion_matrix(y_test, y_pred_knn))
print("\nRelatório de Classificação:")
print(classification_report(y_test, y_pred_knn))
# ===========================================================
# 4. MODELO K-MEANS (Não supervisionado)
# ===========================================================
kmeans = KMeans(n_clusters=3, random_state=42)
clusters = kmeans.fit_predict(X_scaled)
# Mapeamento cluster → classe real
mapping = {}
for c in np.unique(clusters):
mapping[c] = df["EWaste_Class"][clusters == c].mode()[0]
y_pred_kmeans = [mapping[c] for c in clusters]
print("\n===== RESULTADOS K-MEANS =====")
print("Acurácia:", accuracy_score(df["EWaste_Class"], y_pred_kmeans))
print("\nMatriz de Confusão:")
print(confusion_matrix(df["EWaste_Class"], y_pred_kmeans))
print("\nRelatório de Classificação:")
print(classification_report(df["EWaste_Class"], y_pred_kmeans))
# PCA para visualização
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=pd.Series(y_pred_kmeans).astype('category').cat.codes)
plt.title("Clusters do K-Means (PCA)")
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.show()
# ===========================================================
# 5. COMPARAÇÃO ENTRE KNN E K-MEANS
# ===========================================================
print("\n==============================")
print("COMPARAÇÃO ENTRE OS ALGORITMOS")
print("==============================")
acc_knn = accuracy_score(y_test, y_pred_knn)
print("\nAcurácia KNN:", acc_knn)
acc_kmeans = accuracy_score(df["EWaste_Class"], y_pred_kmeans)
print("Acurácia K-Means:", acc_kmeans)
print("\nConclusões:")
print("""
• O KNN, por ser supervisionado, normalmente apresenta desempenho superior,
pois aprende diretamente com as classes reais.
• O K-Means é um método não supervisionado, portanto não recebe a informação
das classes durante o treinamento. Seu objetivo é apenas agrupar dados
com base em semelhança, o que geralmente resulta em acurácia menor.
• As diferenças entre as matrizes de confusão mostram o quanto o K-Means
tem dificuldade em reproduzir exatamente as classes reais.
""")
Preview da base:
| Country | Year | Smartphone Sales (Millions) | Laptop Shipments (Millions) | Gaming Console Adoption (%) | Smartwatch Penetration (%) | Average Consumer Spending on Gadgets ($) | E-Waste Generated (Metric Tons) | 5G Penetration Rate (%) | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | USA | 2015 | 111.37 | 123.63 | 12.05 | 14.49 | 311.21 | 939.89 | 54.64 |
| 1 | USA | 2016 | 224.65 | 65.27 | 12.92 | 9.88 | 250.46 | 1361.42 | 53.61 |
| 2 | USA | 2017 | 102.12 | 26.75 | 19.63 | 17.35 | 2404.22 | 872.52 | 29.94 |
| 3 | USA | 2018 | 148.10 | 129.28 | 26.44 | 12.45 | 1883.37 | 1241.41 | 75.88 |
| 4 | USA | 2019 | 83.93 | 97.81 | 20.84 | 6.18 | 777.42 | 1939.39 | 76.26 |
Informações gerais: <class 'pandas.core.frame.DataFrame'> RangeIndex: 110 entries, 0 to 109 Data columns (total 9 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Country 110 non-null object 1 Year 110 non-null int64 2 Smartphone Sales (Millions) 110 non-null float64 3 Laptop Shipments (Millions) 110 non-null float64 4 Gaming Console Adoption (%) 110 non-null float64 5 Smartwatch Penetration (%) 110 non-null float64 6 Average Consumer Spending on Gadgets ($) 110 non-null float64 7 E-Waste Generated (Metric Tons) 110 non-null float64 8 5G Penetration Rate (%) 110 non-null float64 dtypes: float64(7), int64(1), object(1) memory usage: 7.9+ KB None Resumo estatístico:
| Year | Smartphone Sales (Millions) | Laptop Shipments (Millions) | Gaming Console Adoption (%) | Smartwatch Penetration (%) | Average Consumer Spending on Gadgets ($) | E-Waste Generated (Metric Tons) | 5G Penetration Rate (%) | |
|---|---|---|---|---|---|---|---|---|
| count | 110.00000 | 110.000000 | 110.000000 | 110.000000 | 110.000000 | 110.000000 | 110.000000 | 110.000000 |
| mean | 2020.00000 | 269.095545 | 86.082000 | 21.753545 | 14.129818 | 1571.539182 | 1035.352636 | 42.816273 |
| std | 3.17675 | 128.313552 | 36.429392 | 9.748557 | 6.353190 | 816.552255 | 562.591157 | 21.888573 |
| min | 2015.00000 | 64.000000 | 20.790000 | 5.490000 | 2.040000 | 220.090000 | 111.470000 | 2.990000 |
| 25% | 2017.00000 | 156.910000 | 59.412500 | 13.737500 | 8.982500 | 856.957500 | 570.250000 | 23.952500 |
| 50% | 2020.00000 | 253.435000 | 87.450000 | 20.365000 | 14.520000 | 1592.145000 | 1023.270000 | 45.735000 |
| 75% | 2023.00000 | 376.255000 | 113.965000 | 28.460000 | 19.815000 | 2195.960000 | 1487.847500 | 58.900000 |
| max | 2025.00000 | 499.890000 | 149.210000 | 39.470000 | 24.810000 | 2989.540000 | 1962.590000 | 79.340000 |
Distribuição da classe alvo: EWaste_Class Baixo 37 Alto 37 Medio 36 Name: count, dtype: int64
===== RESULTADOS KNN =====
Acurácia: 0.24242424242424243
Matriz de Confusão:
[[4 4 3]
[4 4 3]
[6 5 0]]
Relatório de Classificação:
precision recall f1-score support
Alto 0.29 0.36 0.32 11
Baixo 0.31 0.36 0.33 11
Medio 0.00 0.00 0.00 11
accuracy 0.24 33
macro avg 0.20 0.24 0.22 33
weighted avg 0.20 0.24 0.22 33
===== RESULTADOS K-MEANS =====
Acurácia: 0.4
Matriz de Confusão:
[[26 11 0]
[19 18 0]
[20 16 0]]
Relatório de Classificação:
precision recall f1-score support
Alto 0.40 0.70 0.51 37
Baixo 0.40 0.49 0.44 37
Medio 0.00 0.00 0.00 36
accuracy 0.40 110
macro avg 0.27 0.40 0.32 110
weighted avg 0.27 0.40 0.32 110
/usr/local/lib/python3.12/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))
/usr/local/lib/python3.12/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))
/usr/local/lib/python3.12/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))
==============================
COMPARAÇÃO ENTRE OS ALGORITMOS
==============================
Acurácia KNN: 0.24242424242424243
Acurácia K-Means: 0.4
Conclusões:
• O KNN, por ser supervisionado, normalmente apresenta desempenho superior,
pois aprende diretamente com as classes reais.
• O K-Means é um método não supervisionado, portanto não recebe a informação
das classes durante o treinamento. Seu objetivo é apenas agrupar dados
com base em semelhança, o que geralmente resulta em acurácia menor.
• As diferenças entre as matrizes de confusão mostram o quanto o K-Means
tem dificuldade em reproduzir exatamente as classes reais.
===========================
DOCUMENTAÇÃO DO PROCESSO
===========================
1. Exploração dos Dados:
- Análise inicial do dataset, incluindo dimensões, tipos de dados,
estatísticas descritivas e visualização da distribuição da variável alvo.
2. Aplicação das Técnicas:
- Implementação dos algoritmos KNN (supervisionado) e K-Means (não supervisionado)
para classificação da variável categórica EWaste_Class.
3. Matrizes de Confusão:
- Geração das matrizes de confusão para ambos os modelos, permitindo avaliar
visualmente onde cada algoritmo erra e acerta.
4. Avaliação dos Modelos:
- Cálculo de acurácia, precisão, recall e F1-score para KNN.
- Comparação com a acurácia obtida pelo K-Means.
5. Comparação dos Resultados:
- Discussão sobre o desempenho dos dois algoritmos, destacando vantagens e limitações.
6. Relatório Final:
- Esta documentação apresenta de forma clara todo o processo,
incluindo código comentado, visualizações e conclusões.
Análise dos Resultados KNN e K-Means
- Desempenho do KNN
O algoritmo KNN apresentou uma acurácia de aproximadamente 0,24, indicando que apenas 24% das amostras de teste foram classificadas corretamente. A matriz de confusão mostra uma distribuição significativa de erros entre as três classes (Alto, Baixo e Médio), sem predominância clara de acertos em nenhuma delas.
As métricas de avaliação reforçam o desempenho limitado:
O precision variou entre 0,00 e 0,31.
O recall ficou entre 0,00 e 0,36.
O f1-score manteve-se baixo, entre 0,00 e 0,33.
O valor zero nas métricas da classe Médio indica que o modelo não foi capaz de reconhecer nenhum elemento dessa categoria no conjunto de teste. Isso sugere que a separação entre as classes no espaço das features não forma vizinhanças bem definidas, fragilizando o funcionamento do KNN, que depende diretamente da proximidade entre amostras.
De modo geral, o KNN não conseguiu capturar padrões suficientemente fortes para distinguir as classes de e-waste utilizando as variáveis disponíveis.
- Desempenho do K-Means
O K-Means obteve acurácia de 0,40, superior ao KNN, mas ainda modesta. Isso era esperado, uma vez que se trata de um algoritmo não supervisionado, que não recebe as classes durante o treinamento e cria agrupamentos apenas com base na similaridade entre os dados.
A matriz de confusão mostra que:
A classe Alto teve o melhor desempenho, com recall de 0,70.
A classe Baixo apresentou recall de 0,49.
A classe Médio não foi reconhecida pelo modelo (recall = 0).
Assim como no KNN, a classe Médio se mostrou a mais difícil de ser identificada. Os valores de f1-score permaneceram baixos (entre 0,00 e 0,51), o que evidencia a dificuldade de separar grupos de forma coerente com as categorias definidas artificialmente.
O gráfico de PCA confirma que os clusters não apresentam separação clara, com forte sobreposição entre os pontos. Isso indica que as variáveis utilizadas como preditoras não formam agrupamentos naturais que correspondam às classes Baixo, Médio e Alto.
- Comparação entre os dois modelos
Ao comparar os desempenhos:
O K-Means, apesar de não supervisionado, obteve acurácia maior que o KNN (0,40 contra 0,24).
O KNN encontra dificuldades porque depende de proximidade entre as amostras no espaço das variáveis, mas esse espaço não apresenta padrões fortes que diferenciem as classes.
O K-Means, embora também limitado, consegue criar agrupamentos ligeiramente mais coerentes com as classes propostas, mas ainda com desempenho insuficiente.
Ambos os modelos falham especialmente na identificação da classe Médio, o que sugere que essa categoria não possui características distintas nas features disponíveis.
No geral, os resultados indicam que as features do dataset não possuem capacidade preditiva suficiente para discriminar corretamente os níveis categorizados de e-waste, mesmo quando algoritmos supervisionados e não supervisionados são aplicados.
- Conclusão Geral
Tanto o KNN quanto o K-Means apresentaram desempenho limitado. Os resultados obtidos demonstram que:
As variáveis do dataset não fornecem separação clara entre as categorias de e-waste.
O KNN foi incapaz de modelar relações robustas entre as features e a classe alvo, resultando em baixa acurácia.
O K-Means produziu agrupamentos parcialmente consistentes, mas insuficientes para representar corretamente as classes definidas.
A classe “Médio” foi a mais difícil de identificar para ambos os modelos, evidenciando a fragilidade dos padrões que diferenciam essa categoria.
Assim, a tarefa de classificação com esses dados é naturalmente desafiadora, e os modelos utilizados exibem desempenhos que refletem essa limitação estrutural do conjunto de dados.