# ==================================================================== # Week 10: Unsupervised Learning # Kmex Consult - R Data Science Course # Open in RStudio and run each block with Ctrl+Enter (Cmd+Enter on Mac). # ==================================================================== # Finding patterns and structure in unlabeled data # ==================================================================== # WEEK 10 OVERVIEW # ==================================================================== # Unsupervised Learning = Learning WITHOUT labels # USE CASES: # - Customer Segmentation: Divide into groups # - Anomaly Detection: Find unusual records # - Data Exploration: Discover structure # - Dimension Reduction: Simplify data # - Recommendation: Find similar users # TWO MAIN APPROACHES: # 1. CLUSTERING: Group similar observations # - K-means # - Hierarchical clustering # - DBSCAN # 2. DIMENSIONALITY REDUCTION: Reduce variables # - PCA (Principal Component Analysis) # - t-SNE (visualization) # CHALLENGES: # - No "right answer" - hard to validate # - Must decide number of clusters/dimensions # - Result quality depends on preprocessing # - Can find spurious patterns # THIS WEEK YOU'LL LEARN: # ✓ K-means clustering # ✓ Hierarchical clustering and dendrograms # ✓ DBSCAN for density-based clustering # ✓ Cluster evaluation (silhouette, Davies-Bouldin) # ✓ Principal Component Analysis (PCA) # ✓ t-SNE for visualization # ✓ Choosing number of clusters # ✓ Interpreting cluster solutions # ==================================================================== # SESSION 1: K-MEANS CLUSTERING # ==================================================================== # --- Duration: 2 hours --- # --- 1.1 K-Means and Cluster Evaluation --- # K-MEANS CLUSTERING - MOST POPULAR: # Algorithm: # 1. Choose k (number clusters) # 2. Randomly assign points to clusters # 3. Calculate center of each cluster # 4. Assign points to nearest center # 5. Repeat until converged library(ggplot2) # Generate sample data set.seed(42) data <- tibble( x = c(rnorm(30, mean=2, sd=0.5), rnorm(30, mean=8, sd=0.5)), y = c(rnorm(30, mean=2, sd=0.5), rnorm(30, mean=8, sd=0.5)) ) # K-means with 2 clusters km <- kmeans(data, centers=2, nstart=25) # Add cluster assignments data$cluster <- factor(km$cluster) # Visualize ggplot(data, aes(x, y, color=cluster)) + geom_point(size=3) + geom_point(data=tibble(x=km$centers[, 1], y=km$centers[, 2]), size=5, shape=8, color="black") + labs(title="K-Means Clustering (k=2)") # CHOOSING K - THE ELBOW METHOD: # Calculate within-cluster sum of squares for k=1 to 10 wss <- vector("numeric", 10) for (k in 1:10) { km <- kmeans(data, centers=k, nstart=25) wss[k] <- km$tot.withinss } # Plot plot(1:10, wss, type="b", main="Elbow Plot", xlab="Number of Clusters", ylab="Within-cluster SS") # Look for "elbow" - point where improvement drops # Often k=2 or k=3 in this example # The "silhouette" method (more formal) library(cluster) silhouette_scores <- vector("numeric", 10) for (k in 2:10) { km <- kmeans(data, centers=k, nstart=25) sil <- silhouette(km$cluster, dist(data)) silhouette_scores[k] <- mean(sil[, 3]) } plot(2:10, silhouette_scores[2:10], type="b", main="Silhouette Scores", xlab="Number of Clusters", ylab="Average Silhouette") # Higher silhouette = better separation # EVALUATING CLUSTERS: # Silhouette coefficient: -1 to 1 # Close to 1 = well-separated # Close to 0 = overlapping # Negative = probably wrong cluster library(cluster) km <- kmeans(data, centers=2, nstart=25) sil <- silhouette(km$cluster, dist(data)) mean(sil[, 3]) # Average silhouette (higher is better) # Visualize silhouette plot(sil, main="Silhouette Plot") # Davies-Bouldin Index: Lower is better library(clusterSim) index.DB(data, km$cluster) # HIERARCHICAL CLUSTERING - DENDROGRAM: # Builds tree of clusters (easy visualization) hc <- hclust(dist(data), method="complete") # Dendrogram plot(hc, main="Hierarchical Clustering Dendrogram") # Cut dendrogram at height 2 cluster_assignment <- cutree(hc, h=2) # Or specify k cluster_assignment <- cutree(hc, k=2) # PCA - DIMENSIONALITY REDUCTION: # Compress data to main patterns # Standardize data first data_scaled <- scale(data) # PCA pca <- prcomp(data_scaled) # Variance explained summary(pca) # PC1 explains 70% of variance # PC2 explains 30% # Together = 100% # Plot in PC space plot(pca$x[, 1], pca$x[, 2], main="PCA Projection", xlab="PC1", ylab="PC2") # Biplot (shows variables) biplot(pca) # T-SNE FOR VISUALIZATION: library(tsne) # t-SNE reduces to 2D for visualization tsne_result <- tsne(data_scaled, k=2, initial_dims=ncol(data_scaled)) plot(tsne_result, main="t-SNE Visualization") # PRACTICAL WORKFLOW: # Customer segmentation example customers <- read_csv("customers.csv") # 1. Prepare data features <- customers |> select(age, income, purchases, tenure) |> scale() # 2. Find optimal k wss <- vector("numeric", 10) for (k in 1:10) { km <- kmeans(features, centers=k, nstart=25) wss[k] <- km$tot.withinss } plot(wss) # Look for elbow # 3. Fit final model with chosen k k_final <- 3 km_final <- kmeans(features, centers=k_final, nstart=25) # 4. Add to original data customers$segment <- km_final$cluster # 5. Profile segments customers |> group_by(segment) |> summarize( avg_age = mean(age), avg_income = mean(income), avg_purchases = mean(purchases), count = n() ) # 6. Name segments customers$segment_name <- case_when( customers$segment == 1 ~ "Young Budget", customers$segment == 2 ~ "Established Rich", customers$segment == 3 ~ "Mature Moderate" )