Hands-on clustering projects: customer segmentation (RFM analysis), document clustering, anomaly detection, social network analysis with complete implementation.
Project 1: Customer Segmentation (E-Commerce RFM Analysis)
Business Problem
- Segment customers for targeted marketing
- Identify VIP customers, at-risk customers, hibernating
- Optimize marketing spend per segment
Data Requirements
Customer ID, Purchase Date, Purchase Amount, Product Category
At least 6-12 months transaction history
Minimum 100-1000 customers
RFM Metrics
| Recency (R) | Days since last purchase |
| - Scale | 0-100 (100 = most recent) |
| Frequency (F) | Number of purchases in period |
| - Scale | 0-100 (100 = most frequent) |
| Monetary (M) | Total spent in period |
| - Scale | 0-100 (100 = highest spender) |
Implementation
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import numpy as np
# Calculate RFM
reference_date = df['purchase_date'].max()
rfm = df.groupby('customer_id').agg({
'purchase_date': lambda x: (reference_date - x.max()).days, # Recency
'order_id': 'count', # Frequency
'amount': 'sum' # Monetary
}).rename(columns={
'purchase_date': 'R',
'order_id': 'F',
'amount': 'M'
})
# Normalize to 0-100 scale
rfm['R_score'] = 100 - rfm['R'].rank(pct=True) * 100
rfm['F_score'] = rfm['F'].rank(pct=True) * 100
rfm['M_score'] = rfm['M'].rank(pct=True) * 100
# Cluster
scaler = StandardScaler()
rfm_scaled = scaler.fit_transform(rfm[['R_score', 'F_score', 'M_score']])
kmeans = KMeans(n_clusters=4, random_state=42)
rfm['cluster'] = kmeans.fit_predict(rfm_scaled)
# Interpret
for cluster_id in range(4):
cluster_data = rfm[rfm['cluster'] == cluster_id]
print(f"\nCluster {cluster_id}:")
print(f" Size: {len(cluster_data)}")
print(f" Avg Recency: {cluster_data['R'].mean():.0f} days")
print(f" Avg Frequency: {cluster_data['F'].mean():.1f} purchases")
print(f" Avg Monetary: ${cluster_data['M'].mean():.2f}")
Segment Interpretation
| High R, High F, High M | VIP (Champions) |
| Action | Reward, exclusive offers, early access |
| High R, High F, Low M | Loyal Low-Spenders |
| Action | Upsell strategies, product recommendations |
| Low R, High F, High M | At-Risk (Churn Risk) |
| Action | Win-back campaigns, loyalty programs |
| Low R, Low F, Low M | Hibernating |
| Action | Re-engagement, special promotions |
Project 2: Document Clustering (News Classification)
Business Problem
- Automatically organize news articles by topic
- Recommend similar articles
- Content moderation at scale
Implementation
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
import pandas as pd
# Load documents
documents = pd.read_csv('news_articles.csv')
# Extract features (TF-IDF)
vectorizer = TfidfVectorizer(max_features=1000, stop_words='english')
tfidf_matrix = vectorizer.fit_transform(documents['text'])
# Find optimal clusters
inertias = []
silhouette_scores = []
for k in range(2, 11):
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(tfidf_matrix)
inertias.append(kmeans.inertia_)
silhouette_scores.append(silhouette_score(tfidf_matrix, kmeans.labels_))
optimal_k = np.argmax(silhouette_scores) + 2
# Final clustering
kmeans = KMeans(n_clusters=optimal_k, random_state=42, n_init=20)
documents['cluster'] = kmeans.fit_predict(tfidf_matrix)
# Interpret (top terms per cluster)
feature_names = vectorizer.get_feature_names_out()
for cluster_id in range(optimal_k):
center = kmeans.cluster_centers_[cluster_id]
top_indices = center.argsort()[-10:][::-1]
top_terms = [feature_names[i] for i in top_indices]
print(f"Cluster {cluster_id}: {', '.join(top_terms)}")
Project 3: Anomaly Detection
Business Problem
- Detect fraudulent transactions
- Identify network intrusions
- Detect sensor anomalies
Implementation
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
# Load data
data = load_transaction_data()
# Preprocess
scaler = StandardScaler()
X_scaled = scaler.fit_transform(data)
# DBSCAN (density-based anomaly detection)
dbscan = DBSCAN(eps=0.5, min_samples=5)
labels = dbscan.fit_predict(X_scaled)
# Anomalies = -1
anomalies = data[labels == -1]
normal = data[labels != -1]
print(f"Total samples: {len(data)}")
print(f"Normal: {len(normal)}")
print(f"Anomalies: {len(anomalies)}")
print(f"Anomaly rate: {len(anomalies) / len(data) * 100:.2f}%")
# Alternative: Isolation Forest (faster)
from sklearn.ensemble import IsolationForest
iso_forest = IsolationForest(contamination=0.1, random_state=42)
labels = iso_forest.fit_predict(X_scaled)
anomalies = data[labels == -1]
Best Practices
- Feature Engineering: Select informative features (RFM, TF-IDF)
- Preprocessing: Normalize, handle missing values
- K Selection: Elbow, Silhouette, domain knowledge
- Validation: Domain expert review, business metrics
- Iteration: Refine features, parameters based on feedback
- Monitoring: Track cluster quality over time
Quick Revision Notes
- RFM powerful for customer segmentation
- Feature Engineering critical for clustering quality
- Validate with domain experts, not just metrics
- Iterate improve features, parameters
- Monitor cluster stability over time
- Interpretability understand why clusters formed
Interview Q&A
Q1: How do you validate customer segments?
A: Business metrics (marketing ROI, retention, LTV per segment), domain expert review, stability (same results in cross-validation), profile analysis (coherent characteristics per segment).
Q2: Anomaly detection: why use DBSCAN vs Isolation Forest?
A: DBSCAN detects density-based anomalies, requires eps tuning. Isolation Forest random forest approach, faster, no density assumptions. Isolation Forest often preferred for scalability.
Q3: How to handle categorical features in clustering?
A: One-hot encode, use Gower distance, or encode numerically if ordinal. Normalize mixed features. K-modes for categorical-only data.