Menu
CoddyTech

64次元を見てみる

CoddyのMachine Learningジャーニー「教師なし学習」セクションの一部。レッスン 29/51。

この章では、手書き数字を使ってPCAを実際に試します。章の終わりまでに、スキャン画像を少数の数値に圧縮し、そこから再構成します。

手書きの9を5回再構成:2個の数値からはぼやけたグレーの画像、5個と10個からは粗い9、20個からは鮮明な9、最後に実際の64ピクセルのスキャン画像

まず、見てみましょう。1つのスキャンは64ピクセルですが、64個の軸を持つグラフはないため、PCAはそれらを2つに圧縮します。

digits = load_digits()
X = digits.data
y = digits.target
points = PCA(n_components=2).fit_transform(X)
for d in range(10):
    ax.scatter(points[y == d, 0], points[y == d, 1], label=str(d))

ここではスケーラーを使いません。すべてのピクセルで単位は共通で、インクの値は0から16です。

2つの成分上に点として表示された数字のスキャン画像。各数字は中心にラベル表示されている。0は下部、4は右端、3は左端にあり、その他の数字はその間の領域に分布し、一部は重なっている

PCAはyを一度も見ていません。点に色を付けているだけです。それでも各数字はそれぞれの領域に集まっています。その構造はピクセルの中にありました。

challenge icon

チャレンジ

中級

子ども向けの手書きアプリは、子どもたちがどの数字を見間違える可能性があるかを知りたいと考えています。プログラムは、358のように続けて入力された数字をchosenに読み込みます。

  1. PCAを使って、1,797個すべてのスキャンをそれぞれ2つの数値に圧縮し、pointsに格納します。
  2. 選択した各数字のスキャンを、数字のラベルを付けて散布図にします。凡例を追加して表示します。
  3. report_closest(points, y, chosen)を呼び出します。

046の場合、次のように表示されます。

Closest on the map: 4 and 6 (13.6 apart)

そして、次の図を描画します。その後、Coddyがグラフを説明します。

「似ている数字」というタイトルの散布図。凡例があり、0は左下、6は中央下、4は右上にあり、6が4に接している

自分で試してみよう

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA


# 類似度の測定より:選択された数字のうち、マップ上で中心が最も近い2つを表示する
def report_closest(points, y, chosen):
    best = -1
    for i in range(len(chosen)):
        for j in range(i + 1, len(chosen)):
            a = points[y == chosen[i]].mean(axis=0)
            b = points[y == chosen[j]].mean(axis=0)
            dist = np.sqrt(((a - b) ** 2).sum())
            if best == -1 or dist < best:
                best = dist
                pair = (chosen[i], chosen[j])
    print(f"Closest on the map: {pair[0]} and {pair[1]} ({best:.1f} apart)")


# 1,797個のスキャンデータ:各データの64ピクセルはXに、描かれた数字はyに格納される
digits = load_digits()
X = digits.data
y = digits.target

# 比較する数字を358のように続けて入力する
chosen = []
for ch in input():
    chosen.append(int(ch))

# 以下の行は変更しないでください
fig, ax = plt.subplots()
ax.set_title("Digits that look alike")
ax.set_xlabel("Component 1")
ax.set_ylabel("Component 2")

# 以下にコードを書いてください
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

教師なし学習のすべてのレッスン

自分で練習してみよう: Pythonオンラインコンパイラ