論文・教科書でよく登場する関連語句のサブインデックス。
🍰 まずはやさしく
データを分けるための道具です。
正解のグループを当てるために使います。
テストの結果で合格か不合格かを分けます。
5つの基本的な分類方法について読みます。
NN/RF が登場する前の古典的分類モデル群。 シンプルで解釈しやすく、 ベースラインや小規模データで未だ強い。
| 手法 | 判定の根拠 | 解釈性 | スケール | 確率出力 |
|---|---|---|---|---|
| ロジスティック回帰 | 線形境界+シグモイド | 高(係数で) | 大規模可 | 自然 |
| k-NN | 近傍 k 個の多数決 | 中 | 推論遅い | 頻度比 |
| SVM | マージン最大の超平面 | 低(カーネル時) | 中規模 | Platt校正 |
| ナイーブベイズ | 条件付き独立仮定 + ベイズ | 中 | 非常に高速 | 自然 |
| LDA / QDA | 各クラスのガウス分布 | 高 | 中規模 | 自然 |
線形結合をシグモイド関数で 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)。 解は最尤推定で求める。 名前は「回帰」だが分類モデル。
🎯 このコードでやること: 分類器を学習。
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]) # 陽性確率 |
💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。
詳細:ロジスティック回帰
「新しい点の近くの $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近傍法
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
ベイズの定理に基づき、 「特徴量が条件付き独立」と仮定して分類:
$$ p(y \mid \boldsymbol{x}) \propto p(y) \prod_j p(x_j \mid y) $$
独立性仮定は非現実的("naive")だが、 実用的にしばしば良い性能。 とくにテキスト分類(スパム判定、 ニュース分類)で標準。
🎯 このコードでやること: モデルを学習。
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)) |
💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。
🍰 まずはやさしく
昔から使われている定番のやり方です。
分析の基準を作るために使います。
スマホのデータなど表形式のデータに便利です。
定義から実装までの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 |
💬 同じ分類問題でも、 データ量・解釈性要求・計算資源で 選ぶべきモデルは変わる。 まずロジスティック回帰でベースラインを作り、 必要に応じて木モデルやアンサンブルに進むのが定石です。
最も基本的な分類タスクは 二値分類 (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 を測る。
📥 入力データ:
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=['地方', '都市'])) |
📤 実行例:
💬 全体精度は 96% で、 都市クラスも precision / recall とも 0.89(誤警報 FP 1 件・見逃し FN 1 件)。 ただし少数クラスはわずか 9 件しかないため、 1 件の誤分類で precision / recall が約 11 ポイントも動く。 不均衡データ (9 vs 38) では「全体精度が高い」だけで判断せず、 少数クラスの recall / precision / F1 を必ず確認する必要があります。
クラスが 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$ は「最も確率が高いクラスを選ぶ」という意味で、 最終予測ラベルになります。 また、 大きなスコア差は指数で 増幅 されるため、 ソフトマックスは「断定的になりやすい」特徴があります。
このコードでやること: SSDSE-B-2026 の都道府県コードから 4 地方ブロックを作り、 人口・経済・教育・消費の特徴量からブロックを多クラス分類。 RandomForest と LogisticRegression を比較する。
📥 入力データ:
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}") |
📤 実行例:
💬 F1-macro は 0.32 (LR) / 0.28 (RF) と 低い値(4 クラスをランダムに当てても 0.25 程度なので、 ほとんど識別できていない)。 人口・経済・消費の連続変数では 地方ブロック をうまく分けられない(=北と南は経済規模が似ている)。 これは特徴量の選択が問題に合っていない典型例。 地理座標(緯度・経度)を入れれば精度は劇的に上がります。 「分類できなかった」も重要な情報 — 「経済規模では地方ブロックを識別できない」と結論できます。
$$\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 (再現率): 「本当に陽性のうち、 何%を見つけられたか」。 見逃しを減らしたい場面(がん検診、 不正検出)で重要。
$F_1$ は両者の調和平均で、 バランス指標。 $F_\beta$ の $\beta$ を 2 にすれば Recall 重視、 0.5 にすれば Precision 重視に調整できます。
このコードでやること: 都市/地方の二値分類で、 閾値を変えながら 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.98 で「ほぼ完璧なモデル」に見えるが、 PR-AUC は 0.87。 不均衡データでは ROC-AUC が楽観的 になることが知られていて、 真の性能は PR-AUC のほうが正しく反映します。 病気・不正検出のような 陽性が稀 な場面では PR-AUC を主指標にしてください。
| シーン | 主指標 | 理由 |
|---|---|---|
| クラスがバランス | Accuracy / F1 | 直感的 |
| 不均衡 + 陽性検出重視 | Recall / PR-AUC | 少数クラスを評価 |
| 誤検出が深刻 | Precision / Specificity | FP を抑制 |
| 医療スクリーニング | Recall (sensitivity) 優先 | 見逃しが致命的 |
| 確率較正が必要 | Brier score / log loss | 確率の質を測る |
| 多クラス + 不均衡 | F1-macro | 全クラスを平等評価 |
分類問題では クラスの数が極端に偏っている(例: 不正取引 0.1%、 病気の人 1%)ことが多く、 標準的な学習では 多数クラスばかり予測 するモデルになります。 対処策は大きく 4 つ。
| 手法 | 仕組み | 利点 | 欠点 |
|---|---|---|---|
| アンダーサンプリング | 多数クラスを削減 | 計算速い | 情報を捨てる |
| オーバーサンプリング (SMOTE) | 少数クラスを合成 | 情報損失なし | 過学習リスク |
| class_weight='balanced' | 損失に重み付け | データを変えない | 確率較正が崩れる |
| 閾値調整 | 0.5 → 0.3 等 | 学習後でも適用可 | どこに置くか難しい |
このコードでやること: 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.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)」「仮定の違い (図2)」「指標の構造 (図3)」がアルゴリズム選択時の三本柱。
「ロジスティック・k-NN・SVM・NB・LDA のどれを使うか」は、 データの特性とビジネス要件で決まる。 闇雲に全部試すのではなく、 以下の 5 ステップフローで段階的に絞り込むのが効率的である。 SSDSE-B-2026 を例にしながら、 各ステップで判断材料となる指標を整理する。
最初に「予測したいか、 解釈したいか、 確率を出したいか」を明確にする。 予測重視 → SVM や決定木ベース、 解釈重視 → ロジスティック回帰や LDA、 確率重視 → ロジスティック回帰や NB が第一候補。 SSDSE-B-2026 で「都道府県を高齢化進行県/未進行県に分類」するなら、 政策議論で 「なぜそう分類されるか」 が求められるので、 解釈性が高いロジスティック回帰や決定木を選ぶ。
サンプル数 n と特徴量数 p の関係で適切なモデルが変わる。 n >> p(大規模・低次元)→ k-NN や SVM(RBF)で非線形を捉える。 n ≈ p(中程度)→ ロジスティック回帰・LDA で過学習を回避。 n << p(高次元・小標本)→ ナイーブベイズ・正則化ロジスティック回帰(Lasso/Ridge)で次元の呪いを回避。 SSDSE-B の 47 サンプル × 数十特徴量は典型的な「n < p または n ≈ p」ケースで、 NB やロジスティック回帰が第一候補となる。
全て数値 → 全モデル適用可。 カテゴリ多数 → 決定木・NB が得意。 スケール感が異なる → ロジスティック・SVM・k-NN は標準化必須、 決定木・NB は不要。 SSDSE-B-2026 は人口(万人単位)、 所得(円単位)、 割合(%)と単位が異なるため、 標準化を前提に SVM やロジスティックを使う。
クラス比 50:50 → そのまま全モデル適用可。 クラス比 90:10 → クラス重み付き SVM・ロジスティック、 または SMOTE などで人工的にバランス調整。 SSDSE-B (2023年度) で「高齢化率 35% 以上の県」を陽性クラスとすると、 47 県のうち陽性は 6 県(約 13%)とかなり不均衡なので、 class_weight='balanced' や閾値調整を併用する。 閾値を「高齢化率が中央値 (約 32%) 以上」に変えれば 50:50 に近づき、 標準モデルをそのまま使える。
ステップ 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 のような結果になる。 標準偏差も併記し、 統計的有意性も評価する。
| 状況 | 第一候補 | 第二候補 | 避けるべき |
|---|---|---|---|
| 解釈重視 | ロジスティック | 決定木 / LDA | SVM(RBF) |
| 予測精度重視 | SVM(RBF) | k-NN | NB (過度に単純) |
| 小標本 (n < 100) | NB | ロジスティック + L2 | 深層学習 |
| 高次元 (p > n) | L1 ロジスティック | NB | k-NN (次元の呪い) |
| 確率出力必須 | ロジスティック | NB | SVM (距離→確率変換が雑) |
この 5 ステップを回せば「とりあえず深層学習」「とりあえずランダムフォレスト」という雑なモデル選択を避けられる。 むしろ 「シンプルなロジスティック回帰で十分な精度が出るなら、 それが最善」 という結論に達することも多い。 オッカムの剃刀(simpler is better)が分類モデル選択の鉄則である。
分類モデルの評価指標は 10 種類以上あり、 用途で使い分ける必要がある。 ここでは主要 7 指標を「正解率系」「ランキング系」「コスト系」の 3 系統で整理する。
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: 全ての閾値で TPR vs FPR を描き、 曲線下面積。 0.5 がランダム、 1.0 が完璧。 PR-AUC: Precision-Recall 曲線下面積。 クラス不均衡に強い(ROC-AUC より過大評価しにくい)。 SSDSE-B 47 県の二値分類で AUC = 0.92 が出たら、 「相当強い分類器」と評価できる。
Log Loss (Cross-Entropy): 確率予測 p に対する -log(p) の平均。 確率の正確さを評価。 ロジスティック回帰や NN の損失関数として使う。 コスト感度行列: FP と FN のコストが異なるとき、 加重して総コストを最小化する。 例: 医療診断で FN(見逃し)のコストが FP(誤陽性)の 10 倍なら、 閾値を下げて Recall を上げる。
| 指標 | 用途 | SSDSE-B での典型値 |
|---|---|---|
| Accuracy | 均衡データの全体感 | 0.85 |
| Precision | FP を減らしたい | 0.80 |
| Recall | FN を減らしたい | 0.75 |
| F1 | P と R の両立 | 0.77 |
| ROC-AUC | 閾値非依存比較 | 0.90 |
| PR-AUC | 不均衡データの比較 | 0.72 |
| Log Loss | 確率予測の正確さ | 0.35 |
論文や報告書では 必ず複数の指標を併記する こと。 Accuracy だけ報告するのは「不誠実」と批判される時代である。 最低でも Precision・Recall・F1・AUC の 4 つを表で示す。 さらにコスト感度が問題なら、 加重総コストも算出する。 これが現代のベストプラクティスである。
2 クラスの点群に対して 1 本の直線(線形決定境界) を自分の手で引いてみましょう。 直線の両側で「赤クラス」「青クラス」に予測が分かれ、 正解率と混同行列がリアルタイム更新 されます。 端点をドラッグ(またはスライダー)で動かし、 どこまで正しく分類できるか体感してください。 分離度スライダー を下げて 2 クラスを重ねると、 どんな直線でも必ず誤分類が残る(=線形分離不可能)ことが分かります。
💡 SVG 上の 2 つの丸ハンドルを直接ドラッグ/タッチしても動かせます。
| 予測1 | 予測0 | |
| 実測1 | – | – |
| 実測0 | – | – |
直感(境界で領域を分ける): 線形分類器がやっているのは 「特徴量空間を直線 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 である確率」を出し、 用途に応じてしきい値を選ぶ(ロジスティック回帰)。 なお線形分離可能性そのものは、 データを高次元へ写像すれば改善しうる、 という考えがカーネル法の出発点です。 分類全体の見取り図は 分類(総論) を参照。
🍰 まずはやさしく
データの分布から分ける方法です。
グループごとの特徴を捉えるために使います。
都道府県のデータなどを分けるときに役立ちます。
線形判別分析などの具体的な仕組みを読みます。
各クラスがガウス分布に従うと仮定し、 ベイズ最適境界を導出:
仮定(多変量正規 + 等分散)が成立すれば最適。 違反でもしばしばロバスト。 PCA と数学的関係が深い。
🎯 このコードでやること: モデルを学習。
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 で対応可 |
k=1。 訓練データの 1 点に完全に従うので、 ノイズまで覚える(高バリアンス)。 k=100 は 100 点の平均で滑らか(高バイアス)。 CV で最適 k を選ぶ。
Multinomial Naive Bayes、 線形 SVM、 ロジスティック回帰(TF-IDF 特徴量 + L1/L2 正則化)。 高次元の単語ベクトルに対して線形モデルが効果的。 現代では BERT/Transformer 系も標準。
「$x_j$ が 1 単位増えると、 ログオッズ $\log(p/(1-p))$ が 1.5 増える」。 オッズ比に変換すれば $e^{1.5} \approx 4.48$。 つまり「$x_j$ が 1 単位増えるとオッズが約 4.5 倍」。
🎯 このコードでやること: SSDSE-B-2026 を読み込み、K-分割交差検証で評価。
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}') |
💬 読み方: 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 に組み込んだ。」
SVM・決定木の確率出力は校正されていない(実際の頻度と乖離)。 Platt scaling(シグモイドフィット)や isotonic regression で校正可能。
🎯 このコードでやること: モデルを学習。
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)) |
💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。
前節の数式に含まれる記号を、 日本語の意味に翻訳する。
classification basic の数式は、 これらの記号を組み合わせて「データから未知量を推定する」あるいは「データの構造を要約する」プロセスを記述している。
SSDSE-B-2026(都道府県別の社会経済データ)を用いて、 各分類モデルを実際に動かすハンズオン例。 目的変数は「東日本=1(北海道・東北・関東・中部の 23 都道県)/西日本=0(近畿以西の 24 府県)」とし、 特徴量は「総人口」「65歳以上人口」「商業地地価」「消費支出」など 6 変数。
🎯 このコードでやること: SSDSE-B-2026 を読み込み、K-分割交差検証で評価。
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}') |
📤 実行例:
💬 読み方: 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 を計算する。
| 予測+ | 予測- | |
|---|---|---|
| 実際+ | TP=40 | FN=10 |
| 実際- | FP=5 | TN=45 |
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}") |
💬 手計算 (Step 2) と Python 出力が完全一致。
| モデル | クラス | 主要パラメータ | 推奨用途 |
|---|---|---|---|
| ロジスティック回帰 | LogisticRegression | C, penalty, solver, class_weight | 解釈性が重要。 ベースライン |
| k-NN | KNeighborsClassifier | n_neighbors, weights, metric | 小〜中規模、 非線形決定境界 |
| 線形SVM | LinearSVC | C, loss | 高次元疎データ(テキスト等) |
| カーネルSVM | SVC | C, kernel, gamma | 非線形・中規模データ |
| ナイーブベイズ | GaussianNB, MultinomialNB | var_smoothing, alpha | テキスト分類、 ベースライン |
| LDA | LinearDiscriminantAnalysis | solver, shrinkage | クラスが正規・等共分散 |
| QDA | QuadraticDiscriminantAnalysis | reg_param | クラスごとに分散が違うとき |
🎯 このコードでやること: K-分割交差検証で評価、分類器を学習。
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_) |
💬 読み方: 分割数 K を増やすほど分散は小さいが計算コスト増。
初学者向けの目安:
実務の多くは正例率が 1〜10% という不均衡データ。 工夫なしに学習すると「全部負例」と予測してしまう。
class_weight='balanced':損失で少数クラスを重く扱う(まずこれ)🎯 このコードでやること: 分類器を学習。
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)) |
💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。
StandardScaler 等で標準化した(k-NN・SVM・ロジスティックは必須)🎯 このコードでやること: 分類器を学習。
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_) |
陽性率が 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 を用いる。
特徴量次元 d が大きくなると、 任意の 2 点間のユークリッド距離が「ほぼ同じ値」に集中し、 「近い」「遠い」の区別が消失する。 これが次元の呪い(curse of dimensionality)で、 k-NN の精度を急激に劣化させる。 d ≥ 20 程度から目に見えて劣化する。 対策は PCA や UMAP による次元削減、 マンハッタン距離 / コサイン距離への切り替え、 そもそも特徴量選択で d を絞ること。 高次元データでは k-NN を諦めて線形 SVM やロジスティック回帰の方が頑健になる。
係数 β は「他の変数を一定にしたときのログオッズの変化」であり、 単位は特徴量のスケールに依存する。 標準化していない係数同士を「大きさ比較」して「変数 A の方が重要」と結論するのは誤り。 比較するなら標準化済み係数(z-スコア化した特徴量での係数)か、 オッズ比 e^β、 あるいは permutation importance を見る。 また、 多重共線性があると個々の β は不安定(分散が膨らむ)ので VIF も合わせて確認する。
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 に切り替える判断も必要。
分類タスクで陥りやすい失敗を 5 つ紹介し、 それぞれのリカバリ手順を示す。 失敗してから学ぶより、 事前に予防する方が遥かに効率的である。
特徴量に「未来情報」や「ターゲット情報」が混入している失敗。 例: 「高齢化進行県」を予測するモデルで、 特徴量に「高齢者割合」を含めてしまう(これは答えに極めて近い情報)。 リカバリ: 特徴量リストを見直し、 ターゲットと因果的に独立な変数のみ使う。 時系列なら必ず時間軸で訓練/テスト分割(ランダム分割禁止)。
陽性が 5% のデータで「全部陰性」と予測しても精度 95%。 一見良いが、 陽性を全く検出できていない(Recall=0)。 リカバリ: class_weight='balanced' を指定、 または SMOTE で陽性を増やす、 または閾値を下げる。
人口(10⁶ スケール)と高齢化率(10⁻¹ スケール)を混在させると、 距離ベースのモデルが人口にのみ反応してしまう。 リカバリ: StandardScaler や MinMaxScaler を Pipeline で組み込む。 これだけで精度が 10〜30% 改善することがある。
小標本で複雑なモデル(深い決定木、 RBF SVM の γ 大)を使うと過学習する。 リカバリ: モデルを単純化(LR + L2 正則化)、 max_depth を制限、 サンプル数を増やす(データ拡張)、 早期停止。
不均衡データで Accuracy 90% を見て満足し、 デプロイ後に「陽性を 1 件も検出しない」と判明する失敗。 リカバリ: 必ず Precision・Recall・F1・AUC を併記。 ビジネス要件(FP・FN のコスト)を反映した指標を選ぶ。
これら 5 つの失敗パターンを意識すれば、 9 割の分類タスクは安全に進められる。 残りの 1 割(時間相関、 分布シフト、 ラベルノイズ)はより高度な対策が必要だが、 まずは基本の 5 つを押さえることが先決である。
ロジスティック回帰・k-NN・SVM・ナイーブベイズ・LDA の 5 モデルを「数学的背景」「計算量」「ハイパーパラメータ」「実装上の注意」の 4 観点で比較する。 同じデータセットでも、 モデルごとに「得意な状況」「失敗しやすい状況」が大きく異なる。
数学的背景: 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 で「県のクラス分類」なら最も標準的な選択肢。
数学的背景: 訓練なし(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 程度なら有効。
数学的背景: マージン最大化、 カーネルトリックで非線形境界。 双対問題で QP(二次計画)を解く。 計算量: 訓練 O(n²) 〜 O(n³)、 大規模データには不向き。 ハイパーパラメータ: C(マージンとマージン違反のトレードオフ)、 kernel(linear, rbf, poly)、 gamma(RBF カーネルの広がり)。 注意: 標準化必須、 GridSearchCV での C/gamma 調整は計算コスト大。 確率出力は probability=True で得られるが、 較正は雑(Platt scaling)。
数学的背景: P(Y|X) ∝ P(X|Y) P(Y) (ベイズの定理)、 特徴量間独立を仮定(「ナイーブ」の由来)。 計算量: 訓練 O(n·p)、 予測 O(p)。 極めて高速。 ハイパーパラメータ: alpha(ラプラス平滑化、 Multinomial NB)、 var_smoothing(Gaussian NB)。 注意: 特徴量独立性は現実には成立しないが、 分類性能はそこそこ高い(テキスト分類の定番)。 小標本でも安定して動く。
数学的背景: クラス内分散最小・クラス間分散最大の線形射影、 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% は対応できる。
分類モデルの性能はハイパーパラメータ (HP) で大きく変わる。 闇雲なグリッドサーチではなく、 「直感的な範囲指定 → ランダムサーチ → ベイズ最適化」 の 3 段階で効率化するのが現代的アプローチである。 SSDSE-B-2026 を例に手順を示す。
まず各 HP に「妥当な範囲」を設定する。 例えばロジスティック回帰の C は対数スケールで [0.001, 1000] が定番。 SVM の C も同じ、 gamma は [0.001, 10] が標準。 k-NN の k は [3, 21] の奇数。 決定木の max_depth は [3, 20]。 この範囲を超えて探索するのは時間の無駄。
グリッドサーチ(全組み合わせ)よりも、 sklearn の RandomizedSearchCV で 50-100 ランダムサンプリングする方が、 同じ計算量で良い HP を見つける確率が高い。 これは Bergstra & Bengio (2012) の有名な論文で示された結果。 50 回の試行で「ほぼ最適」に達することが多い。
本気で最適化したいときは Optuna や Hyperopt でベイズ最適化(TPE アルゴリズム)を使う。 過去の試行結果を確率モデルで学習し、 「次に試すと良い HP」を逐次提案する。 30-50 試行で従来のグリッドサーチ 500 試行と同等以上の精度に到達する。
「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 | 推奨範囲 | 探索方法 |
|---|---|---|---|
| LR | C, penalty | C: log[1e-3,1e3], L1/L2/EN | Randomized 30 |
| k-NN | n_neighbors, weights | k: 3-21 odd | Grid 全列挙 |
| SVM | C, gamma, kernel | C/gamma: log[1e-3,1e3] | Optuna 50 |
| NB | alpha, var_smoothing | alpha: log[1e-3,10] | Randomized 20 |
| LDA | shrinkage, solver | shrinkage: 0-1 or 'auto' | Grid 全列挙 |
HP 調整に時間をかけすぎないこと。 経験則では「総開発時間の 20-30% 以内」が目安。 残りは特徴量エンジニアリング、 データ品質改善、 ドメイン知識の取り込みに使う方がリターンが大きい。 「賢いモデル」よりも「賢い特徴量」 が勝つことが多い。
本ページは主に二値分類を扱ったが、 実務では 3 クラス以上の 多クラス分類 も頻出する。 主要な拡張戦略を整理する。
クラスごとに「そのクラス vs それ以外」の二値分類器を訓練。 K クラスなら K 個のモデル。 ロジスティック回帰、 SVM で標準採用。 サンプル数 n × クラス数 K の計算量。 解釈は容易だが、 クラス不均衡が発生しやすい(各 OvR で「それ以外」が多数派)。
クラス対ごとに二値分類器を訓練。 K クラスなら K(K-1)/2 個のモデル。 SVM で標準(小規模クラスペア)。 各分類器のサンプル数が小さいので計算は速いが、 モデル数が増えて予測時に投票が必要。
直接 K クラスの確率を同時推定。 ロジスティック回帰の多クラス版(multi_class='multinomial')、 NN の出力層 (softmax) に相当。 一つのモデルで K 個の確率を出すので計算効率が良い。
クラスに階層構造があるとき(例: 動物 → 哺乳類/鳥類 → 犬/猫/雀)、 各階層で二値分類器を訓練し連結。 ImageNet などの大規模分類で使われる。
| 戦略 | モデル数 | 典型的な適用先 |
|---|---|---|
| OvR | K | LR, SVM (標準) |
| OvO | K(K-1)/2 | SVM, 少クラス(K<10) |
| Softmax | 1 | NN, Multinomial LR |
| 階層 | 階層数 | ImageNet, 生物分類 |
SSDSE-B-2026 で「県を 5 段階に分類」するなら Softmax が第一候補。 クラス数 K が大きい(K=100 以上)なら、 ヒエラルキカルソフトマックス (Hierarchical Softmax) や Negative Sampling で効率化する。 自然言語処理の単語予測(語彙数 10 万以上)で広く使われる技術である。
分類モデルを体系的に学ぶための 3 ヶ月ロードマップと推奨資料 10 件を提示する。 入門者から中級者への成長を目標にする。
線形回帰との違い、 シグモイド関数、 最尤推定、 オッズ比の解釈、 L1/L2 正則化。 SSDSE-B-2026 で「県のクラス分類」を 5 種類のターゲットで実装。 解釈、 係数の符号、 標準化の効果を確認する。 教科書: Hastie, Tibshirani, Friedman "The Elements of Statistical Learning" 第 4 章。
k-NN, SVM, NB, LDA を順に実装し、 SSDSE-B-2026 で比較。 各モデルの「得意/不得意」を表に整理する。 評価指標を 7 つ全部計算し、 CV で標準偏差まで報告する。 ハイパーパラメータ調整を Optuna でやってみる。
多クラス分類、 クラス不均衡、 オンライン学習、 アンサンブル(Bagging, Boosting)。 XGBoost, LightGBM の使い方も学ぶ。 自分の興味のあるデータセット(Kaggle、 SIGNATE)でコンペに参加する。 この時点で「分類モデルのプロ」と言えるレベルに到達する。
(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 ルールに凝縮する。 (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 方向で配置した俯瞰図。
上の概念マップは「分類モデルの基礎」を中心に、 起点(ロジスティック回帰)・対比(kNN/SVM/決定木)・統合(アンサンブル)・応用(医療診断・与信判定・スパム判定)を 4 方向に展開した俯瞰図である。 中央から放射する 4 つのノードを順に追うと、 教師あり学習の中で分類タスクがどう位置づくかを 30 秒で把握できる。
「分類モデル」は離散ラベルを予測する系で、 上流の特徴量設計と下流の評価指標 (混同行列・F1) を理解しないと、 精度だけ追って実務価値を失う典型例にハマる。
上流の特徴量エンジニアリングで信号を強め、 並列のロジスティック回帰・決定木で線形/非線形を比較し、 下流で混同行列と AUC を確認すれば、 SSDSE 都道府県の「人口減少県」分類のような業務タスクを評価まで通せる。
「分類モデルの基礎(ロジスティック・k-NN・SVM・NB・LDA)」を扱う際の手法選択は、 状況に応じて以下のフローで判断すると迷いが減る。
このフローに沿って判断することで、 「分類モデルの基礎(ロジスティック・k-NN・SVM・NB・LDA)」を中核とした適切な手法選択ができる。
用語「classification-basic」に関連する代表的な可視化を 3 図示す (公的データ参照)。



論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:
実測出力(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 は小標本では必ずしも有利にならない点も重要な学びである。
🎯 このコードでやること: K-分割交差検証で評価。
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=['西日本','東日本'])) |
💬 読み方: LDA の 5-fold CV 予測では東西とも F1=0.81。 誤分類は西→東 5 県・東→西 4 県で、 経済・人口指標だけでは境界付近の県(例: 中部と近畿の境)を完全には分けられない。 分割数 K を増やすほど分散は小さいが計算コスト増。
💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。
scikit-learn は予測重視で、 標準誤差・p値・信頼区間が出ません。 仮説検定や論文表に必要な指標が欲しい場合は statsmodels.api.Logit を使います。
🎯 このコードでやること: モデルを学習。
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)) |
💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。
🎯 このコードでやること: 「分類タスクの基本」の最小コード。
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}') |
💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。
🎯 このコードでやること: モデルを学習。
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] # 校正済みの確率 |
💬 読み方: 「分類タスクの基本」の典型パターン。 列名や引数を変えると応用可能。
🎯 このコードでやること: 「分類タスクの基本」の最小コード。
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 : 38 | 38/47 = 0.809 | 不均衡 — Acc 0.82 でも「ほぼ当てずっぽう」 |
| 東日本 / 西日本 | 23 : 24 | 24/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 で差の頑健性を確かめたい。
balanced_accuracy_score、 κ は cohen_kappa_score、 MCC は matthews_corrcoef で 1 行で出せる。