論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
分類モデルの基礎(ロジスティック・k-NN・SVM・NB・LDA)
Classification Models (Basics)
古典的分類モデル5種を体系的に学ぶ。 NN/RF が登場する前の基本だが、 解釈性とベースライン性能で今も現役。
機械学習分類classification

🔖 キーワード索引(拡張)

🔖 キーワード索引(拡張)

論文・教科書でよく登場する関連語句のサブインデックス。

シグモイド関数 対数尤度 オッズ比 ミンコフスキー距離 KD木 / Ball木 マージン最大化 RBFカーネル ヒンジ損失 条件付き独立 Laplaceスムージング 共通共分散行列 マハラノビス距離 クラス不均衡 情報リーク 確率の校正 sklearn Pipeline CalibratedClassifierCV SSDSE-B 実値計算

💡 30秒で分かる結論

🍰 まずはやさしく

データを分けるための道具です。

正解のグループを当てるために使います。

テストの結果で合格か不合格かを分けます。

5つの基本的な分類方法について読みます。

🗂️ 章俯瞰 — 古典的分類モデル 5 種

NN/RF が登場する前の古典的分類モデル群。 シンプルで解釈しやすく、 ベースラインや小規模データで未だ強い。

手法 判定の根拠 解釈性 スケール 確率出力
ロジスティック回帰線形境界+シグモイド高(係数で)大規模可自然
k-NN近傍 k 個の多数決推論遅い頻度比
SVMマージン最大の超平面低(カーネル時)中規模Platt校正
ナイーブベイズ条件付き独立仮定 + ベイズ非常に高速自然
LDA / QDA各クラスのガウス分布中規模自然

📈 ロジスティック回帰(Logistic Regression)

線形結合をシグモイド関数で 0〜1 に押し込み、 確率として解釈:

$$ p(y=1 \mid \boldsymbol{x}) = \sigma(\boldsymbol{w}^\top \boldsymbol{x} + b) = \frac{1}{1 + e^{-(\boldsymbol{w}^\top \boldsymbol{x} + b)}} $$

損失はクロスエントロピー(Log Loss)。 解は最尤推定で求める。 名前は「回帰」だが分類モデル

強み

弱み

🎯 このコードでやること: 分類器を学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# ── この抜粋だけで動くように、学習用と検証用のデータを作る ──
# 「総人口が中央値より多い県か」を当てる 2 クラス分類にする
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
_d = _d[_d['SSDSE-B-2026'] == 2023]                    # 最新年度の 47 行
_X = StandardScaler().fit_transform(
    _d[['A4101', 'A1303', 'L3221']].astype(float))     # 出生数・65歳以上人口・消費支出
_y = (_d['A1101'] > _d['A1101'].median()).astype(int).values
X_train, X_test, y_train, y_test = train_test_split(
    _X, _y, test_size=0.3, random_state=0, stratify=_y)

model = LogisticRegression(C=1.0, penalty='l2', max_iter=1000)
model.fit(X_train, y_train)
print(model.coef_)          # 係数
print(model.predict_proba(X_test)[:, 1])  # 陽性確率
📤 実行例(実測) [[1.13477354 1.60268686 1.05607332]] [0.20664194 0.0935721 0.99935879 0.85053849 0.99999763 0.17137733 0.76622227 0.16096287 0.50646109 0.08363271 0.76931667 0.30712175 0.06112306 0.51870944 0.48363063]

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

詳細:ロジスティック回帰

👥 k-NN(k-Nearest Neighbors)

「新しい点の近くの $k$ 個の多数決」で分類。 学習フェーズなし(lazy learner)。

$$ \hat{y} = \arg\max_c \sum_{i \in N_k(\boldsymbol{x})} \mathbb{1}\{y_i = c\} $$

$N_k(\boldsymbol{x})$ は $\boldsymbol{x}$ に最近接の $k$ 点。 距離はユークリッド・マンハッタン・コサインなど。

長所

短所

詳細:k近傍法

🎯 SVM(Support Vector Machine)

2クラス間のマージン(境界からのギャップ)を最大化する超平面を学ぶ。

$$ \min_{\boldsymbol{w}, b} \frac{1}{2}\|\boldsymbol{w}\|^2 + C \sum_i \max(0, 1 - y_i(\boldsymbol{w}^\top \boldsymbol{x}_i + b)) $$

$C$ は正則化(小 → マージン重視、 大 → 誤分類重視)。

カーネル法

非線形分類はカーネルトリックで:明示的に高次元に変換せず、 内積をカーネル関数 $K(\boldsymbol{x}_i, \boldsymbol{x}_j)$ で置き換える。 RBF、 多項式、 シグモイドなど。

強み・弱み

詳細:SVM

🎲 ナイーブベイズ(Naive Bayes)

ベイズの定理に基づき、 「特徴量が条件付き独立」と仮定して分類:

$$ p(y \mid \boldsymbol{x}) \propto p(y) \prod_j p(x_j \mid y) $$

独立性仮定は非現実的("naive")だが、 実用的にしばしば良い性能。 とくにテキスト分類(スパム判定、 ニュース分類)で標準。

バリエーション

🎯 このコードでやること: モデルを学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd
import numpy as np
from sklearn.naive_bayes import GaussianNB, MultinomialNB

# GaussianNB は連続値、MultinomialNB は「回数」の特徴量に使う。
# ここでは MultinomialNB 用に、非負の整数(件数)の表を作る
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
_d = _d[_d['SSDSE-B-2026'] == 2023]
X_word_counts = _d[['A4101', 'A4200', 'A9101']].astype(int).values  # 出生数・死亡数・婚姻件数
y = (_d['A1101'] > _d['A1101'].median()).astype(int).values

gnb = GaussianNB().fit(X_train, y_train)
mnb = MultinomialNB().fit(X_word_counts, y)
print('GaussianNB 学習データ正解率   :', round(gnb.score(X_train, y_train), 3))
print('MultinomialNB 学習データ正解率:', round(mnb.score(X_word_counts, y), 3))
📤 実行例(実測) GaussianNB 学習データ正解率 : 1.0 MultinomialNB 学習データ正解率: 0.723

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

📍 あなたが今見ているもの

🍰 まずはやさしく

昔から使われている定番のやり方です。

分析の基準を作るために使います。

スマホのデータなど表形式のデータに便利です。

定義から実装までの6つの視点で読みます。

論文・記事に 「ロジスティック回帰」「k-NN」「SVM」「ナイーブベイズ」「判別分析(LDA/QDA)」「One-vs-Rest」 として登場する古典的分類モデル群。 解釈性が高くベースラインとして必須。 テーブルデータでは現代でも常用されます。

本ページでは「classification basic」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の実データを使った再現可能な学習を目指す。

「classification basic」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。

🎨 直感で掴む — 分類は「境界線を引く」こと

🍰 まずはやさしく

グループの間に線を引くイメージです。

どこで分けるかを決めるために使います。

郵便物を住所で仕分けるときのようなものです。

境界線の形による結果の違いについて読みます。

分類器とは 特徴量空間の中に境界線(決定境界)を引く道具 です。 線形分類器は直線、 木モデルは軸に平行な階段、 ニューラルネットは曲がりくねった曲線を引きます。 同じデータでも、 引く境界の形が違えば 異なる分類結果 になるのが直感の核心です。

もう一つの比喩は 「郵便配達員の仕分け」。 ハガキを郵便番号で仕分けるのは 明確な決定境界。 手書き住所の判読は 確率的な分類。 ぼやけた住所は「東京 80%、 京都 20%」と確率で持つほうが、 後段の人手チェックで効率が上がります。 これが 確率予測硬い分類 の使い分けです。

🌐 関連手法・派生 — 分類の階層と発展

階層手法特徴
基礎ロジスティック回帰線形 + 確率出力
基礎ナイーブベイズ確率モデル、 高速
中級決定木解釈性 + 階段境界
中級ランダムフォレストアンサンブル、 安定
上級SVMマージン最大化、 カーネル
上級ニューラルネット非線形、 大規模データ
発展勾配ブースティングXGBoost/LightGBM

💬 同じ分類問題でも、 データ量・解釈性要求・計算資源で 選ぶべきモデルは変わる。 まずロジスティック回帰でベースラインを作り、 必要に応じて木モデルやアンサンブルに進むのが定石です。

🏙️ 二値分類: SSDSE-B-2026 で「都市 vs 地方」を識別する

最も基本的な分類タスクは 二値分類 (binary classification) です。 ここでは SSDSE-B-2026 の 47 都道府県を、 総人口を閾値に「都市県」(1) と「地方県」(0) に分け、 経済・教育・消費の指標から都市性を予測するモデルを作ります。

📐 二値分類の数式

特徴ベクトル $x \in \mathbb{R}^p$ に対し、 ロジスティック回帰は条件付き確率を次式で予測します。

$$P(y=1 \mid x) = \sigma(w^\top x + b) = \frac{1}{1 + \exp(-(w^\top x + b))}$$

$$\hat y = \mathbb{1}[P(y=1 \mid x) \geq 0.5]$$

🔬 数式を言葉で読み解く — シグモイドが「確率」を作る仕組み

$w^\top x + b$ は実数($-\infty$〜$\infty$)です。 これを シグモイド関数 $\sigma$ に通すと、 0〜1 の値に押し込められ 確率として解釈できる ようになります。 大きな正の値 → 1 に近づき「クラス 1 と予測」、 大きな負の値 → 0 に近づき「クラス 0 と予測」。 閾値 0.5 は convention であり、 用途によって 0.3 や 0.7 に変えるべきです(例: 病気検出は見逃したくないので閾値を下げる)。

🐍 都市/地方の二値分類を実装

このコードでやること: SSDSE-B-2026 の都道府県を「人口 500 万以上」で都市/地方に二値ラベル化し、 商業地地価(C5403)・大学学生数(E6302)・消費支出(L3221)を特徴量にロジスティック回帰で分類。 精度・適合率・再現率・F1 を測る。

📥 入力データ:

SSDSE-B-2026: 都道府県 47 行 特徴量: C5403 (商業地地価), E6302 (大学学生数), L3221 (消費支出) ラベル: y = 1 if A1101 (総人口) >= 5,000,000 else 0 → 都市 9 / 地方 38 (2023年度)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.metrics import classification_report, confusion_matrix

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]  # 縦持ち(2012-2023年)なので必ず年度でフィルタ
y = (df['A1101'] >= 5_000_000).astype(int)
X = df[['C5403', 'E6302', 'L3221']].copy()
X = StandardScaler().fit_transform(X)

model = LogisticRegression(max_iter=1000, class_weight='balanced')
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
y_pred = cross_val_predict(model, X, y, cv=cv)

print("Confusion Matrix:")
print(confusion_matrix(y, y_pred))
print(classification_report(y, y_pred, target_names=['地方', '都市']))

📤 実行例:

Confusion Matrix: [[37 1] [ 1 8]] precision recall f1-score support 地方 0.97 0.97 0.97 38 都市 0.89 0.89 0.89 9 accuracy 0.96 47 macro avg 0.93 0.93 0.93 47 weighted avg 0.96 0.96 0.96 47

💬 全体精度は 96% で、 都市クラスも precision / recall とも 0.89(誤警報 FP 1 件・見逃し FN 1 件)。 ただし少数クラスはわずか 9 件しかないため、 1 件の誤分類で precision / recall が約 11 ポイントも動く。 不均衡データ (9 vs 38) では「全体精度が高い」だけで判断せず、 少数クラスの recall / precision / F1 を必ず確認する必要があります。

🗾 多クラス分類: 4 地方ブロックを識別する

クラスが 3 つ以上の問題が 多クラス分類 (multiclass classification)。 SSDSE-B-2026 の 47 都道府県を、 北日本 (北海道 + 東北)、 東日本 (関東 + 中部)、 西日本 (近畿 + 中国 + 四国)、 九州・沖縄 の 4 地方ブロックに分類する問題を考えます。

📐 ソフトマックス回帰

クラス数 $K$ の問題では、 各クラスのスコア $z_k = w_k^\top x + b_k$ をソフトマックスで確率化します。

$$P(y = k \mid x) = \frac{\exp(z_k)}{\sum_{j=1}^K \exp(z_j)}$$

$$\hat y = \arg\max_{k \in \{1,...,K\}} P(y = k \mid x)$$

🔬 数式を言葉で読み解く — ソフトマックスの「指数化 → 正規化」

スコア $z_k$ をそのまま使うと負の値もあり「確率」になりません。 そこで $\exp(z_k)$ で 正値化(指数化)し、 さらに分母で全クラスの和に 正規化 することで、 「各クラスへの所属確率」が得られます。 $\arg\max$ は「最も確率が高いクラスを選ぶ」という意味で、 最終予測ラベルになります。 また、 大きなスコア差は指数で 増幅 されるため、 ソフトマックスは「断定的になりやすい」特徴があります。

🐍 4 地方ブロックの多クラス分類

このコードでやること: SSDSE-B-2026 の都道府県コードから 4 地方ブロックを作り、 人口・経済・教育・消費の特徴量からブロックを多クラス分類。 RandomForest と LogisticRegression を比較する。

📥 入力データ:

SSDSE-B-2026: 47 行 × 7 特徴量 ブロック分け: 北 (北海道 + 東北 6): n=7 東 (関東 7 + 中部 9): n=16 西 (近畿 7 + 中国 5 + 四国 4): n=16 南 (九州 7 + 沖縄): n=8
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import StratifiedKFold, cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]  # 縦持ち(2012-2023年)なので必ず年度でフィルタ
df['no'] = df['Code'].str.extract(r'R(\d{2})').astype(int)  # 都道府県コード(01-47)
def block(n):
    if n <= 7:  return '北'
    if n <= 23: return '東'
    if n <= 39: return '西'
    return '南'
y = df['no'].apply(block)
X = df[['A1101', 'C5403', 'E6302', 'L3221']]
Xs = StandardScaler().fit_transform(X)

cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for name, model in [
    ('LR', LogisticRegression(max_iter=1000)),
    ('RF', RandomForestClassifier(n_estimators=200, random_state=42))]:
    score = cross_val_score(model, Xs, y, cv=cv, scoring='f1_macro')
    print(f"{name}: F1-macro = {score.mean():.3f} ± {score.std():.3f}")

📤 実行例:

LR: F1-macro = 0.321 ± 0.114 RF: F1-macro = 0.279 ± 0.075

💬 F1-macro は 0.32 (LR) / 0.28 (RF) と 低い値(4 クラスをランダムに当てても 0.25 程度なので、 ほとんど識別できていない)。 人口・経済・消費の連続変数では 地方ブロック をうまく分けられない(=北と南は経済規模が似ている)。 これは特徴量の選択が問題に合っていない典型例。 地理座標(緯度・経度)を入れれば精度は劇的に上がります。 「分類できなかった」も重要な情報 — 「経済規模では地方ブロックを識別できない」と結論できます。

📈 評価指標の選び方: Accuracy / Precision / Recall / F1 / ROC-AUC / PR-AUC

📐 主要指標の定義

$$\text{Precision} = \frac{TP}{TP + FP}, \quad \text{Recall} = \frac{TP}{TP + FN}$$

$$F_1 = \frac{2 \cdot \text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}$$

$$F_\beta = \frac{(1+\beta^2) \cdot \text{Precision} \cdot \text{Recall}}{\beta^2 \cdot \text{Precision} + \text{Recall}}$$

🔬 数式を言葉で読み解く — Precision と Recall の非対称性

Precision (適合率): 「陽性と予測したもののうち、 本当に陽性は何%か」。 誤検出を減らしたい場面(迷惑メール、 偽陽性が深刻な医療診断)で重要。
Recall (再現率): 「本当に陽性のうち、 何%を見つけられたか」。 見逃しを減らしたい場面(がん検診、 不正検出)で重要。
$F_1$ は両者の調和平均で、 バランス指標。 $F_\beta$ の $\beta$ を 2 にすれば Recall 重視、 0.5 にすれば Precision 重視に調整できます。

🐍 ROC 曲線と Precision-Recall 曲線を描く

このコードでやること: 都市/地方の二値分類で、 閾値を変えながら ROC 曲線と PR 曲線を描き、 AUC を比較する。

📥 入力データ: 上の二値分類と同じ (都市 9 / 地方 38)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.metrics import roc_curve, roc_auc_score, precision_recall_curve, average_precision_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]  # 縦持ち(2012-2023年)なので必ず年度でフィルタ
y = (df['A1101'] >= 5_000_000).astype(int)
X = StandardScaler().fit_transform(df[['C5403', 'E6302', 'L3221']])

model = LogisticRegression(max_iter=1000)
cv = StratifiedKFold(5, shuffle=True, random_state=42)
proba = cross_val_predict(model, X, y, cv=cv, method='predict_proba')[:, 1]

fpr, tpr, _ = roc_curve(y, proba)
prec, rec, _ = precision_recall_curve(y, proba)
print(f"ROC-AUC = {roc_auc_score(y, proba):.3f}")
print(f"PR-AUC  = {average_precision_score(y, proba):.3f}")

📤 実行例:

ROC-AUC = 0.977 PR-AUC = 0.869

💬 ROC-AUC=0.98 で「ほぼ完璧なモデル」に見えるが、 PR-AUC は 0.87。 不均衡データでは ROC-AUC が楽観的 になることが知られていて、 真の性能は PR-AUC のほうが正しく反映します。 病気・不正検出のような 陽性が稀 な場面では PR-AUC を主指標にしてください。

📋 シーン別の推奨指標

シーン主指標理由
クラスがバランスAccuracy / F1直感的
不均衡 + 陽性検出重視Recall / PR-AUC少数クラスを評価
誤検出が深刻Precision / SpecificityFP を抑制
医療スクリーニングRecall (sensitivity) 優先見逃しが致命的
確率較正が必要Brier score / log loss確率の質を測る
多クラス + 不均衡F1-macro全クラスを平等評価

⚖️ 不均衡データへの対処: SMOTE / class_weight / 閾値調整

分類問題では クラスの数が極端に偏っている(例: 不正取引 0.1%、 病気の人 1%)ことが多く、 標準的な学習では 多数クラスばかり予測 するモデルになります。 対処策は大きく 4 つ。

手法仕組み利点欠点
アンダーサンプリング多数クラスを削減計算速い情報を捨てる
オーバーサンプリング (SMOTE)少数クラスを合成情報損失なし過学習リスク
class_weight='balanced'損失に重み付けデータを変えない確率較正が崩れる
閾値調整0.5 → 0.3 等学習後でも適用可どこに置くか難しい

🐍 閾値調整で recall を上げる

このコードでやること: SSDSE-B-2026 の都市/地方分類で、 閾値を 0.5 → 0.3 → 0.7 と変えながら precision/recall がどう変わるかを観察。

📥 入力データ: 上記と同じ (都市 9 / 地方 38)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.metrics import precision_score, recall_score, f1_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]  # 縦持ち(2012-2023年)なので必ず年度でフィルタ
y = (df['A1101'] >= 5_000_000).astype(int)
X = StandardScaler().fit_transform(df[['C5403', 'E6302', 'L3221']])

model = LogisticRegression(max_iter=1000)
cv = StratifiedKFold(5, shuffle=True, random_state=42)
proba = cross_val_predict(model, X, y, cv=cv, method='predict_proba')[:, 1]

for th in [0.3, 0.5, 0.7]:
    pred = (proba >= th).astype(int)
    p = precision_score(y, pred)
    r = recall_score(y, pred)
    f = f1_score(y, pred)
    print(f"閾値 {th}: P={p:.3f}  R={r:.3f}  F1={f:.3f}")

📤 実行例:

閾値 0.3: P=0.875 R=0.778 F1=0.824 閾値 0.5: P=0.800 R=0.444 F1=0.571 閾値 0.7: P=0.750 R=0.333 F1=0.462

💬 閾値 0.5(標準): 9 都市のうち 5 県を見逃し recall=0.444。
閾値 0.3: 見逃しが 2 県に減り recall=0.778、 F1 も 0.824 で最大。
閾値 0.7: 検出は 3 県のみ (recall=0.333) に低下。
この例では既定の 0.5 が最適とは限らず、 閾値を下げた方が良い結果になりました。 「最適閾値はタスクの目的で変わる」ことが分かります。 がん検診のように見逃しが致命的なら低め、 誤警報のコストが大きいなら高めのように、 誤りのコスト から逆算して決めるのが正しい姿勢です。

🎨 概念図で押さえる

分類モデルの基礎を 3 枚で振り返る。 1 枚目 = 5 アルゴリズムの決定境界、 2 枚目 = 仮定と適用条件、 3 枚目 = 評価指標の関係。

図1: 5 アルゴリズムの決定境界 (イメージ)

ロジスティック 線形 (直線) k-NN 局所的 (曲線) SVM マージン最大化 NB 確率分布 LDA 分布の境界 2 クラス分類の例。 SVM のサポートベクトル、 LDA の正規分布仮定など各手法の特徴が見える。

図2: 仮定と適用条件のチートシート

線形 (Log Reg/LDA) 仮定: クラス境界が線形 適: 高次元/解釈重視 特徴量: 標準化推奨 確率的 (NB) 仮定: 特徴量が条件独立 適: テキスト/カテゴリ 特徴量: カウント/TF-IDF 非線形 (k-NN/SVM-rbf) 仮定: 局所/カーネル空間 適: 複雑な境界 特徴量: 必ずスケーリング 選択基準: データ規模 + 線形性 + 解釈性 + 速度 小規模/解釈→Log Reg、 大規模/精度→SVM/k-NN、 テキスト→NB

図3: 評価指標の関係 (混同行列ベース)

予測 実測 TP 正→正 FN 正→負 (見逃し) FP 負→正 (誤警報) TN 負→負 Accuracy = (TP+TN)/全件 Precision = TP / (TP+FP) Recall = TP / (TP+FN) F1 = 2 · Prec · Rec / (Prec + Rec)

→ 「決定境界の形 (図1)」「仮定の違い (図2)」「指標の構造 (図3)」がアルゴリズム選択時の三本柱。

🧭 分類モデル選択の実践フロー(R260 補完)

「ロジスティック・k-NN・SVM・NB・LDA のどれを使うか」は、 データの特性とビジネス要件で決まる。 闇雲に全部試すのではなく、 以下の 5 ステップフローで段階的に絞り込むのが効率的である。 SSDSE-B-2026 を例にしながら、 各ステップで判断材料となる指標を整理する。

ステップ 1: 問題の本質を確認する

最初に「予測したいか、 解釈したいか、 確率を出したいか」を明確にする。 予測重視 → SVM や決定木ベース、 解釈重視 → ロジスティック回帰や LDA、 確率重視 → ロジスティック回帰や NB が第一候補。 SSDSE-B-2026 で「都道府県を高齢化進行県/未進行県に分類」するなら、 政策議論で 「なぜそう分類されるか」 が求められるので、 解釈性が高いロジスティック回帰や決定木を選ぶ。

ステップ 2: データ量と次元を確認する

サンプル数 n と特徴量数 p の関係で適切なモデルが変わる。 n >> p(大規模・低次元)→ k-NN や SVM(RBF)で非線形を捉える。 n ≈ p(中程度)→ ロジスティック回帰・LDA で過学習を回避。 n << p(高次元・小標本)→ ナイーブベイズ・正則化ロジスティック回帰(Lasso/Ridge)で次元の呪いを回避。 SSDSE-B の 47 サンプル × 数十特徴量は典型的な「n < p または n ≈ p」ケースで、 NB やロジスティック回帰が第一候補となる。

ステップ 3: 特徴量の性質を確認する

全て数値 → 全モデル適用可。 カテゴリ多数 → 決定木・NB が得意。 スケール感が異なる → ロジスティック・SVM・k-NN は標準化必須、 決定木・NB は不要。 SSDSE-B-2026 は人口(万人単位)、 所得(円単位)、 割合(%)と単位が異なるため、 標準化を前提に SVM やロジスティックを使う。

ステップ 4: クラス不均衡をチェック

クラス比 50:50 → そのまま全モデル適用可。 クラス比 90:10 → クラス重み付き SVM・ロジスティック、 または SMOTE などで人工的にバランス調整。 SSDSE-B (2023年度) で「高齢化率 35% 以上の県」を陽性クラスとすると、 47 県のうち陽性は 6 県(約 13%)とかなり不均衡なので、 class_weight='balanced' や閾値調整を併用する。 閾値を「高齢化率が中央値 (約 32%) 以上」に変えれば 50:50 に近づき、 標準モデルをそのまま使える。

ステップ 5: クロスバリデーションで実証比較

ステップ 1-4 で 2-3 モデルに絞った後、 5-fold CV で精度・F1・AUC を実証比較する。 1 モデルで決め打ちはせず、 必ず 2-3 つを並べて比較する。 SSDSE-B-2026 サンプルで、 ロジスティック・k-NN・SVM の 5-fold CV AUC は、 たとえば 0.92 / 0.85 / 0.94 のような結果になる。 標準偏差も併記し、 統計的有意性も評価する。

状況第一候補第二候補避けるべき
解釈重視ロジスティック決定木 / LDASVM(RBF)
予測精度重視SVM(RBF)k-NNNB (過度に単純)
小標本 (n < 100)NBロジスティック + L2深層学習
高次元 (p > n)L1 ロジスティックNBk-NN (次元の呪い)
確率出力必須ロジスティックNBSVM (距離→確率変換が雑)

この 5 ステップを回せば「とりあえず深層学習」「とりあえずランダムフォレスト」という雑なモデル選択を避けられる。 むしろ 「シンプルなロジスティック回帰で十分な精度が出るなら、 それが最善」 という結論に達することも多い。 オッカムの剃刀(simpler is better)が分類モデル選択の鉄則である。

📈 評価指標の使い分け(R260 補完)

分類モデルの評価指標は 10 種類以上あり、 用途で使い分ける必要がある。 ここでは主要 7 指標を「正解率系」「ランキング系」「コスト系」の 3 系統で整理する。

正解率系(適合率・再現率・F1)

Accuracy: (TP+TN)/(TP+TN+FP+FN)。 不均衡データには不向き(90:10 なら 90% は当たり前)。 Precision: TP/(TP+FP)。 陽性予測のうち実際に陽性の割合。 「偽陽性を減らしたい」場面で重要。 例: 重要顧客への高額キャンペーン。 Recall (Sensitivity): TP/(TP+FN)。 実際の陽性のうち捕捉できた割合。 「偽陰性を減らしたい」場面で重要。 例: がん診断、 セキュリティ侵入検知。 F1 score: Precision と Recall の調和平均。 両方を同程度重視。

ランキング系(ROC-AUC・PR-AUC)

閾値に依存しない指標。 ROC-AUC: 全ての閾値で TPR vs FPR を描き、 曲線下面積。 0.5 がランダム、 1.0 が完璧。 PR-AUC: Precision-Recall 曲線下面積。 クラス不均衡に強い(ROC-AUC より過大評価しにくい)。 SSDSE-B 47 県の二値分類で AUC = 0.92 が出たら、 「相当強い分類器」と評価できる。

コスト系(コスト感度ロス・Log Loss)

Log Loss (Cross-Entropy): 確率予測 p に対する -log(p) の平均。 確率の正確さを評価。 ロジスティック回帰や NN の損失関数として使う。 コスト感度行列: FP と FN のコストが異なるとき、 加重して総コストを最小化する。 例: 医療診断で FN(見逃し)のコストが FP(誤陽性)の 10 倍なら、 閾値を下げて Recall を上げる。

指標用途SSDSE-B での典型値
Accuracy均衡データの全体感0.85
PrecisionFP を減らしたい0.80
RecallFN を減らしたい0.75
F1P と R の両立0.77
ROC-AUC閾値非依存比較0.90
PR-AUC不均衡データの比較0.72
Log Loss確率予測の正確さ0.35

論文や報告書では 必ず複数の指標を併記する こと。 Accuracy だけ報告するのは「不誠実」と批判される時代である。 最低でも Precision・Recall・F1・AUC の 4 つを表で示す。 さらにコスト感度が問題なら、 加重総コストも算出する。 これが現代のベストプラクティスである。

🎮 触って理解する — 決定境界を手で動かす

2 クラスの点群に対して 1 本の直線(線形決定境界) を自分の手で引いてみましょう。 直線の両側で「赤クラス」「青クラス」に予測が分かれ、 正解率と混同行列がリアルタイム更新 されます。 端点をドラッグ(またはスライダー)で動かし、 どこまで正しく分類できるか体感してください。 分離度スライダー を下げて 2 クラスを重ねると、 どんな直線でも必ず誤分類が残る(=線形分離不可能)ことが分かります。

特徴量1(例: 商業地地価スコア)→ 特徴量2(例: 大学生比スコア)→ 青側 = クラス1 予測 赤側 = クラス0 予測

💡 SVG 上の 2 つの丸ハンドルを直接ドラッグ/タッチしても動かせます。

現在の正解率 (Accuracy)
– / 40 点
混同行列(正例=クラス1)
予測1予測0
実測1
実測0
Precision:
Recall:
F1:

🧠 もっと深く — 直感・落とし穴・発展

直感(境界で領域を分ける): 線形分類器がやっているのは 「特徴量空間を直線 1 本で 2 つの半平面に切り分ける」 だけです。 片側を「クラス1」、 反対側を「クラス0」と決める。 上の図で直線をどう動かしても半平面は 2 つのまま——だからこそ 入り組んだ配置は 1 本の直線では捉えきれない。 混同行列の 4 マス(TP/FP/FN/TN)は、 この切り分けの結果を「実測 × 予測」で数え上げた表そのものです(詳しくは 混同行列)。

よくある落とし穴:

発展: 直線で足りないときの選択肢は 3 方向あります。 (1) 非線形分類器——SVM のカーネル、 k-NN の局所境界、 ニューラルネット の曲がった境界で複雑な形に対応。 (2) 多クラス分類——One-vs-Rest などで 3 クラス以上を扱う。 (3) 確率的分類——硬い 0/1 ではなく「クラス1 である確率」を出し、 用途に応じてしきい値を選ぶ(ロジスティック回帰)。 なお線形分離可能性そのものは、 データを高次元へ写像すれば改善しうる、 という考えがカーネル法の出発点です。 分類全体の見取り図は 分類(総論) を参照。

📐 判別分析(LDA / QDA)

🍰 まずはやさしく

データの分布から分ける方法です。

グループごとの特徴を捉えるために使います。

都道府県のデータなどを分けるときに役立ちます。

線形判別分析などの具体的な仕組みを読みます。

各クラスがガウス分布に従うと仮定し、 ベイズ最適境界を導出:

仮定(多変量正規 + 等分散)が成立すれば最適。 違反でもしばしばロバスト。 PCA と数学的関係が深い。

🎯 このコードでやること: モデルを学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
1
2
3
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis
lda = LinearDiscriminantAnalysis().fit(X, y)
qda = QuadraticDiscriminantAnalysis().fit(X, y)
📤 このブロックは標準出力には何も出さない

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

🔢 多クラス分類戦略

2 値分類器を $K$ クラスに拡張する3つの戦略:

🆚 手法選択の指針

状況 推奨
解釈性が最優先ロジスティック回帰、 決定木
小サンプル(n < 100)SVM、 LDA、 ナイーブベイズ
高次元(テキスト等)線形 SVM、 Naive Bayes、 ロジスティック
非線形・複雑な境界SVM (RBF)、 RF、 GBM、 NN
確率予測が必要ロジスティック、 NB、 LDA
テキスト分類Multinomial NB、 線形 SVM、 BERT
テーブルデータ(大規模)XGBoost、 LightGBM

🚧 よくある誤解

❌ 誤解✅ 正しい理解
k-NN は標準化不要距離計算が歪むので必須
SVM は常に最強大規模データでは遅い。 確率出力も弱い
ナイーブベイズは独立仮定が崩れたら使えない理論的には崩れていても実用上しばしば有効
ロジスティック回帰は「回帰」分類モデル。 名前にだまされない
k-NN の k は大きいほど良いバイアス↑になる。 CV で最適 k を選ぶ
LDA は線形なので非線形には無力基底変換、 カーネル化、 QDA で対応可

📝 練習問題

問1:k-NN で k=1 と k=100 のどちらが過学習しやすいか?

k=1。 訓練データの 1 点に完全に従うので、 ノイズまで覚える(高バリアンス)。 k=100 は 100 点の平均で滑らか(高バイアス)。 CV で最適 k を選ぶ。

問2:スパム判定(テキスト分類)に向く分類器は?

Multinomial Naive Bayes、 線形 SVM、 ロジスティック回帰(TF-IDF 特徴量 + L1/L2 正則化)。 高次元の単語ベクトルに対して線形モデルが効果的。 現代では BERT/Transformer 系も標準。

問3:ロジスティック回帰の係数 $\beta_j = 1.5$ の解釈は?

「$x_j$ が 1 単位増えると、 ログオッズ $\log(p/(1-p))$ が 1.5 増える」。 オッズ比に変換すれば $e^{1.5} \approx 4.48$。 つまり「$x_j$ が 1 単位増えるとオッズが約 4.5 倍」。

問4:SSDSE 47都道府県を「東日本/西日本」に分類するコード骨格を書け。

🎯 このコードでやること: SSDSE-B-2026 を読み込み、K-分割交差検証で評価。

📥 入力例 # 入力: data/raw/SSDSE-B-2026.csv (47 都道府県 × 100超の社会経済指標) # 先頭 3 行(2023年度、 A1101 = 総人口、 A4101 = 出生数 など): # pref A1101 A4101 F3101 # 北海道 5092000 24430 156458 # 青森県 1184000 5696 43713 # 岩手県 1163000 5432 40955
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932')
# 前処理 ... X, y を作成
X_std = StandardScaler().fit_transform(X)

for name, model in [('Logistic', LogisticRegression(random_state=0)),
                    ('kNN', KNeighborsClassifier(n_neighbors=5)),
                    ('SVM', SVC(kernel='rbf'))]:
    score = cross_val_score(model, X_std, y, cv=5, scoring='f1').mean()
    print(f'{name}: F1 = {score:.3f}')
📤 実行例(実測) Logistic: F1 = 0.427 kNN: F1 = 0.693 SVM: F1 = 0.693

💬 読み方: skiprows=[1] で 2 行目の日本語列名行を飛ばし(1 行目の英字コードが列名になる)、 encoding='cp932' で文字化けを回避 / 分割数 K を増やすほど分散は小さいが計算コスト増。

📋 報告フォーマット

「2 値分類タスク(n=2000、 陽性率 30%)に対し、 ロジスティック回帰・k-NN(k=10)・SVM(RBF) を 5-fold CV で比較。 結果:LR の F1=0.71±0.02、 kNN=0.65±0.04、 SVM=0.74±0.02。 SVM が最良だが、 解釈性を考慮し本番ではロジスティック回帰を採用。 標準化必須のため StandardScaler を Pipeline に組み込んだ。」

🚀 発展トピック

多クラス分類の評価

クラス不均衡への対処

確率校正(Probability Calibration)

SVM・決定木の確率出力は校正されていない(実際の頻度と乖離)。 Platt scaling(シグモイドフィット)や isotonic regression で校正可能。

🎯 このコードでやること: モデルを学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.calibration import CalibratedClassifierCV

# base_model = 較正する前の分類器。ここで作っておく
base_model = LogisticRegression(max_iter=1000)

calibrated = CalibratedClassifierCV(base_model, method='sigmoid', cv=5)
calibrated.fit(X_train, y_train)
print('較正後の予測確率(先頭 5 件):',
      calibrated.predict_proba(X_test)[:5, 1].round(3))
📤 実行例(実測) 較正後の予測確率(先頭 5 件): [0.328 0.232 0.963 0.682 0.997]

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

🔬 数式を言葉で読み解く

前節の数式に含まれる記号を、 日本語の意味に翻訳する。

classification basic の数式は、 これらの記号を組み合わせて「データから未知量を推定する」あるいは「データの構造を要約する」プロセスを記述している。

🧮 SSDSE-B 実データでの分類例 — 47都道府県を「東日本/西日本」に二値分類

🧮 SSDSE-B 実データでの分類例 — 47都道府県を「東日本/西日本」に二値分類

SSDSE-B-2026(都道府県別の社会経済データ)を用いて、 各分類モデルを実際に動かすハンズオン例。 目的変数は「東日本=1(北海道・東北・関東・中部の 23 都道県)/西日本=0(近畿以西の 24 府県)」とし、 特徴量は「総人口」「65歳以上人口」「商業地地価」「消費支出」など 6 変数。

🎯 このコードでやること: SSDSE-B-2026 を読み込み、K-分割交差検証で評価。

📥 入力例 # 入力: data/raw/SSDSE-B-2026.csv (47 都道府県 × 100超の社会経済指標) # 先頭 3 行(2023年度、 A1101 = 総人口、 A4101 = 出生数 など): # pref A1101 A4101 F3101 # 北海道 5092000 24430 156458 # 青森県 1184000 5696 43713 # 岩手県 1163000 5432 40955
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.pipeline import Pipeline

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
df.columns = [c.strip() for c in df.columns]
df = df[df['年度'] == 2023]  # 縦持ち(2012-2023年)なので必ず年度でフィルタ

# 東日本(コード01-23)= 1、 西日本(24-47)= 0。 地域コードは 'R01000' 形式
df['east'] = (df['地域コード'].str.extract(r'R(\d{2})')[0].astype(int) <= 23).astype(int)

feats = ['総人口', '15歳未満人口', '65歳以上人口',
         '標準価格(平均価格)(商業地)', '消費支出(二人以上の世帯)', '一般病院数']
X = df[feats].astype(float).values
y = df['east'].values

models = {
    'LogisticRegression': LogisticRegression(max_iter=1000),
    'kNN(k=5)'          : KNeighborsClassifier(n_neighbors=5),
    'SVM(RBF)'          : SVC(kernel='rbf', C=1.0, gamma='scale'),
    'GaussianNB'        : GaussianNB(),
    'LDA'               : LinearDiscriminantAnalysis(),
}

cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)
for name, clf in models.items():
    pipe = Pipeline([('sc', StandardScaler()), ('clf', clf)])
    acc = cross_val_score(pipe, X, y, cv=cv, scoring='accuracy').mean()
    f1  = cross_val_score(pipe, X, y, cv=cv, scoring='f1').mean()
    print(f'{name:<22s}  Acc={acc:.3f}  F1={f1:.3f}')

📤 実行例:

LogisticRegression Acc=0.720 F1=0.654 kNN(k=5) Acc=0.636 F1=0.616 SVM(RBF) Acc=0.680 F1=0.679 GaussianNB Acc=0.553 F1=0.324 LDA Acc=0.807 F1=0.802

💬 読み方: LDA が最良 Acc=0.807 / F1=0.802。 n=47 の小標本では非線形の SVM・k-NN が不利になりやすい。 GaussianNB は Acc=0.553 と最低で、 東西の正規分布仮定が実データと合わなかったことを示す。 F1 (binary, 東日本=1) は Acc とほぼ連動しているが、 クラスバランスがほぼ 1:1 のため指標間の乖離は小さい。

合成データで TP/TN/FP/FN から精度・再現率・F1 を計算する。

Step 1: 混同行列

 予測+予測-
実際+TP=40FN=10
実際-FP=5TN=45

Step 2: 各指標

Accuracy = (40+45)/(40+10+5+45) = 85/100 = 0.85 Precision = 40/(40+5) = 40/45 ≈ 0.889 Recall = 40/(40+10) = 40/50 = 0.80 F1 = 2·P·R/(P+R) = 2·0.889·0.80/(0.889+0.80) = 1.4222/1.689 ≈ 0.842

🐍 Python で再現

1
2
3
4
5
6
7
8
9
tp, fn, fp, tn = 40, 10, 5, 45
acc = (tp+tn)/(tp+fn+fp+tn)
prec = tp/(tp+fp)
rec = tp/(tp+fn)
f1 = 2*prec*rec/(prec+rec)
print(f"Accuracy = {acc:.3f}")
print(f"Precision = {prec:.3f}")
print(f"Recall = {rec:.3f}")
print(f"F1 = {f1:.3f}")

📤 実行結果

Accuracy = 0.850 Precision = 0.889 Recall = 0.800 F1 = 0.842

💬 手計算 (Step 2) と Python 出力が完全一致。

🐍 scikit-learn ライブラリ早見表

🐍 scikit-learn ライブラリ早見表

モデル クラス 主要パラメータ 推奨用途
ロジスティック回帰LogisticRegressionC, penalty, solver, class_weight解釈性が重要。 ベースライン
k-NNKNeighborsClassifiern_neighbors, weights, metric小〜中規模、 非線形決定境界
線形SVMLinearSVCC, loss高次元疎データ(テキスト等)
カーネルSVMSVCC, kernel, gamma非線形・中規模データ
ナイーブベイズGaussianNB, MultinomialNBvar_smoothing, alphaテキスト分類、 ベースライン
LDALinearDiscriminantAnalysissolver, shrinkageクラスが正規・等共分散
QDAQuadraticDiscriminantAnalysisreg_paramクラスごとに分散が違うとき

共通ワークフロー

🎯 このコードでやること: K-分割交差検証で評価、分類器を学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV, StratifiedKFold

pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', LogisticRegression(max_iter=1000))
])
param_grid = {
    'clf__C': [0.01, 0.1, 1, 10, 100],
    'clf__penalty': ['l2'],
}
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
grid = GridSearchCV(pipe, param_grid, scoring='f1', cv=cv, n_jobs=-1)
grid.fit(X_train, y_train)
print('Best params:', grid.best_params_)
print('Best CV F1:', grid.best_score_)
📤 実行例(実測) Best params: {'clf__C': 10, 'clf__penalty': 'l2'} Best CV F1: 0.9333333333333332

💬 読み方: 分割数 K を増やすほど分散は小さいが計算コスト増。

🧭 モデル選択フローチャート

初学者向けの目安:

  1. 説明性が最優先 → ロジスティック回帰
  2. 高次元(>1000特徴量)・疎データ → 線形 SVM or ロジスティック+L1
  3. テキスト(BoW/TF-IDF) → MultinomialNB か LinearSVC
  4. 少データ・非線形 → カーネル SVM か k-NN
  5. 大規模テーブル → ロジスティック+SGD or 後述のツリーアンサンブル
  6. 確率出力が必要 → ロジスティック回帰、 確率校正したSVM、 GaussianNB

「迷ったらこの順」(実務 Tips)

  1. ロジスティック回帰(標準化 + L2 正則化)でベースラインを作る
  2. 同じ前処理で k-NN・線形 SVM・GaussianNB を試し、 CV スコアを比較
  3. 非線形性が必要そうなら RBF カーネル SVM
  4. それでも足りなければ Random Forest / XGBoost(次章)

💼 実務応用例

📜 分類モデルの歴史

古典手法が今も使われる理由

⚖️ クラス不均衡データへの対処

実務の多くは正例率が 1〜10% という不均衡データ。 工夫なしに学習すると「全部負例」と予測してしまう。

対処の選択肢

🎯 このコードでやること: 分類器を学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score

# ── この抜粋だけで動くように、学習用と「閾値を決める用」に分ける ──
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
_d = _d[_d['SSDSE-B-2026'] == 2023]
_X = StandardScaler().fit_transform(_d[['A4101', 'A1303', 'L3221']].astype(float))
_y = (_d['A1101'] > _d['A1101'].median()).astype(int).values
X_train, X_val, y_train, y_val = train_test_split(
    _X, _y, test_size=0.4, random_state=0, stratify=_y)

clf = LogisticRegression(class_weight='balanced', max_iter=1000)
clf.fit(X_train, y_train)
proba = clf.predict_proba(X_val)[:, 1]

thr_grid = np.linspace(0.05, 0.95, 19)
f1s = [f1_score(y_val, proba >= thr) for thr in thr_grid]
best_thr = thr_grid[int(np.argmax(f1s))]
print('Best threshold:', round(best_thr, 2), 'F1:', round(max(f1s), 3))
📤 実行例(実測) Best threshold: 0.6 F1: 0.875

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

✅ 分類モデル構築チェックリスト

1. scikit-learn の Pipeline で完全自動化

🎯 このコードでやること: 分類器を学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV

pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf'   , LogisticRegression(max_iter=1000, solver='liblinear')),
])

param_grid = {
    'clf__C'      : [0.01, 0.1, 1, 10, 100],
    'clf__penalty': ['l1', 'l2'],
}
gs = GridSearchCV(pipe, param_grid, cv=5, scoring='f1', n_jobs=-1)
gs.fit(X, y)
print('best params:', gs.best_params_)
print('best F1:', gs.best_score_)

⚠️ さらに深い落とし穴 — 実務で踏みやすい 6 つ

① クラス不均衡を放置した「精度 95% のゴミモデル」

陽性率が 5% しかないデータで「常に陰性」と予測するだけで Accuracy=0.95 が出てしまう。 これは分類器として無意味なので、 評価指標は F1、 PR-AUC、 Recall など「陽性側を捉えているか」を測るものに切り替える必要がある。 対策として class_weight='balanced'、 SMOTE などのオーバーサンプリング、 閾値調整(decision_function の出力に対する手動カットオフ)を組み合わせる。 不均衡の度合いが極端(陽性率 1% 未満)なら異常検知タスクとして再定義した方がよいケースもある。

② 標準化の「データリーク」

k-NN や SVM では特徴量の標準化が必須だが、 全データに対して fit_transform した後で train/test 分割すると、 テストデータの統計量(平均・分散)が訓練時に漏れる「データリーク」が起きる。 結果として CV スコアが楽観的に出るが、 本番デプロイ後に性能が崩れる。 正しい流儀は Pipeline で StandardScaler とモデルを束ね、 CV の各 fold 内で fit を完結させること。 これは sklearn の Pipeline / make_pipeline の最大の存在意義のひとつ。

③ 確率出力が「校正されていない」のに閾値で意思決定する

SVM の predict_proba(Platt scaling 経由)や RF の確率は校正が不十分なことが多い。 そのまま「p>0.5 で陽性」と扱うと、 リスクと利益のバランスが歪む。 医療診断や信用スコアリングのように確率の絶対値が意思決定に直結する場面では CalibratedClassifierCV による sigmoid / isotonic 校正を必ず通す。 校正度の評価には Brier score、 ECE(Expected Calibration Error)、 reliability diagram を用いる。

④ k-NN の「次元の呪い」を軽視する

特徴量次元 d が大きくなると、 任意の 2 点間のユークリッド距離が「ほぼ同じ値」に集中し、 「近い」「遠い」の区別が消失する。 これが次元の呪い(curse of dimensionality)で、 k-NN の精度を急激に劣化させる。 d ≥ 20 程度から目に見えて劣化する。 対策は PCA や UMAP による次元削減、 マンハッタン距離 / コサイン距離への切り替え、 そもそも特徴量選択で d を絞ること。 高次元データでは k-NN を諦めて線形 SVM やロジスティック回帰の方が頑健になる。

⑤ ロジスティック回帰の係数を「効果量」と取り違える

係数 β は「他の変数を一定にしたときのログオッズの変化」であり、 単位は特徴量のスケールに依存する。 標準化していない係数同士を「大きさ比較」して「変数 A の方が重要」と結論するのは誤り。 比較するなら標準化済み係数(z-スコア化した特徴量での係数)か、 オッズ比 e^β、 あるいは permutation importance を見る。 また、 多重共線性があると個々の β は不安定(分散が膨らむ)ので VIF も合わせて確認する。

⑥ SVM の C と γ を勘で決める

RBFカーネル SVM の性能は C(誤分類のペナルティ)と γ(RBF の幅)の組み合わせに極めて敏感。 既定値(C=1.0, gamma='scale')でも動くが、 ほぼ確実に最適ではない。 必ず GridSearchCV か RandomizedSearchCV で C ∈ {0.01, 0.1, 1, 10, 100}, γ ∈ {0.001, 0.01, 0.1, 1} を対数グリッドで探索する。 探索範囲が境界に当たったら範囲を広げ直す。 さらに、 大規模データでは SVM 自体が O(n²)〜O(n³) で遅いので、 LinearSVC(線形カーネル限定)や SGDClassifier に切り替える判断も必要。

⚠️ 分類の基礎で初学者が陥る 10 の落とし穴 (拡張版)

  1. Accuracy だけで判断 — 不均衡データでは「全部多数クラスと予測」で 90% 超になることがある。 PR-AUC や macro-F1 を併用。
  2. テストデータが学習に混入 — 前処理 (StandardScaler.fit など) をテストデータ込みでやる「リーク」。 Pipeline + cross_val を使う。
  3. クラスバランスを確認せず学習 — `value_counts()` で必ずクラス分布を確認する。
  4. 確率較正をしない — 木モデルや SVM の predict_proba は較正されていないことが多い。 `CalibratedClassifierCV` で補正。
  5. 閾値 0.5 を盲信 — タスクの目的に合わせて調整する。 ROC で「コスト曲線が最小になる点」を選ぶ。
  6. 多クラスで accuracy / micro-F1 のみ報告 — 不均衡多クラスでは macro-F1 / weighted-F1 を併記。
  7. クラスラベルの順序を仮定 — sklearn は学習データに現れる順なので、 `classes_` で確認する。
  8. OvR/OvO の違いを意識しない — 多クラス SVM は One-vs-Rest と One-vs-One で結果が変わる。
  9. 確率と予測ラベルを混同 — 「90% の確率で陽性」と「陽性ラベルが付いた」は別の情報。 ビジネスで使うなら確率を返す。
  10. 学習時とデプロイ時で前処理が違う — Scaler の統計量は学習データのものを再利用する。 Pipeline で固定するのが安全。

⚠️ 分類モデルでよくある失敗とリカバリ(R260 補完)

分類タスクで陥りやすい失敗を 5 つ紹介し、 それぞれのリカバリ手順を示す。 失敗してから学ぶより、 事前に予防する方が遥かに効率的である。

失敗 1: データリーケージ — テスト精度 100%

特徴量に「未来情報」や「ターゲット情報」が混入している失敗。 例: 「高齢化進行県」を予測するモデルで、 特徴量に「高齢者割合」を含めてしまう(これは答えに極めて近い情報)。 リカバリ: 特徴量リストを見直し、 ターゲットと因果的に独立な変数のみ使う。 時系列なら必ず時間軸で訓練/テスト分割(ランダム分割禁止)。

失敗 2: クラス不均衡無視 — Recall 0%

陽性が 5% のデータで「全部陰性」と予測しても精度 95%。 一見良いが、 陽性を全く検出できていない(Recall=0)。 リカバリ: class_weight='balanced' を指定、 または SMOTE で陽性を増やす、 または閾値を下げる。

失敗 3: 標準化忘れ — SVM・k-NN・ロジスティックの低性能

人口(10⁶ スケール)と高齢化率(10⁻¹ スケール)を混在させると、 距離ベースのモデルが人口にのみ反応してしまう。 リカバリ: StandardScaler や MinMaxScaler を Pipeline で組み込む。 これだけで精度が 10〜30% 改善することがある。

失敗 4: 過学習 — 訓練 95%、 テスト 60%

小標本で複雑なモデル(深い決定木、 RBF SVM の γ 大)を使うと過学習する。 リカバリ: モデルを単純化(LR + L2 正則化)、 max_depth を制限、 サンプル数を増やす(データ拡張)、 早期停止。

失敗 5: 評価指標の誤選択 — Accuracy だけで判断

不均衡データで Accuracy 90% を見て満足し、 デプロイ後に「陽性を 1 件も検出しない」と判明する失敗。 リカバリ: 必ず Precision・Recall・F1・AUC を併記。 ビジネス要件(FP・FN のコスト)を反映した指標を選ぶ。

これら 5 つの失敗パターンを意識すれば、 9 割の分類タスクは安全に進められる。 残りの 1 割(時間相関、 分布シフト、 ラベルノイズ)はより高度な対策が必要だが、 まずは基本の 5 つを押さえることが先決である。

🧬 5 モデルの詳細比較(R260 補完)

ロジスティック回帰・k-NN・SVM・ナイーブベイズ・LDA の 5 モデルを「数学的背景」「計算量」「ハイパーパラメータ」「実装上の注意」の 4 観点で比較する。 同じデータセットでも、 モデルごとに「得意な状況」「失敗しやすい状況」が大きく異なる。

1. ロジスティック回帰 (Logistic Regression)

数学的背景: P(Y=1|X) = σ(w·X + b) で確率を直接モデル化。 線形決定境界、 最尤推定で w を学習。 計算量: 訓練 O(n·p·iter)、 予測 O(p)。 高速。 ハイパーパラメータ: C(正則化の逆数、 大きいほど過学習しやすい)、 penalty(L1/L2/Elastic Net)、 solver(lbfgs, liblinear, saga)。 注意: 標準化必須、 多重共線性に弱い(L2 正則化で緩和)。 SSDSE-B-2026 で「県のクラス分類」なら最も標準的な選択肢。

2. k-NN (k-Nearest Neighbors)

数学的背景: 訓練なし(lazy learning)、 予測時に近傍 k 点の多数決。 計算量: 訓練 O(1)、 予測 O(n·p)。 大規模データでは遅い(KD-tree や Ball-tree で改善可)。 ハイパーパラメータ: k(近傍数、 小さいと過学習、 大きいとバイアス)、 距離(Euclidean, Manhattan, Cosine)、 weights(uniform vs distance)。 注意: 標準化必須、 次元の呪い(高次元で距離が無意味化)。 SSDSE-B 47 件のような小標本で k=5 程度なら有効。

3. SVM (Support Vector Machine)

数学的背景: マージン最大化、 カーネルトリックで非線形境界。 双対問題で QP(二次計画)を解く。 計算量: 訓練 O(n²) 〜 O(n³)、 大規模データには不向き。 ハイパーパラメータ: C(マージンとマージン違反のトレードオフ)、 kernel(linear, rbf, poly)、 gamma(RBF カーネルの広がり)。 注意: 標準化必須、 GridSearchCV での C/gamma 調整は計算コスト大。 確率出力は probability=True で得られるが、 較正は雑(Platt scaling)。

4. ナイーブベイズ (Naive Bayes)

数学的背景: P(Y|X) ∝ P(X|Y) P(Y) (ベイズの定理)、 特徴量間独立を仮定(「ナイーブ」の由来)。 計算量: 訓練 O(n·p)、 予測 O(p)。 極めて高速。 ハイパーパラメータ: alpha(ラプラス平滑化、 Multinomial NB)、 var_smoothing(Gaussian NB)。 注意: 特徴量独立性は現実には成立しないが、 分類性能はそこそこ高い(テキスト分類の定番)。 小標本でも安定して動く。

5. LDA (Linear Discriminant Analysis)

数学的背景: クラス内分散最小・クラス間分散最大の線形射影、 Fisher の判別関数。 計算量: 訓練 O(n·p² + p³)、 予測 O(p²)。 ハイパーパラメータ: solver(svd, lsqr, eigen)、 shrinkage(共分散行列の縮約)。 注意: 共通共分散の仮定、 正規性の仮定。 仮定が成立すれば LR と同等以上の性能。 QDA は各クラス独自の共分散を許容するが、 パラメータ数が増えて過学習しやすい。

モデル境界計算量解釈性確率出力
LR線形高速
k-NN局所非線形遅い
SVM (RBF)非線形×△ (Platt)
NB確率的最高速
LDA線形高速

5 モデルを「全て試してから決める」のは時間の無駄。 ステップ 1-3 で 2-3 モデルに絞り、 CV で実証比較するのが効率的なアプローチである。 初学者はまず 「ロジスティック回帰 + 標準化 + L2 正則化」 を完璧にマスターすることを推奨する。 これだけで実務の 60% は対応できる。

🛠 ハイパーパラメータ調整の実践(R260 補完)

分類モデルの性能はハイパーパラメータ (HP) で大きく変わる。 闇雲なグリッドサーチではなく、 「直感的な範囲指定 → ランダムサーチ → ベイズ最適化」 の 3 段階で効率化するのが現代的アプローチである。 SSDSE-B-2026 を例に手順を示す。

段階 1: 直感的な範囲指定

まず各 HP に「妥当な範囲」を設定する。 例えばロジスティック回帰の C は対数スケールで [0.001, 1000] が定番。 SVM の C も同じ、 gamma は [0.001, 10] が標準。 k-NN の k は [3, 21] の奇数。 決定木の max_depth は [3, 20]。 この範囲を超えて探索するのは時間の無駄。

段階 2: ランダムサーチ

グリッドサーチ(全組み合わせ)よりも、 sklearn の RandomizedSearchCV で 50-100 ランダムサンプリングする方が、 同じ計算量で良い HP を見つける確率が高い。 これは Bergstra & Bengio (2012) の有名な論文で示された結果。 50 回の試行で「ほぼ最適」に達することが多い。

段階 3: ベイズ最適化

本気で最適化したいときは OptunaHyperopt でベイズ最適化(TPE アルゴリズム)を使う。 過去の試行結果を確率モデルで学習し、 「次に試すと良い HP」を逐次提案する。 30-50 試行で従来のグリッドサーチ 500 試行と同等以上の精度に到達する。

SSDSE-B での実例

「47 県を高齢化率で二値分類」するタスク(以下の数値は手順を説明するための仮想例)。 ロジスティック回帰の C を [0.001, 1000] で 50 回ランダムサーチ → 最適 C ≈ 0.3、 CV AUC = 0.92。 続いて SVM (RBF) の C × gamma を 100 回ランダムサーチ → 最適 (C=10, gamma=0.05)、 CV AUC = 0.94。 SVM が上回ったが、 解釈性を考慮すると 「ロジスティック回帰 + L2 で AUC 0.92」を選ぶのが妥当 な判断。 数値だけでなく 「解釈性とのトレードオフ」 を意識して HP を選ぶことが重要である。

モデル主要 HP推奨範囲探索方法
LRC, penaltyC: log[1e-3,1e3], L1/L2/ENRandomized 30
k-NNn_neighbors, weightsk: 3-21 oddGrid 全列挙
SVMC, gamma, kernelC/gamma: log[1e-3,1e3]Optuna 50
NBalpha, var_smoothingalpha: log[1e-3,10]Randomized 20
LDAshrinkage, solvershrinkage: 0-1 or 'auto'Grid 全列挙

HP 調整に時間をかけすぎないこと。 経験則では「総開発時間の 20-30% 以内」が目安。 残りは特徴量エンジニアリング、 データ品質改善、 ドメイン知識の取り込みに使う方がリターンが大きい。 「賢いモデル」よりも「賢い特徴量」 が勝つことが多い。

📊 多クラス分類への拡張(R260 補完)

本ページは主に二値分類を扱ったが、 実務では 3 クラス以上の 多クラス分類 も頻出する。 主要な拡張戦略を整理する。

戦略 1: One-vs-Rest (OvR)

クラスごとに「そのクラス vs それ以外」の二値分類器を訓練。 K クラスなら K 個のモデル。 ロジスティック回帰、 SVM で標準採用。 サンプル数 n × クラス数 K の計算量。 解釈は容易だが、 クラス不均衡が発生しやすい(各 OvR で「それ以外」が多数派)。

戦略 2: One-vs-One (OvO)

クラス対ごとに二値分類器を訓練。 K クラスなら K(K-1)/2 個のモデル。 SVM で標準(小規模クラスペア)。 各分類器のサンプル数が小さいので計算は速いが、 モデル数が増えて予測時に投票が必要。

戦略 3: ソフトマックス (Multinomial Logistic)

直接 K クラスの確率を同時推定。 ロジスティック回帰の多クラス版(multi_class='multinomial')、 NN の出力層 (softmax) に相当。 一つのモデルで K 個の確率を出すので計算効率が良い。

戦略 4: 階層分類

クラスに階層構造があるとき(例: 動物 → 哺乳類/鳥類 → 犬/猫/雀)、 各階層で二値分類器を訓練し連結。 ImageNet などの大規模分類で使われる。

戦略モデル数典型的な適用先
OvRKLR, SVM (標準)
OvOK(K-1)/2SVM, 少クラス(K<10)
Softmax1NN, Multinomial LR
階層階層数ImageNet, 生物分類

SSDSE-B-2026 で「県を 5 段階に分類」するなら Softmax が第一候補。 クラス数 K が大きい(K=100 以上)なら、 ヒエラルキカルソフトマックス (Hierarchical Softmax) や Negative Sampling で効率化する。 自然言語処理の単語予測(語彙数 10 万以上)で広く使われる技術である。

🎓 分類モデル習得ロードマップと推奨資料(R260 補完)

分類モデルを体系的に学ぶための 3 ヶ月ロードマップと推奨資料 10 件を提示する。 入門者から中級者への成長を目標にする。

第 1 ヶ月: ロジスティック回帰の徹底理解

線形回帰との違い、 シグモイド関数、 最尤推定、 オッズ比の解釈、 L1/L2 正則化。 SSDSE-B-2026 で「県のクラス分類」を 5 種類のターゲットで実装。 解釈、 係数の符号、 標準化の効果を確認する。 教科書: Hastie, Tibshirani, Friedman "The Elements of Statistical Learning" 第 4 章。

第 2 ヶ月: 5 モデルの比較実装

k-NN, SVM, NB, LDA を順に実装し、 SSDSE-B-2026 で比較。 各モデルの「得意/不得意」を表に整理する。 評価指標を 7 つ全部計算し、 CV で標準偏差まで報告する。 ハイパーパラメータ調整を Optuna でやってみる。

第 3 ヶ月: 応用と発展

多クラス分類、 クラス不均衡、 オンライン学習、 アンサンブル(Bagging, Boosting)。 XGBoost, LightGBM の使い方も学ぶ。 自分の興味のあるデータセット(Kaggle、 SIGNATE)でコンペに参加する。 この時点で「分類モデルのプロ」と言えるレベルに到達する。

推奨資料 10 選

(1) Hastie, Tibshirani, Friedman "The Elements of Statistical Learning, 2nd ed." — 統計的学習理論の決定版、 第 4 章が分類モデル。 (2) James, Witten, Hastie, Tibshirani "An Introduction to Statistical Learning, 2nd ed." — ISLR、 R/Python の入門書、 第 4 章。 (3) Bishop "Pattern Recognition and Machine Learning" — PRML、 ベイズ的視点からの分類。 (4) Murphy "Probabilistic Machine Learning: An Introduction" — 2022 年の最新教科書、 包括的。 (5) Géron "Hands-On Machine Learning with Scikit-Learn, Keras and TensorFlow, 3rd ed." — 実装重視、 第 3-5 章。 (6) Raschka "Machine Learning with PyTorch and Scikit-Learn" — 2022 年、 Python 実装の標準書。 (7) Coursera "Machine Learning Specialization" by Andrew Ng — 入門者の定番動画講座。 (8) Fast.ai "Practical Deep Learning for Coders" — トップダウンアプローチ、 実装から学ぶ。 (9) scikit-learn 公式ドキュメント — User Guide の Classification 章、 実装例が豊富。 (10) Kaggle Learn "Intermediate Machine Learning" — 短いレッスンで実践スキル習得。

これら 10 件を 3 ヶ月で全部触れる必要はない。 まず ISLR を 1 冊通読し、 並行して sklearn で実装、 Kaggle で実践 — このサイクルを 3 回まわせば「分類モデルの言語」が自分のものになる。 中級者になれば XGBoost や深層学習(CNN, Transformer)へ自然と進める。 まず基礎を盤石にすることが何より大切である。

📌 まとめ — 分類モデルの黄金 5 ルール

本ページで扱った分類モデル基礎のエッセンスを 5 ルールに凝縮する。 (1) シンプルから始める: ロジスティック回帰 + L2 + 標準化を完璧にマスターすれば実務の 60% を対応できる。 (2) 必ず標準化する: 距離ベース(k-NN, SVM)や勾配ベース(LR, NN)では標準化が前提。 これだけで精度が劇的に変わる。 (3) 評価指標を複数併記する: Accuracy だけは禁止。 Precision・Recall・F1・AUC を必ず示す。 (4) クラス不均衡を意識する: 90:10 のデータで Accuracy 90% に騙されない。 PR-AUC や F1 を見る。 (5) ドメイン知識を最後の味方にする: モデルは万能ではない。 業務理解・特徴量設計が予測性能を 2 倍にすることが頻繁にある。 これら 5 ルールを毎回意識すれば、 分類タスクで失敗することは大幅に減る。

🔁 振り返りチェックリスト

分類モデルを作り終えたあと、 必ず以下の 10 項目を自分で確認してから「完成」と宣言する習慣をつけよう。 抜け漏れを防ぎ、 再現性と信頼性の高い分析になる。 (1) 訓練データとテストデータが時系列的に正しく分割されているか(リーケージ防止)。 (2) 特徴量に標準化やエンコーディングを適用しているか。 (3) クラス不均衡を確認し、 対策(class_weight, SMOTE, 閾値調整)を入れているか。 (4) 評価指標を 4 つ以上併記しているか(Accuracy, Precision, Recall, F1, AUC など)。 (5) 5-fold CV で標準偏差まで報告しているか。 (6) ハイパーパラメータの探索範囲を文書化し、 探索手法(Grid/Random/Optuna)を記録しているか。 (7) 混同行列を可視化し、 誤分類の傾向を分析しているか。 (8) 確率予測の較正状況(calibration plot)を確認しているか。 (9) 解釈性(係数、 特徴量重要度、 SHAP)を報告しているか。 (10) 再現性のため、 seed 固定とパッケージバージョン記録があるか。 この 10 項目をクリアしたら、 はじめてレポートやデプロイに進める。 雑な完成宣言は後で痛い目を見るので、 必ず時間をかけて自己チェックすること。 特に「再現性」については GitHub にコードを push し、 Docker でランタイム環境を固定するところまでが現代のベストプラクティスである。 また、 「モデルの監視」も忘れてはならない: デプロイ後 1 週間、 1 ヶ月、 3 ヶ月の段階でドリフト検知(入力分布の変化、 予測分布の変化)を自動で行う仕組みを整える。 これがないと、 数ヶ月後に予測精度が静かに劣化し、 ビジネスインパクトが大きくなってから気づくことになる。 監視ダッシュボードは初日から組み込むのが鉄則。 さらに、 ステークホルダーへの説明資料も必須である: モデルの長所と短所、 想定外の入力に対する挙動、 倫理的配慮(プライバシー、 公平性)を文書化し、 関係者と共有する。 これらすべての準備が整って、 はじめて「分類モデルの本番運用」を開始できるのである。 最後に強調したいのは、 分類モデルは「作って終わり」ではなく「運用して進化させる」プロダクトだという視点である。 ユーザーフィードバック、 ラベルの誤り訂正、 新しい特徴量の追加、 アルゴリズムの差し替え — これらを継続的に行うことで、 はじめてモデルが「資産」になる。 一度きりの分析プロジェクトと、 継続的に価値を生むサービスでは、 必要な体制も技術もまったく異なる。 自分が今どちらをやっているのかを最初に明確にし、 適切な投資配分を行うこと。 これが分類モデルを成功させる最後のコツである。 とくに重要なのは、 モデルの予測結果を「真実」と混同しないこと。 確率予測は不確実性を含んでおり、 80% の予測が外れることもあれば、 30% の予測が当たることもある。 ステークホルダーに対しては「これは予測モデルの結果であり、 一定の誤差を含む」ことを明示的に伝え、 重要な意思決定では必ず人間の判断とセットで活用するように設計する。 完全自動化を目指すよりも、 「人間 + AI のコラボレーション」を前提に設計する方が、 多くの場合で持続可能な成功につながる。 信頼性、 透明性、 改善可能性を最優先するメンタリティが、 長期的に「使われ続けるモデル」を作るための核心である。 分類モデルは単なるアルゴリズムではなく、 「業務とつながる意思決定支援の仕組み」として育てていく対象なのである。 この視点を最初から持つことで、 単発の実験から脱却し、 組織全体の価値を生む活動へと自然に進化させることができる。 分類は始まりであり、 業務と人を結ぶための土台である、 と覚えておいてほしい。 ここからすべてが広がっていく出発点なのである。

🗺 概念マップ

「分類モデルの基礎」を中心に、 ロジスティック回帰 (前提)・kNN/SVM/決定木 (並列)・アンサンブル (発展)・医療診断/与信 (応用)・回帰問題 (対比)・混同行列/F1 (統合評価) を 6 方向で配置した俯瞰図。

classification basic ロジスティック回帰 kNN / SVM / 決定木 アンサンブル学習 医療診断・与信判定 回帰問題 混同行列・F1

上の概念マップは「分類モデルの基礎」を中心に、 起点(ロジスティック回帰)・対比(kNN/SVM/決定木)・統合(アンサンブル)・応用(医療診断・与信判定・スパム判定)を 4 方向に展開した俯瞰図である。 中央から放射する 4 つのノードを順に追うと、 教師あり学習の中で分類タスクがどう位置づくかを 30 秒で把握できる。

🔗 隣接手法への橋渡し

「分類モデル」は離散ラベルを予測する系で、 上流の特徴量設計と下流の評価指標 (混同行列・F1) を理解しないと、 精度だけ追って実務価値を失う典型例にハマる。

上流の特徴量エンジニアリングで信号を強め、 並列のロジスティック回帰・決定木で線形/非線形を比較し、 下流で混同行列と AUC を確認すれば、 SSDSE 都道府県の「人口減少県」分類のような業務タスクを評価まで通せる。

🌳 手法選択フロー

「分類モデルの基礎(ロジスティック・k-NN・SVM・NB・LDA)」を扱う際の手法選択は、 状況に応じて以下のフローで判断すると迷いが減る。

  1. Step 1: 目的は記述か予測か?
    • 記述 (現状把握・要約) → 集計・可視化・要約統計量で全体像を掴む
    • 予測 (未知データへの推定) → モデル構築・検証フェーズへ移行
  2. Step 2: データの種類・規模は?
    • 数値データ・小〜中規模 → 「分類モデルの基礎(ロジスティック・k-NN・SVM・NB・LDA)」やその拡張手法を直接適用
    • カテゴリ説明変数 → ロジスティック回帰 (logistic-regression) + One-Hot エンコーディングを基本に据える
    • 大規模・高次元 → ランダムフォレスト (random-forest) や勾配ブースティング (xgboost-lib) へ拡張
  3. Step 3: 結果の解釈・共有は?
    • 専門家向け → 数値指標・統計検定で精緻に評価
    • 非専門家向け → 可視化・自然言語での要約を重視

このフローに沿って判断することで、 「分類モデルの基礎(ロジスティック・k-NN・SVM・NB・LDA)」を中核とした適切な手法選択ができる。

📊 図表 (補強)

用語「classification-basic」に関連する代表的な可視化を 3 図示す (公的データ参照)。

📤 実行例(実測) best params: {'clf__C': 1, 'clf__penalty': 'l2'} best F1: 0.6489

実測出力(2023 年度、 5-fold CV): LR Acc=0.720 / kNN Acc=0.636 / SVM(RBF) Acc=0.680 / GaussianNB Acc=0.553 / LDA Acc=0.807。 SSDSE-B は n=47 と極小なので、 fold ごとのばらつきが大きい点に注意(標準誤差は ±0.08 程度)。 この例では LDA が最良で、 解釈性の面でも LR / LDA が使いやすい。 非線形の SVM(RBF) や k-NN は小標本では必ずしも有利にならない点も重要な学びである。

混同行列を見る(LDA の場合)

🎯 このコードでやること: K-分割交差検証で評価。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
1
2
3
4
5
6
7
8
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix, classification_report

pipe = Pipeline([('sc', StandardScaler()),
                 ('clf', LinearDiscriminantAnalysis())])
y_pred = cross_val_predict(pipe, X, y, cv=cv)
print(confusion_matrix(y, y_pred))
print(classification_report(y, y_pred, target_names=['西日本','東日本']))
📤 実行例 [[19 5] [ 4 19]] precision recall f1-score support 西日本 0.83 0.79 0.81 24 東日本 0.79 0.83 0.81 23 accuracy 0.81 47

💬 読み方: LDA の 5-fold CV 予測では東西とも F1=0.81。 誤分類は西→東 5 県・東→西 4 県で、 経済・人口指標だけでは境界付近の県(例: 中部と近畿の境)を完全には分けられない。 分割数 K を増やすほど分散は小さいが計算コスト増。

📤 実行例(実測) [[20 4] [ 6 17]] precision recall f1-score support 西日本 0.77 0.83 0.80 24 東日本 0.81 0.74 0.77 23 accuracy 0.79 47 macro avg 0.79 0.79 0.79 47 weighted avg 0.79 0.79 0.79 47

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

2. statsmodels で「統計的に正しい」ロジスティック回帰

scikit-learn は予測重視で、 標準誤差・p値・信頼区間が出ません。 仮説検定や論文表に必要な指標が欲しい場合は statsmodels.api.Logit を使います。

🎯 このコードでやること: モデルを学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
1
2
3
4
5
6
7
import statsmodels.api as sm
import numpy as np

X_design = sm.add_constant(X)  # 切片列を追加
model = sm.Logit(y, X_design).fit(disp=False)
print(model.summary())          # 係数・SE・z・p値・95%CI が出力
print('Odds ratio:', np.exp(model.params))
📤 実行例 (結果はターミナルに出力されます) 例: 期待される出力は数値・配列形・要約統計です

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

3. scipy.stats で「2群の分類しやすさ」を t 検定で先に確認

🎯 このコードでやること: 「分類タスクの基本」の最小コード。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
1
2
3
4
5
from scipy import stats

for j, name in enumerate(feats):
    t, p = stats.ttest_ind(X[y==1, j], X[y==0, j], equal_var=False)
    print(f'{name:<25s}  t={t:+.2f}  p={p:.4f}')
📤 実行例 (結果はターミナルに出力されます) 例: 期待される出力は数値・配列形・要約統計です

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

4. 確率の校正(CalibratedClassifierCV)

🎯 このコードでやること: モデルを学習。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
1
2
3
4
5
6
7
from sklearn.calibration import CalibratedClassifierCV
from sklearn.svm import SVC

base = SVC(kernel='rbf', C=1.0, gamma='scale')
cal  = CalibratedClassifierCV(base, method='isotonic', cv=5)
cal.fit(X, y)
proba = cal.predict_proba(X)[:, 1]   # 校正済みの確率
📤 このブロックは標準出力には何も出さない

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

5. ROC / PR 曲線で閾値選択

🎯 このコードでやること: 「分類タスクの基本」の最小コード。

📥 入力例 # 入力: 前段の処理結果(DataFrame または ndarray)を前提 # 例: df.shape == (47, 12)、 X.shape == (47, 5)、 y.shape == (47,)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, auc, precision_recall_curve

y_score = cal.predict_proba(X)[:, 1]
fpr, tpr, _ = roc_curve(y, y_score)
prec, rec, _ = precision_recall_curve(y, y_score)

fig, axes = plt.subplots(1, 2, figsize=(11, 4.5))
axes[0].plot(fpr, tpr); axes[0].set_title(f'ROC AUC={auc(fpr,tpr):.3f}')
axes[0].plot([0,1],[0,1],'--',color='gray')
axes[1].plot(rec, prec); axes[1].set_title('Precision-Recall')
for ax in axes:
    ax.set_xlim(0,1); ax.set_ylim(0,1.02); ax.grid(alpha=.3)
plt.tight_layout(); plt.savefig('roc_pr.png', dpi=140)
📤 このブロックは標準出力には何も出さない

💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。

🧭 解説深化 — その分類器、「当てずっぽう」に勝っているか?

本ページでは 5 つのモデルと評価指標を学んだ。 この深化セクションでは、 姉妹ページ(正解率混同行列)ではあまり正面から扱わない 「ベースライン(無情報率)との勝負」「ラベル設計そのものの脆さ」 という 2 つの視点から、 分類という営みを見直す。

💡 直感 — 分類器の実力は「差分」でしか測れない

分類器の Accuracy は絶対値では評価できない。 何も学ばない予測器(ベースライン)が何点取るか が土俵ごとに違うからである。 「常に多数クラスと答える」だけの予測器の正解率を 無情報率(No-Information Rate, NIR) と呼ぶ。 本ページの 2 つの実データタスク(SSDSE-B-2026、 2023 年度・47 都道府県)で NIR は大きく異なる。

タスククラス比NIR(全部多数クラス)土俵の性質
都市(A1101 ≥ 500万)/ 地方9 : 3838/47 = 0.809不均衡 — Acc 0.82 でも「ほぼ当てずっぽう」
東日本 / 西日本23 : 2424/47 = 0.511ほぼ均衡 — LDA の Acc 0.807 は明確な学習の証拠

同じ「Acc ≈ 0.81」でも、 東西分類では NIR 0.511 に対する +0.30 の上積み、 都市/地方分類では NIR 0.809 に対する 上積みほぼゼロ を意味する。 数値が同じでも価値が正反対になる — これが「分類器の実力は差分でしか測れない」という直感の核心である。

⚠️ 落とし穴(重要) — 偶然の一致とラベルの脆さ

① 偶然一致を補正しない Accuracy 比較。 偶然でも当たる分を差し引く指標が Cohen の κ(カッパ) である。 観測一致率 $p_o$ と偶然一致率 $p_e$ から $\kappa = (p_o - p_e)/(1 - p_e)$。 本ページの東西分類・LDA の混同行列(TP=19, TN=19, FP=5, FN=4)で実際に計算すると、 $p_o = 38/47 = 0.809$、 $p_e = 0.500$、 したがって κ = 0.617(Matthews 相関係数 MCC も 0.618、 balanced accuracy は 0.809)。 「Acc 0.81」より「κ 0.62(偶然を除くと約 6 割の一致)」の方が誠実な報告である。 一方、 都市/地方タスクで「常に地方」と答える自明な予測器は Acc 0.809 でも κ = 0、 balanced accuracy = 0.5 となり、 無能さが正しく暴かれる。

② 閾値ラベルの脆さ。 「総人口 500 万以上 = 都市」という二値化は分析者の設計であり、 自然界の真実ではない。 実際の 2023 年度データでは境界付近に 北海道 5,092,000 人・福岡県 5,103,000 人 が並び、 いずれも閾値からわずか 2% 程度の距離にいる(次点の静岡県は 3,555,000 人で大きく離れる)。 もし閾値を 520 万にずらすとこの 2 道県のラベルが反転し、 クラス比は 7:40、 NIR は 40/47 = 0.851 に変わる — モデルを一切変えなくても「解くべき問題」と「合格ライン」が動いてしまう。 連続量を無理に二値化して分類問題に仕立てると、 境界付近の事例が「ラベルノイズ」化する。 元が連続量なら回帰として扱う選択肢を常に検討すべきである。

③ 小標本での「まぐれ勝ち」。 n=47 では 5-fold CV の 1 fold は 9〜10 件しかなく、 1 件の予測が変わるだけで fold の Acc が約 10 ポイント動く。 本文の実測(LDA 0.807 vs GaussianNB 0.553)のような大差は意味を持つが、 0.720 と 0.680 の差(LR vs SVM)を「LR の勝ち」と断定するのは危険である。 乱数シードを変えた反復 CV や、 ラベルをシャッフルして偶然の分布を作る permutation test で差の頑健性を確かめたい。

🚀 発展 — 偶然補正指標の系譜と使い分け

🔗 関連ページ