AI: Aprendizado Não Supervisionado
Última atualização: 2026-08-26
E se seus dados não estiverem rotulados? Quando você se depara com um grande conjunto de registros de comportamento do usuário, sequências genéticas ou dados de sensores — mas sem "respostas corretas" — o aprendizado não supervisionado é uma ferramenta poderosa para descobrir padrões ocultos. Este capítulo explora duas abordagens principais — agrupamento e redução de dimensionalidade — para ajudá-lo a entender os princípios e aplicações práticas do K-Means e do PCA.
1. O Que Você Vai Aprender
- A Diferença Fundamental Entre Aprendizado Não Supervisionado e Aprendizado Supervisionado
- Princípios e Implementação do Algoritmo de Clusterização K-Means
- O Método do Cotovelo para Selecionar o Valor Ótimo de k
- A Intuição e o Raciocínio Matemático por Trás da Redução de Dimensionalidade PCA
- Aplicações de Clusterização e Redução de Dimensionalidade em Cenários Comerciais do Mundo Real
2. História: 100K Usuários—Quem Vai Ajudar a Organizá-los em Grupos?
(1) Ponto de Dor: Com uma base de usuários tão massiva, é difícil saber por onde começar
A equipe de marketing de Charlie tinha 100 mil dados de usuários—valores gastos, frequência de compra, duração do cadastro, tempo de atividade mais recente e mais—mas ninguém sabia como segmentar os usuários. Baseando-se na experiência, o departamento de marketing dividiu os usuários em dois grupos—“novos usuários” e “usuários existentes”—e enviou cupons, mas a taxa de conversão foi de apenas 2,3%. O CEO exigiu que fosse aumentada para 5%, deixando a equipe sem saber o que fazer.
(2) A Abordagem de IA: Usando Clustering para Identificar Automaticamente Grupos de Usuários
Depois que Alice assumiu, ela usou K-Means para agrupar os usuários em quatro clusters:
| ID do Cluster | Característica | Porcentagem | Nome |
|---|---|---|---|
| Grupo 0 | Alto gasto, baixa frequência | 15% | Compradores de alto valor |
| Grupo 1 | Baixo gasto, alta frequência | 35% | Caçadores de ofertas ativos |
| Grupo 2 | Alto gasto, alta frequência | 10% | VIPs principais |
| Grupo 3 | Baixo gasto, baixa frequência | 40% | Usuários inativos |
Enviamos cupons diferentes para cada grupo: recomendando novos produtos para compradores de alto gasto, enviando cupons de desconto para caçadores de ofertas ativos, oferecendo benefícios exclusivos para VIPs principais e enviando pacotes de reativação para usuários inativos. A taxa de conversão saltou de 2,3% para 3,1%—um aumento de 35%.
(3) Benefícios: De "Adivinhação" para "Baseado em Dados"
Charlie descobriu que o poder do aprendizado não supervisionado não está na previsão, mas em descobrir o que você não sabia que existia. Mesmo sem rótulos ou conhecimento prévio, os algoritmos ainda conseguem revelar agrupamentos significativos nos dados—e esse é o valor do aprendizado não supervisionado.
3. Aprendizado Não Supervisionado vs. Aprendizado Supervisionado
(1) Principais Diferenças
| Dimensão | Aprendizado Supervisionado | Aprendizado Não Supervisionado |
|---|---|---|
| Dados de Treinamento | Rotulados (X → y) | Não rotulados (somente X) |
| Objetivo | Prever categorias/valores conhecidos | Descobrir a estrutura subjacente dos dados |
| Tarefas Típicas | Classificação, Regressão | Agrupamento, Redução de Dimensionalidade, Regras de Associação |
| Métodos de Avaliação | Acurácia, F1, RMSE, etc. | Coeficiente de contorno, inércia, visualização |
| Analogia | Um professor ensina os alunos a identificar animais | Uma criança separa os brinquedos por cor por conta própria |
| Algoritmos Representativos | Árvores de Decisão, SVM, Regressão Linear | K-Means, PCA, DBSCAN |
(2) Por Que o Aprendizado Não Supervisionado é Necessário?
- Altos custos de rotulagem: A anotação de imagens médicas requer especialistas, com custo de $50–$200 por imagem
- Rótulos Inexistentes: Segmentação de Usuários, Detecção de Anomalias—simplesmente não existe uma "resposta correta"
- Análise Exploratória: Primeiro, realiza-se o agrupamento para ver como os dados se comportam, depois decide-se o que fazer com aprendizado supervisionado
4. Agrupamento K-Means
(1) O que é Agrupamento?
Agrupamento é o processo de reunir pontos de dados semelhantes em conjunto e dissímeis em grupos separados. A questão-chave é: O que significa "semelhante"? — Isso é tipicamente medido usando uma métrica de distância, sendo a mais comum a distância euclidiana.
(2) Fluxograma do Algoritmo K-Means
O K-Means é o algoritmo de agrupamento mais clássico e prático. Sua ideia central é: dividir os dados em k clusters de modo que a soma das distâncias de cada ponto de dados ao centroide do seu cluster seja minimizada.
flowchart TD
A[Initialize k centroids randomly] --> B[Assign each point to nearest centroid]
B --> C[Recalculate centroids as mean of assigned points]
C --> D{Centroids changed?}
D -- Yes --> B
D -- No --> E[Converged! Output clusters]
style A fill:#e1f5fe
style E fill:#e8f5e9
style D fill:#fff3e0
Passos do Algoritmo:
- Inicialização: Selecionar aleatoriamente k pontos como centroides iniciais
- Atribuição: Atribuir cada ponto de dados ao cluster contendo o centro de massa mais próximo
- Atualização: Recalcular o centro de massa para cada cluster (calculando a média de todos os pontos dentro do cluster)
- Iteração: Repetir os passos 2–3 até que o centro de massa não mude mais ou o número máximo de iterações seja alcançado.
▶ Exemplo: Agrupamento K-Means de Dados de Clientes (Dificuldade: ⭐)
from sklearn.cluster import KMeans
import numpy as np
np.random.seed(42)
group_a = np.random.normal(loc=[20, 80], scale=5, size=(30, 2))
group_b = np.random.normal(loc=[80, 20], scale=5, size=(30, 2))
group_c = np.random.normal(loc=[50, 50], scale=5, size=(30, 2))
X = np.vstack([group_a, group_b, group_c])
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
kmeans.fit(X)
print(f"Cluster centers:\n{kmeans.cluster_centers_}")
print(f"Inertia (sum of squared distances): {kmeans.inertia_:.2f}")
print(f"First 10 labels: {kmeans.labels_[:10]}")
Cluster centers:
[[50.14 49.60]
[20.38 79.63]
[80.27 19.44]]
Inertia (sum of squared distances): 1310.56
First 10 labels: [1 1 1 1 1 1 1 1 1 1]
(3) Comparação de Três Algoritmos de Agrupamento
| Dimensão | K-Means | Agrupamento Hierárquico | DBSCAN |
|---|---|---|---|
| Requer especificar k | Sim | Não | Não (requer especificar eps/min_samples) |
| Formato do Cluster | Esférico | Qualquer | Qualquer |
| Tratamento de Ruído | Fraco | Razoável | Bom (marcado como pontos de ruído) |
| Complexidade temporal | O(nkt) | O(n²) ~ O(n³) | O(n log n) |
| Escalabilidade | Bom para grandes conjuntos de dados | Lento com grandes conjuntos de dados | Moderado |
| Aplicações | Segmentação de clientes, compressão de imagens | Pequenos conjuntos de dados, estruturas em árvore | Detecção de anomalias, dados espaciais |
5. Como Escolher o Valor de k
O maior problema com o K-Means: Você precisa especificar k antecipadamente. Se você escolher o k errado, os resultados do agrupamento serão sem sentido. Aqui estão dois métodos comuns para ajudá-lo a encontrar o k ótimo.
(1) O Método do Cotovelo (Elbow Method)
Trace as curvas de inércia (ou seja, a soma das distâncias quadradas dentro dos clusters) correspondentes a diferentes valores de k, selecione o valor de k no "ponto de inflexão" — semelhante ao cotovelo de um braço — após o qual o benefício de aumentar k diminui.
▶ Exemplo: Desenhando a Regra Prática — Selecionando k (Dificuldade ⭐)
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import numpy as np
np.random.seed(42)
X = np.vstack([
np.random.normal(loc=[20, 80], scale=5, size=(50, 2)),
np.random.normal(loc=[80, 20], scale=5, size=(50, 2)),
np.random.normal(loc=[50, 50], scale=5, size=(50, 2)),
np.random.normal(loc=[80, 80], scale=5, size=(50, 2)),
])
inertias = []
K_range = range(1, 11)
for k in K_range:
km = KMeans(n_clusters=k, random_state=42, n_init=10)
km.fit(X)
inertias.append(km.inertia_)
plt.figure(figsize=(8, 5))
plt.plot(K_range, inertias, 'bo-', linewidth=2, markersize=8)
plt.xlabel('Number of clusters (k)')
plt.ylabel('Inertia')
plt.title('Elbow Method for Optimal k')
plt.axvline(x=4, color='red', linestyle='--', label='Elbow at k=4')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('elbow_method.png', dpi=150)
plt.show()
Saída: (Execute o exemplo para ver a saída real, ou consulte a nota de saída esperada nos comentários do código acima.)
(2) Coeficiente de Silhueta (Silhouette Score)
O coeficiente de silhueta mede a similaridade de cada ponto em relação ao seu próprio cluster versus sua similaridade aos clusters mais próximos; seus valores variam de [-1, 1], sendo que valores mais altos são melhores.
▶ Exemplo: Selecionando k para pontuação de silhueta (Dificuldade ⭐⭐)
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
import numpy as np
np.random.seed(42)
X = np.vstack([
np.random.normal(loc=[20, 80], scale=5, size=(50, 2)),
np.random.normal(loc=[80, 20], scale=5, size=(50, 2)),
np.random.normal(loc=[50, 50], scale=5, size=(50, 2)),
np.random.normal(loc=[80, 80], scale=5, size=(50, 2)),
])
print("k | Silhouette Score")
print("--|------------------")
for k in range(2, 8):
km = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = km.fit_predict(X)
score = silhouette_score(X, labels)
print(f"{k} | {score:.4f}")
k | Silhouette Score
--|------------------
2 | 0.5812
3 | 0.6234
4 | 0.6891
5 | 0.5543
6 | 0.4672
7 | 0.3891
(3) Comparação dos Métodos de Avaliação de Agrupamento
| Método | O que mede | Faixa de Valores | Vantagens | Desvantagens |
|---|---|---|---|---|
| Inércia | Densidade intra-cluster | ≥0; quanto menor, melhor | Cálculo rápido; integrado ao K-Means | Decresce monotonicamente com o aumento de k; não pode ser usado isoladamente |
| Silhueta | Compacidade + Dispersão | [-1, 1], quanto maior, melhor | Permite comparar diferentes valores de k | Cálculo lento, O(n²) |
| Calinski-Harabasz | Razão da variância inter-cluster/intra-cluster | ≥0; quanto maior, melhor | Cálculo rápido | Prefere clusters convexos |
| Davies-Bouldin | Razão da divergência intra-cluster/distância inter-cluster | ≥0; quanto menor, melhor | Intuitivo | Prefere clusters convexos |
6. Redução de Dimensionalidade com PCA
(1) Por que a redução de dimensionalidade é necessária?
- Maldição da Dimensionalidade: Muitos atributos fazem com que as medidas de distância percam o sentido, levando a uma queda no desempenho do modelo.
- Visualização: Humanos só conseguem perceber 2D e 3D; dados de alta dimensionalidade precisam ser reduzidos a dimensões inferiores antes de poderem ser visualizados.
- Redução de Ruído: As principais informações estão concentradas nos primeiros componentes principais; os subsequentes podem ser ruído.
- Aceleração: Treinamento mais rápido e menor uso de memória após a redução de dimensionalidade.
(2) PCA: Uma Explicação Intuitiva
A ideia central do PCA (Análise de Componentes Principais) é identificar as direções com maior variância nos dados e projetar os dados nessas direções. Maior variância significa mais informação, e o objetivo é preservar o máximo possível da informação original após a projeção.
Imagine um conjunto de pontos de dados 3D dispostos em um elipsoide "achatado" - o PCA identifica o eixo mais longo (aquele com maior variância) e projeta os dados nesse eixo, transformando 3D em 1D enquanto minimiza a perda de informação.
▶ Exemplo: Reduzindo as Dimensões para 2D com PCA e Visualizando os Resultados (Dificuldade: ⭐⭐)
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import numpy as np
iris = load_iris()
X = iris.data
y = iris.target
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
print(f"Original shape: {X.shape}")
print(f"After PCA: {X_pca.shape}")
print(f"Explained variance ratio: {pca.explained_variance_ratio_}")
print(f"Total variance explained: {pca.explained_variance_ratio_.sum():.4f}")
plt.figure(figsize=(8, 6))
for target, color, label in zip([0, 1, 2], ['red', 'blue', 'green'], iris.target_names):
plt.scatter(X_pca[y == target, 0], X_pca[y == target, 1],
c=color, label=label, alpha=0.7, edgecolors='k', s=60)
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.1%} variance)')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.1%} variance)')
plt.title('PCA: Iris Dataset Reduced to 2D')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('pca_iris.png', dpi=150)
plt.show()
Original shape: (150, 4)
After PCA: (150, 2)
Explained variance ratio: [0.9246 0.0530]
Total variance explained: 0.9776
(3) Comparação de Métodos de Redução de Dimensionalidade
| Método | Tipo | Conceito Central | Preserva Estrutura Global | Preserva Estrutura Local | Interpretabilidade | Cenários de Aplicação |
|---|---|---|---|---|---|---|
| PCA | Linear | Direção de máxima variância | Boa | Ruim | Alta (pesos dos atributos são interpretáveis) | Redução de dimensionalidade rápida, redução de ruído |
| t-SNE | Não-linear | Preservação de Probabilidade de Vizinhança | Ruim | Boa | Baixa | Visualização (2D/3D) |
| UMAP | Não-linear | Preservação de estrutura topológica | Razoável | Boa | Baixa | Visualização, dados em larga escala |
| Autoencoder | Não-linear | Compressão por rede neural | Consciente da estrutura | Consciente da estrutura | Média | Redução de dimensionalidade de imagens/textos |
7. Introdução à Visualização com t-SNE
PCA é um método linear de redução de dimensionalidade que se destaca em preservar a estrutura global, mas tende a "achatar" relacionamentos não lineares. O t-SNE (t-Distributed Stochastic Neighbor Embedding) é projetado especificamente para visualização e se destaca em preservar estruturas de vizinhança local—pontos semelhantes permanecem próximos uns dos outros em 2D.
▶ Exemplo: Visualização de Dados de Alta Dimensionalidade com t-SNE (Dificuldade: ⭐⭐)
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
import numpy as np
digits = load_digits()
X = digits.data
y = digits.target
print(f"Original shape: {X.shape}") # 64-dimensional handwritten digits
tsne = TSNE(n_components=2, random_state=42, perplexity=30)
X_tsne = tsne.fit_transform(X)
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap='tab10',
alpha=0.7, edgecolors='k', s=30)
plt.colorbar(scatter, label='Digit Class')
plt.title('t-SNE: 64D Handwritten Digits → 2D')
plt.xlabel('t-SNE Dimension 1')
plt.ylabel('t-SNE Dimension 2')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('tsne_digits.png', dpi=150)
plt.show()
Saída: (Execute o exemplo para ver a saída real, ou consulte a nota de saída esperada nos comentários do código acima.)
8. Aplicações Práticas de Agrupamento e Redução de Dimensionalidade
(1) Segmentação de Clientes
As indústrias de comércio eletrônico, finanças e jogos utilizam o agrupamento para segmentar usuários em diferentes grupos e desenvolver estratégias diferenciadas:
| Indústria | Características de Agrupamento | Resultados do Agrupamento | Ações de Negócio |
|---|---|---|---|
| Comércio Eletrônico | Valor Gasto, Frequência e Preferências por Categoria | Alto Valor/Baixo Valor/Risco de Churn | Cupons Personalizados |
| Finanças | Renda, Passivos, Histórico de Crédito | Baixo Risco/Médio Risco/Alto Risco | Taxas de Juros Escalonadas |
| Jogos | Tempo de Jogo, Pagamentos, Atividade Social | Baleias/Golfinhos/Usuários Gratuitos | Operações Diferenciadas |
(2) Compressão de Imagens
O K-Means pode ser usado para a quantização de cores em imagens — agrupando milhões de cores em k categorias, reduzindo significativamente o tamanho do arquivo.
(3) Detecção de Anomalias
Pontos que não pertencem a nenhum agrupamento podem ser outliers. Pontos marcados como ruído pelo DBSCAN e pontos que estão longe dos centros dos agrupamentos merecem atenção.
(4) Engenharia de Características
Os componentes principais obtidos através do PCA podem ser usados como novas características para alimentar modelos de aprendizado supervisionado, removendo assim o ruído, reduzindo a multicolinearidade e acelerando o treinamento.
9. Comparação dos Resultados do Agrupamento com Rótulos Originais
Às vezes você tem rótulos, mas quer ver se o agrupamento não supervisionado pode "descobrir" essas categorias por conta própria—esta é uma excelente maneira de testar a qualidade do agrupamento.
▶ Exemplo: Comparação dos Resultados do Agrupamento com Rótulos Originais (Dificuldade: ⭐⭐)
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
from sklearn.metrics import confusion_matrix, accuracy_score
from scipy.stats import mode
import numpy as np
iris = load_iris()
X = iris.data
y_true = iris.target
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
y_pred = kmeans.fit_predict(X)
# Os rótulos dos clusters são arbitrários, então os alinhamos com os rótulos verdadeiros
aligned_pred = np.zeros_like(y_pred)
for i in range(3):
mask = y_pred == i
aligned_pred[mask] = mode(y_true[mask], keepdims=True).mode[0]
print("Matriz de Confusão (cluster vs rótulo verdadeiro):")
print(confusion_matrix(y_true, aligned_pred))
print(f"\nAcurácia alinhada: {accuracy_score(y_true, aligned_pred):.4f}")
Matriz de Confusão (cluster vs rótulo verdadeiro):
[[50 0 0]
[ 0 48 2]
[ 0 14 36]]
Acurácia alinhada: 0.8933
10. Limitações do Aprendizado Não Supervisionado
| Limitações | Descrição |
|---|---|
| Sem Resultados Garantidos | Sem rótulos, é impossível quantificar se algo está "certo" ou "errado"; só se pode confiar no julgamento do negócio |
| A escolha de k é subjetiva | O ponto de inflexão da "regra do cotovelo" pode não ser óbvio, e diferentes métodos podem levar a conclusões diferentes |
| Sensível à inicialização | Diferentes centros de cluster iniciais no K-Means podem produzir resultados diferentes (requer n_init > 1) |
| Só consegue detectar clusters convexos | O K-Means assume que os clusters são esféricos; dados em forma de anel ou crescente requerem DBSCAN |
| A redução de dimensionalidade resulta em perda de informação | O PCA descarta dimensões com baixa variância, o que pode resultar na perda de diferenças sutis importantes |
| Desafios na Avaliação | Não existe uma "resposta padrão"; a avaliação depende de conhecimento de domínio e visualização |
11. Exemplo Abrangente: Segmentação de Clientes Usando o Dataset "Mall Customer"
▶ Exemplo: O Processo Completo de Segmentação de Clientes Orientada por Dados (Dificuldade: ⭐⭐⭐)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
# ============================================
# Passo 1: Carregar e explorar o dataset Mall Customer
# ============================================
np.random.seed(42)
n = 200
data = {
'CustomerID': range(1, n + 1),
'Gender': np.random.choice(['Male', 'Female'], n),
'Age': np.random.randint(18, 70, n),
'Annual_Income_kUSD': np.random.randint(15, 137, n),
'Spending_Score': np.random.randint(1, 100, n),
}
df = pd.DataFrame(data)
# Inject realistic cluster structure
df.loc[:49, 'Annual_Income_kUSD'] = np.random.randint(15, 40, 50)
df.loc[:49, 'Spending_Score'] = np.random.randint(60, 100, 50)
df.loc[50:99, 'Annual_Income_kUSD'] = np.random.randint(70, 137, 50)
df.loc[50:99, 'Spending_Score'] = np.random.randint(60, 100, 50)
df.loc[100:149, 'Annual_Income_kUSD'] = np.random.randint(70, 137, 50)
df.loc[100:149, 'Spending_Score'] = np.random.randint(1, 40, 50)
df.loc[150:, 'Annual_Income_kUSD'] = np.random.randint(15, 40, 50)
df.loc[150:, 'Spending_Score'] = np.random.randint(1, 40, 50)
print("Formato do Dataset:", df.shape)
print(df.head(10))
print("\nEstatísticas descritivas:")
print(df[['Age', 'Annual_Income_kUSD', 'Spending_Score']].describe())
# ============================================
# Passo 2: Seleção de características e escalonamento
# ============================================
features = ['Age', 'Annual_Income_kUSD', 'Spending_Score']
X = df[features].values
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# ============================================
# Passo 3: Método do Cotovelo para encontrar o k ótimo
# ============================================
inertias = []
silhouette_scores = []
K_range = range(2, 11)
for k in K_range:
km = KMeans(n_clusters=k, random_state=42, n_init=10)
labels = km.fit_predict(X_scaled)
inertias.append(km.inertia_)
silhouette_scores.append(silhouette_score(X_scaled, labels))
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
axes[0].plot(K_range, inertias, 'bo-', linewidth=2)
axes[0].set_xlabel('Número de clusters (k)')
axes[0].set_ylabel('Inércia')
axes[0].set_title('Método do Cotovelo')
axes[0].axvline(x=4, color='red', linestyle='--', label='Cotovelo em k=4')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
axes[1].plot(K_range, silhouette_scores, 'go-', linewidth=2)
axes[1].set_xlabel('Número de clusters (k)')
axes[1].set_ylabel('Pontuação de Silhueta')
axes[1].set_title('Método da Silhueta')
axes[1].axvline(x=4, color='red', linestyle='--', label='Melhor em k=4')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('mall_elbow_silhouette.png', dpi=150)
plt.show()
# ============================================
# Passo 4: Clustering final com k=4
# ============================================
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
df['Cluster'] = kmeans.fit_predict(X_scaled)
# ============================================
# Passo 5: Analisar cada cluster
# ============================================
cluster_summary = df.groupby('Cluster')[features].mean()
print("\nPerfis dos clusters (valores médios):")
print(cluster_summary)
cluster_counts = df['Cluster'].value_counts().sort_index()
print("\nTamanhos dos clusters:")
print(cluster_counts)
# ============================================
# Passo 6: PCA para visualização em 2D
# ============================================
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
plt.figure(figsize=(10, 7))
colors = ['red', 'blue', 'green', 'orange']
labels_text = [
'Cluster 0: Jovens com Alto Gasto',
'Cluster 1: Ricos com Alto Gasto',
'Cluster 2: Ricos com Baixo Gasto',
'Cluster 3: Econômicos com Baixo Gasto',
]
for i in range(4):
mask = df['Cluster'] == i
plt.scatter(X_pca[mask, 0], X_pca[mask, 1],
c=colors[i], label=labels_text[i],
alpha=0.6, edgecolors='k', s=50)
centroids_pca = pca.transform(kmeans.cluster_centers_)
plt.scatter(centroids_pca[:, 0], centroids_pca[:, 1],
c='black', marker='X', s=200, label='Centróides')
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.1%})')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.1%})')
plt.title('Segmentação de Clientes do Shopping (K-Means + PCA)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('mall_clusters_pca.png', dpi=150)
plt.show()
# ============================================
# Passo 7: Recomendações de negócio
# ============================================
print("\n=== Recomendações de Negócio ===")
for i in range(4):
row = cluster_summary.loc[i]
count = cluster_counts[i]
print(f"\nCluster {i} ({count} clientes):")
print(f" Idade Média: {row['Age']:.0f}, Renda: ${row['Annual_Income_kUSD']:.0f}k, Gasto: {row['Spending_Score']:.0f}/100")
Formato do Dataset: (200, 5)
CustomerID Gender Age Annual_Income_kUSD Spending_Score
0 1 Female 56 28 86
1 2 Male 25 32 79
2 3 Female 38 22 93
3 4 Female 36 37 74
4 5 Male 47 33 68
5 6 Female 32 27 82
6 7 Female 51 18 88
7 8 Male 19 38 95
8 9 Male 23 25 71
9 10 Female 27 39 91
Estatísticas descritivas:
Age Annual_Income_kUSD Spending_Score
count 200.000000 200.000000 200.000000
mean 43.475000 60.720000 50.115000
std 15.441418 41.082376 31.494432
min 18.000000 15.000000 1.000000
max 69.000000 136.000000 99.000000
Perfis dos clusters (valores médios):
Age Annual_Income_kUSD Spending_Score
Cluster
0 41.34 26.82 80.44
1 43.88 99.24 78.32
2 44.92 101.58 19.44
3 43.36 26.24 21.12
Tamanhos dos clusters:
0 50
1 50
2 50
3 50
Name: Cluster, dtype: int64
=== Recomendações de Negócio ===
Cluster 0 (50 clientes):
Idade Média: 41, Renda: $27k, Gasto: 80/100
Cluster 1 (50 clientes):
Idade Média: 44, Renda: $99k, Gasto: 78/100
Cluster 2 (50 clientes):
Idade Média: 45, Renda: $102k, Gasto: 19/100
Cluster 3 (50 clientes):
Idade Média: 43, Renda: $26k, Gasto: 21/100
❓ Perguntas Frequentes
P: Como você avalia a qualidade dos resultados de agrupamento? R: Quando não há rótulos disponíveis, use métricas internas: o escore Silhouette ([-1,1], onde maior é melhor), o índice Calinski-Harabasz (onde maior é melhor) e o índice Davies-Bouldin (onde menor é melhor). Quando há rótulos disponíveis, compare os resultados com os rótulos reais (calcule a acurácia após alinhamento). O método mais confiável é a validação de negócios — verifique se os resultados do agrupamento estão alinhados com a intuição do negócio e são acionáveis.
P: Como você escolhe o valor de k para o K-Means? R: Primeiro, use a “regra do cotovelo” para identificar o ponto de inflexão no gráfico de inércia e, em seguida, valide os resultados usando o escore de silhueta. Se os dois métodos produzirem resultados consistentes, você pode usar esse valor com confiança; se não, priorize as necessidades do negócio — é mais fácil desenvolver estratégias diferenciadas para 4 clusters do que para 8. k não é um problema matemático; é um problema de negócios.
P: A redução de dimensionalidade via PCA resulta em perda de informação? R: Sim, mas a informação “perdida” não é necessariamente ruim. O PCA ordena as dimensões por variância, da maior para a menor; descartar dimensões com baixa variância equivale a descartar ruído. O ponto-chave é quanta variância é retida — normalmente, 85% ou mais é suficiente. Use
pca.explained_variance_ratio_para ver a contribuição de cada componente principal e, em seguida, decida quantos reter.
P: Quais são as aplicações práticas do aprendizado não supervisionado? R: Cinco cenários típicos: ① Segmentação de clientes (marketing personalizado) ② Detecção de anomalias (detecção de fraude) ③ Redução de dimensionalidade (engenharia de características) ④ Compressão de imagens (quantização de cores) ⑤ Início frio em sistemas de recomendação (agrupamento primeiro quando não há dados comportamentais disponíveis). Em essência, é “análise exploratória” — primeiro examinar como os dados se parecem e, em seguida, decidir o que fazer com eles.
P: O que é mais difícil, agrupamento ou classificação? R: O agrupamento é mais difícil porque não há uma “resposta correta”. A classificação tem rótulos, então você pode medir a acurácia para determinar o desempenho; o agrupamento não tem rótulos, então a avaliação depende de métricas internas e julgamento de negócios. Além disso, o K-Means é sensível à inicialização, a escolha de k é subjetiva e só é adequado para clusters convexos. A classificação é como uma “prova com gabarito”, enquanto o agrupamento é como uma “questão aberta sem gabarito”.
📖 Resumo
- O aprendizado não supervisionado não utiliza rótulos; seu objetivo é descobrir a estrutura intrínseca dos dados—agrupamento (clustering) para identificar grupos, e redução de dimensionalidade para identificar padrões.
- K-Means é o algoritmo de agrupamento mais prático: inicialização → atribuição → atualização → iteração—simples e eficiente.
- Selecione k usando a regra de ouro + validação cruzada com pontuação de Silhueta; a decisão final será baseada nos requisitos do negócio.
- PCA projeta os dados ao longo da direção de máxima variância, permitindo redução de dimensionalidade rápida, redução de ruído e visualização, mas descarta estruturas não lineares.
- t-SNE é adequado para visualização em 2D/3D e preserva vizinhanças locais, mas não é adequado para pré-processamento de modelos.
- Limitações do aprendizado não supervisionado: difícil de avaliar, seleção de k subjetiva, sensível à inicialização e só pode detectar clusters convexos.
📝 Exercícios
-
Problema Básico (Dificuldade ⭐): Use
sklearn.datasets.make_blobspara gerar 3 clusters de dados, realize o agrupamento K-Means e plote um gráfico de dispersão (usando cores diferentes para cada cluster e rotulando os centros dos clusters). -
Problema Avançado (Dificuldade ⭐⭐): Plote um diagrama de Regra Geral e um gráfico de Silhouette score para os dados acima, a fim de determinar o valor ótimo de k. Em seguida, intencionalmente agrupe os dados usando k=2 e k=8, respectivamente, compare os resultados e explique por que a escolha do valor errado de k leva a resultados piores.
-
Desafio (Dificuldade: ⭐⭐⭐): Carregue o conjunto de dados de dígitos manuscritos (64 dimensões) usando
sklearn.datasets.load_digits. Primeiro, use PCA para reduzi-lo para uma visualização 2D, depois use t-SNE para reduzi-lo para uma visualização 2D, e compare os resultados dos dois métodos. Escreva uma análise: Quais características estruturais o PCA e o t-SNE preservam cada um? Qual é mais adequado para visualizar este conjunto de dados?