Homework

15.4.3. Homework#

  • Use this assignment to practice the chapter’s concepts and coding skills in runnable Python code.

  • Sign in from the account menu before you start working on the assignment.

  • Write and run your code directly in the coding cells.

  • Multiple submissions are allowed. The highest score is kept.

1. Labels

Like a classifier, k-means needs training examples whose group labels are already known.

Hide code cell source

### Solution
# False
# Clustering is unsupervised: it finds groups in unlabeled data. Classification learns from labeled examples.

2. Scaling

Customers are described by annual spend (in dollars) and number of orders. Converting both features to standard units before k-means keeps spend from dominating the distances.

Hide code cell source

### Solution
# True
# Without scaling, a difference of a few dollars counts as much as a difference of a few orders, so spend decides the clusters.

3. Smallest Inertia

Inertia always decreases as k increases, so the value of k with the smallest inertia is the best choice.

Hide code cell source

### Solution
# False
# Inertia keeps falling until every point is its own cluster. Look for the elbow where the improvement levels off, or compare silhouette scores.

4. Silhouette Score

A silhouette score close to 1 means that points are much closer to their own cluster than to the nearest other cluster.

Hide code cell source

### Solution
# True
# Scores near 1 indicate tight, well-separated clusters; scores near 0 indicate overlapping clusters.

5. Cluster Numbers

In a k-means result, cluster 0 is always the most important segment, and cluster 0 in one run is the same group as cluster 0 in another run.

Hide code cell source

### Solution
# False
# Cluster numbers are arbitrary names. Describe each cluster by its profile, such as average spend and orders, not by its number.
### 6. Assigning Spend to Two Centers
# One round of the assignment step on one feature.
#   1. Assign each monthly spend value to the nearer center (0 or 1).
#   2. Print the assignments and the size of each cluster.
# Print exactly:
# Assignments: [0, 0, 1, 0, 1, 1, 1]
# Sizes: [3, 4]
import numpy as np
import pandas as pd

spend = pd.Series([15, 22, 61, 30, 75, 58, 90])
centers = [20, 70]

### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
import numpy as np
import pandas as pd

spend = pd.Series([15, 22, 61, 30, 75, 58, 90])
centers = [20, 70]

assignments = []
for value in spend:
    if abs(value - centers[0]) <= abs(value - centers[1]):
        assignments.append(0)
    else:
        assignments.append(1)

print("Assignments:", assignments)
print("Sizes:", [assignments.count(0), assignments.count(1)])
Assignments: [0, 0, 1, 0, 1, 1, 1]
Sizes: [3, 4]
### 7. Inertia by Hand
# Inertia is the sum of squared distances from each point to its own cluster's center.
#   1. Compute the center of each cluster (the mean of its points).
#   2. Compute the inertia.
# Print exactly:
# Centers: [[1.5, 1.5], [9.0, 8.0]]
# Inertia: 5.0
import numpy as np
import pandas as pd

points = pd.DataFrame({
    "x": [1, 2, 8, 10, 9],
    "y": [2, 1, 9, 7, 8],
    "cluster": [0, 0, 1, 1, 1],
})

### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
import numpy as np
import pandas as pd

points = pd.DataFrame({
    "x": [1, 2, 8, 10, 9],
    "y": [2, 1, 9, 7, 8],
    "cluster": [0, 0, 1, 1, 1],
})

centers = points.groupby('cluster')[['x', 'y']].mean()
inertia = 0
for x, y, cluster in zip(points['x'], points['y'], points['cluster']):
    inertia = inertia + (x - centers.loc[cluster, 'x']) ** 2 + (y - centers.loc[cluster, 'y']) ** 2

print("Centers:", centers.values.tolist())
print("Inertia:", inertia)
Centers: [[1.5, 1.5], [9.0, 8.0]]
Inertia: 5.0
### 8. Clustering Stores
# Twelve stores are described by foot traffic and basket size, in standard units.
#   1. Fit KMeans(n_clusters=3, n_init=10, random_state=0).
#   2. Print the cluster sizes, sorted from smallest to largest.
# Print exactly:
# Cluster sizes: [4, 4, 4]
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans

stores = pd.DataFrame({
    "traffic_su": [-1.2, -1.0, -1.3, -0.9, 0.1, 0.3, 0.0, 0.2, 1.3, 1.1, 1.4, 1.2],
    "basket_su": [1.1, 0.9, 1.2, 1.0, -1.0, -1.2, -0.9, -1.1, 0.2, 0.0, 0.3, 0.1],
})

### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans

stores = pd.DataFrame({
    "traffic_su": [-1.2, -1.0, -1.3, -0.9, 0.1, 0.3, 0.0, 0.2, 1.3, 1.1, 1.4, 1.2],
    "basket_su": [1.1, 0.9, 1.2, 1.0, -1.0, -1.2, -0.9, -1.1, 0.2, 0.0, 0.3, 0.1],
})

labels = KMeans(n_clusters=3, n_init=10, random_state=0).fit_predict(stores)
print("Cluster sizes:", sorted(pd.Series(labels).value_counts().tolist()))
Cluster sizes: [4, 4, 4]
### 9. How Many Store Groups?
#   1. For k = 2, 3, and 4, fit KMeans(n_clusters=k, n_init=10, random_state=0) to
#      stores and compute the silhouette score, rounded to 3 decimals.
#   2. Print each score, then the k with the highest score.
# Print exactly:
# k=2: 0.682
# k=3: 0.864
# k=4: 0.773
# Best k: 3
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

stores = pd.DataFrame({
    "traffic_su": [-1.2, -1.0, -1.3, -0.9, 0.1, 0.3, 0.0, 0.2, 1.3, 1.1, 1.4, 1.2],
    "basket_su": [1.1, 0.9, 1.2, 1.0, -1.0, -1.2, -0.9, -1.1, 0.2, 0.0, 0.3, 0.1],
})

### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

stores = pd.DataFrame({
    "traffic_su": [-1.2, -1.0, -1.3, -0.9, 0.1, 0.3, 0.0, 0.2, 1.3, 1.1, 1.4, 1.2],
    "basket_su": [1.1, 0.9, 1.2, 1.0, -1.0, -1.2, -0.9, -1.1, 0.2, 0.0, 0.3, 0.1],
})

scores = {}
for k in [2, 3, 4]:
    labels = KMeans(n_clusters=k, n_init=10, random_state=0).fit_predict(stores)
    scores[k] = round(silhouette_score(stores, labels), 3)
    print("k=" + str(k) + ":", scores[k])
print("Best k:", max(scores, key=scores.get))
k=2: 0.682
k=3: 0.864
k=4: 0.773
Best k: 3
### 10. Profiling Segments
# K-means has assigned nine customers to clusters.
#   1. Use groupby to compute each cluster's mean visits and mean spend.
#   2. Find the cluster with the highest mean visits and print its mean spend
#      and its number of customers.
# Print exactly:
# Most frequent visitors: cluster 1
# Their mean spend: 45.0
# Customers: 3
import numpy as np
import pandas as pd

segments = pd.DataFrame({
    "visits": [2, 3, 12, 14, 1, 13, 6, 5, 7],
    "spend": [120, 140, 40, 50, 100, 45, 80, 70, 90],
    "cluster": [0, 0, 1, 1, 0, 1, 2, 2, 2],
})

### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
import numpy as np
import pandas as pd

segments = pd.DataFrame({
    "visits": [2, 3, 12, 14, 1, 13, 6, 5, 7],
    "spend": [120, 140, 40, 50, 100, 45, 80, 70, 90],
    "cluster": [0, 0, 1, 1, 0, 1, 2, 2, 2],
})

profile = segments.groupby('cluster')[['visits', 'spend']].mean()
top = profile['visits'].idxmax()

print("Most frequent visitors: cluster", top)
print("Their mean spend:", profile.loc[top, 'spend'])
print("Customers:", (segments['cluster'] == top).sum())
# Frequent visitors spend the least per month: possibly a segment to target with
# bundles or add-ons.
Most frequent visitors: cluster 1
Their mean spend: 45.0
Customers: 3