Menu
CoddyTech

Find the Odd Ones

Part of the Unsupervised Learning section of Coddy's Machine Learning journey. Lesson 47 of 51.

One last question: which scans are the odd ones? An isolation forest scores every scan, and the lower the score, the stranger. First, the highest scores, the most ordinary:

Ten tidy handwritten scans in two rows, the most ordinary in the set: five round 0s, three 9s, an 8 and a 2

iso = IsolationForest(contamination=0.02, random_state=0)
flags = iso.fit_predict(X_small)
scores = iso.score_samples(X_small)
typical = np.argsort(scores)[::-1][:10]

np.argsort lists the row numbers from the lowest score up, so reversed, the most ordinary come first. Show them from X: all 64 pixels.

challenge icon

Challenge

Medium

The finale. The starter carries all so far, and guess, each scan's cluster name.

  1. Fit an isolation forest on X_small (contamination=0.02, random_state=0). Print how many it flags, the digit flagged most often, and how many of those their cluster names right.
  2. Draw the 10 strangest scans, strangest first: a 2 by 5 gallery in gray_r, titled with their digits.

With contamination=0.01:

Flagged as odd: 18 of 1797 scans
Most often odd: 7 (10 scans)
Named right by their cluster: 11 of 18 odd scans

A gallery of the most ordinary 7s looks like this:

Ten handwritten 7s in a 2 by 5 gallery, each titled 7, all alike: a top bar, a short crossbar and a stroke down

Yours shows the strangest. Clusters name 79.2% of all scans right: how do the odd ones compare? You explored 1,797 scans and never trained on a label.

Try it yourself

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from sklearn.ensemble import IsolationForest

# From Look at the Digits: 1,797 scans of 64 pixels, ink from 0 to 16
digits = load_digits()
X = digits.data
y = digits.target

# From Shrink with PCA: 80% of the variance in 13 numbers per scan
pca = PCA(n_components=0.8)
X_small = pca.fit_transform(X)

# From Cluster the Digits: 10 clusters, found without a label
km = KMeans(n_clusters=10, n_init=10, random_state=0).fit(X_small)

# From Name the Clusters: the digit each scan's cluster is named after (79.2% match y)
names = pd.crosstab(km.labels_, y).idxmax(axis=1)
guess = names.to_numpy()[km.labels_]

# Write your code below
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Unsupervised Learning

Practice on your own: Online Python compiler