W10
Advanced 3 sessions • 6 hours R

Week 10: Unsupervised Learning

.R
Follow along in RStudioDownload the Week 10 R script — every example ready to run with Ctrl+Enter.
Download R Script

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:

  • CLUSTERING: Group similar observations
  • K-means
  • Hierarchical clustering
  • DBSCAN
  • 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:

  • Choose k (number clusters)
  • Randomly assign points to clusters
  • Calculate center of each cluster
  • Assign points to nearest center
  • 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"
)