import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import joblib
import matplotlib.cm as cm
from sklearn.preprocessing import OneHotEncoder
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score, silhouette_samples
# 1. Carregar dados
url = 'https://raw.githubusercontent.com/alura-cursos/Clusterizacao-dados-sem-rotulo/main/Dados/dados_mkt.csv'
df = pd.read_csv(url)
# 2. One-Hot Encoding da coluna sexo
encoder = OneHotEncoder(categories=[['F', 'M', 'NE']], sparse_output=False)
sexo_cod = encoder.fit_transform(df[['sexo']])
sexo_df = pd.DataFrame(sexo_cod, columns=encoder.get_feature_names_out(['sexo']))
dados = pd.concat([df, sexo_df], axis=1).drop('sexo', axis=1)
# 3. Salvar encoder
joblib.dump(encoder, 'encoder.pkl')
# 4. Treinar modelo inicial
mod_kmeans = KMeans(n_clusters=2, random_state=45, n_init='auto')
mod_kmeans.fit(dados)
# 5. Métricas iniciais
print("Inércia:", mod_kmeans.inertia_)
print("Silhouette:", silhouette_score(dados, mod_kmeans.predict(dados)))
# 6. Avaliar vários k
def avaliacao(dados):
inercia, silhueta = [], []
for k in range(2, 21):
modelo = KMeans(n_clusters=k, random_state=45, n_init='auto')
pred = modelo.fit_predict(dados)
inercia.append(modelo.inertia_)
silhueta.append(silhouette_score(dados, pred))
return silhueta, inercia
silhueta, inercia = avaliacao(dados)
for k, s in enumerate(silhueta, start=2):
print(f'k={k} - silhueta={s:.4f}')
# 7. Gráfico de silhueta
def graf_silhueta(n_clusters, dados):
modelo = KMeans(n_clusters=n_clusters, random_state=45, n_init='auto')
pred = modelo.fit_predict(dados)
media = silhouette_score(dados, pred)
amostras = silhouette_samples(dados, pred)
fig, ax = plt.subplots(figsize=(9, 7))
ax.set_xlim([-0.1, 1])
ax.set_ylim([0, len(dados) + (n_clusters + 1) * 10])
y_lower = 10
for i in range(n_clusters):
vals = amostras[pred == i]
vals.sort()
tam = vals.shape[0]
y_upper = y_lower + tam
cor = cm.nipy_spectral(float(i) / n_clusters)
ax.fill_betweenx(np.arange(y_lower, y_upper), 0, vals,
facecolor=cor, edgecolor=cor, alpha=0.7)
ax.text(-0.05, y_lower + 0.5 * tam, str(i))
y_lower = y_upper + 10
ax.axvline(x=media, color='red', linestyle='--')
ax.set_title(f'Silhueta para {n_clusters} clusters')
ax.set_xlabel('Coeficiente de silhueta')
ax.set_ylabel('Cluster')
ax.set_yticks([])
plt.show()
graf_silhueta(2, dados)
# 8. Método do cotovelo
def plot_cotovelo(inercia):
plt.figure(figsize=(8, 4))
plt.plot(range(2, 21), inercia, 'bo-')
plt.xlabel('Número de clusters')
plt.ylabel('Inércia')
plt.title('Método do Cotovelo')
plt.show()
plot_cotovelo(inercia)