教師あり学習と教師なし学習

機械学習を分ける最初の基準は、正解ラベルの有無です。正解があるなら予測器を学ぶ問題になり、正解がないならデータの構造を見つける問題になります。

同じ数値データを見ていても、問う内容が違えば、使うアルゴリズムも評価指標も変わります。

問いの種類が違う

教師あり学習では、モデルは既知のラベルへ近づくように調整されます。教師なし学習では、まとまり、向き、近さのような構造そのものを探ります。

違いはアルゴリズム名にあるのではなく、何を答えとみなすかにあります。

ラベル付きデータでの分類、ラベルなしデータでのクラスタリング、PCA による次元圧縮を並べると、同じ「学習」でも読み方がかなり違うことが見えてきます。

基本語彙

どの手法でも、まず目的に合った出力の読み方を定める必要があります。

同じデータでも見る数字は変わる

分類では accuracy や混同行列が重要ですが、クラスタリングでは inertia や silhouette が手がかりになります。PCA では explained variance ratio が、圧縮後にどれくらい情報が残っているかを示します。

よくある誤解

教師なし学習は評価できないのではなく、分類と同じ基準では評価しにくいだけです。逆に、教師あり学習で accuracy だけを見ていると、どのクラスを取りこぼしているかが見えなくなります。

扱う範囲

分類、クラスタリング、PCA の入口に焦点を絞ります。クラスタ数選択の理論や次元圧縮の厳密な導出には踏み込まず、目的ごとの読み方の違いを明確にします。

ラベルがあると予測問題になる

ラベル付きデータでは、0/1 のような目標が最初から与えられています。モデルはその正解へ近づくように学習し、当たり外れを明確に数えられます。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.datasets import make_classification, make_blobs, load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, silhouette_score

sns.set_theme(style="whitegrid", context="notebook")

教師あり学習: ラベルありデータで予測する

二値分類では、各サンプルに対して 01 かの正解が付いています。モデルの役割は、そのラベルを未知データにも再現できる規則へ圧縮することです。

X, y = make_classification(
    n_samples=600,
    n_features=6,
    n_informative=4,
    n_redundant=1,
    class_sep=1.2,
    random_state=42,
)

feature_names = [f"x{i}" for i in range(X.shape[1])]
df_cls = pd.DataFrame(X, columns=feature_names)
df_cls["label"] = y

df_cls.head()

訓練用と評価用を分けるのは、未見データでも規則が保たれるかを確かめるためです。正解ラベルがあるからこそ、汎化の良し悪しをはっきり測れます。

X_train, X_test, y_train, y_test = train_test_split(
    df_cls[feature_names],
    df_cls["label"],
    test_size=0.25,
    random_state=42,
    stratify=df_cls["label"],
)

clf = Pipeline([
    ("scaler", StandardScaler()),
    ("model", LogisticRegression(max_iter=1000, random_state=42)),
])
clf.fit(X_train, y_train)

pred = clf.predict(X_test)
acc = accuracy_score(y_test, pred)
print(f"test accuracy: {acc:.3f}")

混同行列を見ると、どちらのクラスで間違いが多いかが具体的になります。正解率 1 つでは、誤り方の偏りまでは分かりません。

cm = confusion_matrix(y_test, pred)
fig, ax = plt.subplots(figsize=(4.5, 4))
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", cbar=False, ax=ax)
ax.set_title("Confusion Matrix")
ax.set_xlabel("Predicted")
ax.set_ylabel("Actual")
plt.show()

print(classification_report(y_test, pred, digits=3))

標準化の有無を比べると、前処理が分類境界の学びやすさにどう効くかが分かります。教師あり学習は、モデル単体ではなく前処理込みの系として考える必要があります。

clf_no_scale = LogisticRegression(max_iter=1000, random_state=42)
clf_no_scale.fit(X_train, y_train)
pred_no_scale = clf_no_scale.predict(X_test)

acc_no_scale = accuracy_score(y_test, pred_no_scale)
print(f"without scaling: {acc_no_scale:.3f}")
print(f"with scaling   : {acc:.3f}")

教師なし学習: ラベルなしで構造を探す

クラスタリングでは、学習時に正解ラベルを使いません。近い点どうしを同じ群へ寄せ、データの中に潜むまとまりを浮かび上がらせます。

X_blob, _ = make_blobs(
    n_samples=450,
    centers=3,
    cluster_std=1.2,
    n_features=2,
    random_state=42,
)

fig, ax = plt.subplots(figsize=(5, 4))
ax.scatter(X_blob[:, 0], X_blob[:, 1], s=18, alpha=0.8)
ax.set_title("Unlabeled Data for Clustering")
ax.set_xlabel("feature 1")
ax.set_ylabel("feature 2")
plt.show()

クラスタ数 k は外から与える必要があります。inertiasilhouette は、その選択が極端に不自然でないかを見る補助指標です。

rows = []
for k in range(2, 8):
    km = KMeans(n_clusters=k, n_init=20, random_state=42)
    labels = km.fit_predict(X_blob)
    rows.append({
        "k": k,
        "inertia": km.inertia_,
        "silhouette": silhouette_score(X_blob, labels)
    })

k_report = pd.DataFrame(rows)
k_report

k=3 の結果を可視化すると、評価は「正解と一致したか」ではなく、点群がどれだけ分かれて見えるかとして読まれることが分かります。

kmeans = KMeans(n_clusters=3, n_init=20, random_state=42)
cluster_id = kmeans.fit_predict(X_blob)
centers = kmeans.cluster_centers_

fig, ax = plt.subplots(figsize=(5.5, 4.2))
scatter = ax.scatter(X_blob[:, 0], X_blob[:, 1], c=cluster_id, cmap="tab10", s=22, alpha=0.8)
ax.scatter(centers[:, 0], centers[:, 1], c="black", marker="X", s=140, label="centers")
ax.legend(loc="best")
ax.set_title("KMeans Clustering (k=3)")
ax.set_xlabel("feature 1")
ax.set_ylabel("feature 2")
plt.show()

PCA は、多数の特徴量を少数の軸へ写し直して全体像を見やすくする方法です。主成分は元の列の混合ですが、最初の理解としては「情報をなるべく保ちながら軸を減らす」と捉えれば十分です。

iris = load_iris(as_frame=True)
X_iris = iris.data
y_iris = iris.target

X_iris_scaled = StandardScaler().fit_transform(X_iris)
pca = PCA(n_components=2, random_state=42)
X_iris_2d = pca.fit_transform(X_iris_scaled)

pca_df = pd.DataFrame(X_iris_2d, columns=["PC1", "PC2"])
pca_df["species"] = y_iris.map({0: "setosa", 1: "versicolor", 2: "virginica"})

fig, ax = plt.subplots(figsize=(6, 4.5))
sns.scatterplot(data=pca_df, x="PC1", y="PC2", hue="species", ax=ax)
ax.set_title("PCA Projection of Iris")
plt.show()

print("explained variance ratio:", pca.explained_variance_ratio_)

まとめ

教師あり学習は正解ラベルへ向かって予測器を作る学習であり、教師なし学習はラベルなしで構造を探る学習です。同じデータでも、問いが変われば評価軸も変わります。

手法名を並べる前に、何を知りたいのかを明確にすることが機械学習の出発点です。