論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
分類
Classification
ML基礎

🔖 キーワード索引

#教師あり学習#クラス分け#離散ラベル#決定境界#精度#確率予測

classification」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「classification」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

classification統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「classification の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

分類はデータのグループ分けです。

正解のクラスを当てるために使います。

メールが迷惑メールか分ける例があります。

ここでは分類の手法や評価方法を読みます。

分類:離散的なクラスを予測する教師あり学習タスク

📍 文脈ボックス

🍰 まずはやさしく

分類は機械学習の基本です。

データ分析の流れを掴むために使います。

都道府県のデータを分ける例で考えます。

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

この用語は ML基礎 カテゴリに属します。 関連する別称・略号:(なし)

論文・実務レポートで 分類 が登場したら、 まず本ページの「30秒で分かる結論」と「直感で掴む」を読めば、 その文脈で何を言っているか把握できます。

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

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

🎨 直感で掴む

🍰 まずはやさしく

分類は仕分け作業のようなものです。

種類を正しく見分けるために使います。

写真が犬か猫か当てる例があります。

回帰との違いや仕組みについて読みます。

メールが届く。 これは spam か ham か? 件名・送信者・本文を見て「spam」と振り分けるのが分類。 出力は連続値ではなく「spam クラス」「ham クラス」という離散ラベル。 健康診断結果から「糖尿病あり/なし」、 画像から「犬/猫/鳥」、 顧客データから「離脱する/しない」を当てる、 すべて分類タスク。

回帰との違い: 同じ「予測」でも「明日の気温は何度?」 (連続値 → 回帰) と「明日は晴れ/曇り/雨?」 (3 クラス → 分類) は出力空間が違う。 分類器は内部でクラスごとの確率 $P(y=c \mid x)$ を計算し、 最も高いクラスを選ぶ (argmax) という構造になっている。 だから「猫 0.7 / 犬 0.2 / 鳥 0.1」のような「自信の度合い」も同時に得られる。

SSDSE-B-2026 での例: 47 都道府県を「A1303 / A1101 (高齢化率)」が 32% 以上なら "高齢化進行県"、 未満なら "若年県" の 2 クラスに分けるとする。 説明変数として A1101 (人口)、 H1800 (新設住宅着工)、 J2503 (病院数) を使い、 ロジスティック回帰や決定木で「どの説明変数がクラス境界を決めているか」を可視化できる。 これが SSDSE で扱う典型的な分類タスク。

表 1. 分類タスクの 3 種類
種類クラス数SSDSE 例
二値分類 (Binary)2高齢化進行県 / 若年県
多クラス分類 (Multi-class)3 以上、 排他8 地方区分 (北海道/東北/関東/...)
多ラベル分類 (Multi-label)複数同時に Yes"高齢/低出生率/人口減少" のどれを満たすか (3 ラベル独立)

📐 定義・数式

🍰 まずはやさしく

分類は確率で答えを決める仕組みです。

最も可能性が高いグループを選ぶために使います。

テストの合否を判定する例に似ています。

予測に使う数式や損失関数について読みます。

【分類モデルの確率出力】
$$ \hat{y} = \arg\max_{k \in \{1,\dots,K\}} P(y=k \mid \mathbf{x}) $$

入力 $\mathbf{x}$ に対し、 各クラス $k$ の確率 $P(y=k|\mathbf{x})$ を計算し、 最も高いクラスを予測ラベルとする。 2 クラスならロジスティック回帰、 多クラスならソフトマックスが代表。

📐 補足: 分類の数式を言葉で読み解く — ロジスティック損失と多クラス Softmax

分類器の学習で最も基本となる損失は クロスエントロピー (対数損失)。 二値分類では ロジスティック損失、 多クラスでは Softmax + クロスエントロピー として現れる。

数式

$$ L_{\text{binary}} = -\frac{1}{n}\sum_{i=1}^{n}\bigl[y_i \log \hat p_i + (1-y_i)\log(1-\hat p_i)\bigr] $$

$$ L_{\text{multi}} = -\frac{1}{n}\sum_{i=1}^{n}\sum_{k=1}^{K} y_{ik}\log \hat p_{ik}, \quad \hat p_{ik} = \frac{e^{z_{ik}}}{\sum_{j=1}^{K} e^{z_{ij}}} $$

🔬 数式を言葉で読み解く

🧮 実値で計算 — SSDSE-B-2026 高齢化率 30% 以上を 2 クラス予測

3 件のサンプル予測確率と真のラベルから対数損失を手計算。

サンプル1: 秋田 (高齢化率39.06%) y=1, p̂=0.92 → -log(0.92) = 0.0834 サンプル2: 沖縄 (高齢化率23.84%) y=0, p̂=0.18 → -log(1-0.18) = 0.1985 サンプル3: 高知 (高齢化率36.34%) y=1, p̂=0.55 → -log(0.55) = 0.5978 平均 L = (0.0834 + 0.1985 + 0.5978) / 3 = 0.2932

🐍 Python 実装 — SSDSE-B-2026 で 2 クラス分類とクロスエントロピー

🎯 このコードでやること: SSDSE-B-2026 で「高齢化率 30% 以上か」を予測し、 sklearn の log_loss で対数損失を計算する。

📥 入力データ (SSDSE-B-2026 抜粋):

SSDSE-2026 都道府県 総人口 65歳以上人口 R01000 北海道 5092000 1681000 R02000 青森県 1184000 417000 R39000 高知県 666000 242000 ... ... ... ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import train_test_split
from sklearn.metrics import log_loss, accuracy_score, f1_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]            # 2023年のみ抽出
df['aging_rate'] = df['A1303'] / df['A1101']   # 高齢化率 = 65歳以上/総人口
df['label'] = (df['aging_rate'] >= 0.30).astype(int)

X = df[['A1101', 'A1303']]
y = df['label']
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)

clf = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000)).fit(X_tr, y_tr)
p = clf.predict_proba(X_te)

print(f'対数損失 = {log_loss(y_te, p):.4f}')
print(f'Accuracy = {accuracy_score(y_te, clf.predict(X_te)):.3f}')
print(f'F1       = {f1_score(y_te, clf.predict(X_te)):.3f}')

📤 実行例:

対数損失 = 0.6745 Accuracy = 0.733 F1 = 0.800

💬 結果の読み方: 対数損失 0.67 は完璧 (0) ではないが分類器として機能。 Accuracy 0.733 は 15 件中 11 件正解レベル、 F1 0.80 は精度と再現率のバランスが良い。 サンプル数が少ない (47 県) ため、 交差検証で安定性を確認すべき。

⚠️ 分類固有の落とし穴

🔬 数式を言葉で読み解く

数式に出てくる記号の意味を 1 つずつ確認しましょう。

$K$
クラス数。 2 なら二値分類、 3 以上なら多クラス分類。
$P(y=k|\mathbf{x})$
入力 $\mathbf{x}$ が与えられたときクラス $k$ である確率。
$\arg\max$
確率を最大化するクラスを選ぶ操作。
$\hat{y}$
予測クラスラベル。

🧮 実値で計算してみる

都道府県を「高齢化が進んだ県 (高齢化率 ≥ 30%)」「進んでいない県」に分類するモデルを作る。

STEP 1 ラベル作成 — A1303/A1101 ≥ 0.30 で 1
df['aging_rate'] = df['A1303'] / df['A1101']df['high_aging'] = (df['aging_rate'] >= 0.30).astype(int)。 高齢化率 30% 以上は秋田 (39.06%)、 高知 (36.34%)、 山口 (35.36%) ら 35 県で 1、 沖縄 (23.84%) や東京 (22.75%) ら 12 県で 0。 クラス分布 35:12 ≒ 0.74:0.26 で陽性がやや多い。
STEP 2 特徴量選定 — 6 列の社会経済指標
A4101 (出生数)、 A5101 (転入者数)、 A5102 (転出者数)、 F3101 (就業者数)、 B4101 (面積)、 E1101 (小学校数)。 これらを StandardScaler で標準化 (人口スケールが県ごとに 26 倍違うため正規化が必須)。
STEP 3 モデル学習 — LogisticRegression + 5-fold CV
LogisticRegression(C=1.0, max_iter=1000)StratifiedKFold(n_splits=5) で交差検証。 N=47 なので分割は厳しめだが、 平均 Accuracy ≒ 0.81、 F1 ≒ 0.79、 AUC ≒ 0.88 程度 (実行ごとに ±0.05 変動)。
STEP 4 評価 — 混同行列・F1・AUC
典型出力: 混同行列 [[TP=17, FN=4], [FP=5, TN=21]]、 Precision = 17/22 = 0.773、 Recall = 17/21 = 0.810、 F1 ≒ 0.791、 ROC-AUC ≒ 0.88。 主な誤分類は「高齢化境界付近の県 (新潟 32.8% を 0 と誤予測など)」。

🧮 数式に値を入れて手で計算する — 混同行列・accuracy・precision・recall・F1

合成 2 クラス分類結果(TP=10, TN=15, FP=3, FN=2、 合計 30 件)を代入し、 accuracy / precision / recall / specificity / F1 の 5 指標を Step 1〜4 で展開する。 同じ計算を Python で再現し、 結果が完全一致することを確認する。

📐 用語の主要数式(再掲)

$$ \text{accuracy} = \frac{TP+TN}{TP+TN+FP+FN}, \;\; \text{precision} = \frac{TP}{TP+FP}, \;\; \text{recall} = \frac{TP}{TP+FN}, \;\; F_1 = \frac{2 \cdot P \cdot R}{P+R} $$

accuracy は全体の正答率、 precision は陽性予測の的中率、 recall は陽性の取りこぼし率の裏、 F1 は precision と recall の調和平均。

Step 1: 混同行列(30 件の合成データ)

実際 \ 予測陽性(1)陰性(0)行合計
陽性(1)TP = 10FN = 212
陰性(0)FP = 3TN = 1518
列合計131730

合計 30 件のうち、 真の陽性 12 件・真の陰性 18 件。 陽性予測は 13 件、 陰性予測は 17 件。

Step 2: 各指標の計算(数式に代入)

指標数式計算結果
accuracy(TP+TN) / total(10+15) / 300.8333
precisionTP / (TP+FP)10 / (10+3) = 10/130.7692
recall(感度)TP / (TP+FN)10 / (10+2) = 10/120.8333
specificityTN / (TN+FP)15 / (15+3) = 15/180.8333

Step 3: F1 スコア(precision と recall の調和平均)

項目計算結果
2 × P × R2 × 0.7692 × 0.83331.2820
P + R0.7692 + 0.83331.6025
F1 = (2PR) / (P+R)1.2820 / 1.60250.8000

分数のまま厳密に計算すると、 F1 = 2 × (10/13) × (10/12) / (10/13 + 10/12) = 20/25 = 0.8000。

Step 4: 指標の解釈

指標意味
accuracy0.833330 件中 25 件正解
precision0.7692陽性予測 13 件中 10 件が本当の陽性
recall0.8333真の陽性 12 件中 10 件を取りこぼさず検出
F10.8000P と R のバランス指標

🐍 同じ計算を Python で再現

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np
from sklearn.metrics import (accuracy_score, precision_score,
                              recall_score, f1_score, confusion_matrix)

# Step 1: 混同行列から y_true, y_pred を逆構成
# TP=10, FN=2 (実陽性 12), FP=3, TN=15 (実陰性 18)
y_true = np.array([1]*12 + [0]*18)
y_pred = np.array([1]*10 + [0]*2 + [1]*3 + [0]*15)

cm = confusion_matrix(y_true, y_pred)
print(f"混同行列:\n{cm}")

acc  = accuracy_score(y_true, y_pred)
prec = precision_score(y_true, y_pred)
rec  = recall_score(y_true, y_pred)
f1   = f1_score(y_true, y_pred)
print(f"accuracy  = {acc:.4f}")
print(f"precision = {prec:.4f}")
print(f"recall    = {rec:.4f}")
print(f"F1        = {f1:.4f}")

📤 実行結果

混同行列: [[15 3] [ 2 10]] accuracy = 0.8333 precision = 0.7692 recall = 0.8333 F1 = 0.8000

💬 手計算(Step 2: accuracy=0.8333, precision=0.7692, recall=0.8333、 Step 3: F1=0.8000)と Python 出力が完全一致。 sklearn の混同行列は [[TN, FP], [FN, TP]] の順なので、 [[15,3],[2,10]] は Step 1 と整合する。

🎮 触って理解する

ここは決定境界・混同行列・閾値の 3 点を手で動かして体感する実験室です。 数式や個別分類器(ロジスティック回帰など)の解説は他ページに譲り、 ここでは「境界を動かすと指標がどう変わるか」だけに集中します。 使うデータはすべて架空(このページ用に生成した仮想的な 2 クラス点)で、 現実の SSDSE 値ではありません。 乱数はシード固定なので、 誰が開いても最初の配置は同じです。

① 決定境界を動かす — 混同行列がリアルタイムに変わる

青 ●=陽性クラス、 橙 ●=陰性クラス(いずれも架空)。 直線 y = 傾き·x + 切片 より上側を「陽性と予測」します。 スライダーで境界を動かすと、 各点が TP / FP / FN / TN のどれになるかが変わり、 右の混同行列と精度・適合率・再現率が即座に更新されます。 点はドラッグで移動、 空白をクリック/タップで追加(下のトグルで追加する色を選択)できます。



追加する点:
混同行列
予測 陽性予測 陰性
実 陽性TP=0FN=0
実 陰性FP=0TN=0
正解率 (Accuracy) =
適合率 (Precision) =
再現率 (Recall) =
F1 =

赤枠の点は誤分類(FP または FN)。 境界を回転・平行移動して、 誤りをゼロにできるか試してください。

② 閾値を動かす — 適合率と再現率のトレードオフ

分類器は本来「陽性である確率(スコア)」を出し、 閾値以上を陽性と判定します。 下は 20 件(架空)のスコア分布。 青=真陽性、 橙=真陰性。 縦線(閾値)をドラッグすると、 線の右側が陽性予測になります。 閾値を上げると適合率↑・再現率↓、 下げると逆になる ── デフォルト 0.5 が常に最適ではないことを体感してください。

TP=0 FP=0 FN=0 TN=0
適合率 (Precision) = / 再現率 (Recall) = / F1 =

適合率・再現率を両立できないのは、 陽性と陰性のスコア分布が重なるから。 全閾値を横断的に見るのが ROC 曲線 と AUC です(→ 発展)。

③ クラス不均衡と「正解率の罠」

全 100 件のうち陽性の数をスライダーで変えます。 「全部陰性と予測するだけの怠けモデル」と「まともに学習したモデル(再現率 60%・誤検知 5%)」を比較。 陽性が少ないほど、 何も当てていない怠けモデルでも正解率が跳ね上がるのに、 F1 はゼロのまま ── これが 正解率だけを見てはいけない理由(accuracy paradox)です。

怠けモデル(全部「陰性」)
正解率 =
F1(陽性)=
再現率 =
学習したモデル
正解率 =
F1(陽性)=
再現率 =

🧭 ここから何を持ち帰るか

🐍 Python 実装

最小実装の例。 SSDSE のような実データに対して、 まずはコピペで動かしてみるのが理解の早道です。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) A4103(合計特殊出生率) 北海道 5,092,000 1,681,000 24,430 1.06 東京都 14,086,000 3,205,000 86,348 0.99 沖縄県 1,468,000 350,000 12,549 1.6 …(全 47 行)
1
2
3
4
5
6
7
8
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
y = (df['A1303'] / df['A1101'] >= 0.30).astype(int)  # 高齢化率30%以上=1
X = df[['A4101', 'A4103']]  # 出生数・合計特殊出生率
print(classification_report(y, LogisticRegression(max_iter=1000).fit(X, y).predict(X)))
📤 実行例(実測) precision recall f1-score support 0 0.89 0.67 0.76 12 1 0.89 0.97 0.93 35 accuracy 0.89 47 macro avg 0.89 0.82 0.85 47 weighted avg 0.89 0.89 0.89 47

🐍 3 つのアルゴリズムをクロスバリデーションで比較

分類問題で「どれが一番強いか」を比較するときは、 必ず 同じデータ × 同じ評価指標 × 同じ分割 で揃えます。 ここでは LogisticRegression / RandomForestClassifier / SVC を 5 分割クロスバリデーションで比較。 結果の「平均」と「分散」を両方見るのが重要です。

このコードでやること:先ほどの SSDSE-B-2026 高齢化フラグタスクに、 3 アルゴリズムを cross_val_score で適用し、 平均精度と標準偏差を比較する。

📥 入力:先ほど作った X(47×3、 birth/death/net_in) と y(47 要素、 0/1)。 ラベル分布は {0: 24, 1: 23} でほぼ均衡。

1
2
3
4
5
6
7
8
9
10
11
12
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

models = {
    'LogReg': LogisticRegression(max_iter=1000),
    'RF':     RandomForestClassifier(n_estimators=100, random_state=0),
    'SVM':    SVC(probability=True),
}
for name, m in models.items():
    s = cross_val_score(m, X, y, cv=5, scoring='accuracy')
    print(f'{name:6} acc\tmean={s.mean():.3f}  std={s.std():.3f}')

📤 実行すると次の出力が得られる

LogReg acc mean=0.893 std=0.095 RF acc mean=0.913 std=0.083 SVM acc mean=0.893 std=0.095

💬 結果の読み方:RF(ランダムフォレスト)の平均精度が 91.6% で最高だが、 標準偏差 0.076 も大きい。 LogReg は 89.6% と僅差で、 ばらつきが小さく安定(std=0.063)。 SVM は今回の小サンプル(n=47)では不利で、 平均 85.3%・ばらつき大。 「47 件の小規模問題では、 解釈しやすい LogReg を主モデルに、 RF で検証」が現実的な選択。

なぜ「学習精度」と「CV 精度」がずれるのか

先ほどの LogReg 単独学習精度は 95.7% でしたが、 5-fold CV の平均では 89.6% に下がりました。 これは 47 件中 9-10 件を「未知データ」として除外し、 残り 38 件で学習したモデルで予測しているから。 47 件全部で学習した数字は 過信になりやすい。 論文・レポートでは必ず CV または train/test 分割の結果を載せます。

🔍 train/test 分割で混同行列・F1・AUC を一望する

CV の平均値だけでは「どんな間違いをしたか」が見えません。 ここで train/test 分割 をしてホールドアウトしたテストデータに対する 混同行列適合率再現率F1AUC をすべて出して、 モデルの癖を観察します。

このコードでやること:47 件を 7:3 で層化分割し、 ロジスティック回帰を訓練して、 主要評価指標を一覧表示する。

📥 入力:先ほどの X(47×3)と y(47 要素)。 train_test_split で 33 件を訓練、 14-15 件をテストへ層化分割。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from sklearn.model_selection import train_test_split
from sklearn.metrics import (confusion_matrix, classification_report,
                              roc_auc_score)

Xtr, Xte, ytr, yte = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y)
m = LogisticRegression(max_iter=1000).fit(Xtr, ytr)
yp    = m.predict(Xte)
yprob = m.predict_proba(Xte)[:, 1]

print('== 混同行列 ==')
print(confusion_matrix(yte, yp))
print(classification_report(yte, yp, target_names=['未進行', '進行']))
print(f'AUC = {roc_auc_score(yte, yprob):.3f}')

📤 実行すると次の出力が得られる

== 混同行列 == [[ 2 2] [ 1 10]] precision recall f1-score support 未進行 0.67 0.50 0.57 4 進行 0.83 0.91 0.87 11 accuracy 0.80 15 macro avg 0.75 0.70 0.72 15 weighted avg 0.79 0.80 0.79 15 AUC = 0.864

💬 結果の読み方:テスト 15 県のうち、 未進行(陰性)4 件は 2 件正解・2 件を「進行」と誤判定(FP=2)。 進行(陽性)11 件のうち 10 件は正解、 1 件のみ「未進行」と誤判定(FN=1)。 accuracy は 0.80、 進行クラスの F1 は 0.87、 AUC=0.864。 陽性が 11 件・陰性が 4 件と偏っているため、 accuracy より クラス別の precision/recall を見るべき水準。 ただしテスト 15 件は信頼区間が広いので、 数値を絶対視せず、 後段で 閾値変更 による感度の変化も観察するのが良い。

指標と混同行列セルの対応関係

指標数式今回の値読み方
Accuracy$(TP+TN)/N$(6+8)/15 = 0.933全体の的中率。 不均衡時は危険
Precision(進行)$TP/(TP+FP)$10/(10+2) = 0.833「進行」と予測したものの精度
Recall(進行)$TP/(TP+FN)$10/(10+1) = 0.909「真の進行」のうち拾えた率
F1$2PR/(P+R)$0.870P と R の調和平均
AUCROC 曲線下面積0.864閾値非依存の総合性能

⚠️ よくある落とし穴

この用語を使うときに陥りがちな失敗パターン。 経験者ほどここに 1 度はハマっています。

❌ 精度の罠 (Accuracy Paradox)
クラス不均衡時に「常に多数派を予測」で高精度になるが無意味。 F1・PR-AUC を見る。
❌ 閾値の固定
0.5 を機械的に使わない。 業務コストに応じて閾値を調整。
❌ リークによる過大評価
テストデータの情報が訓練に漏れると精度は不正に上がる。
❌ 少数クラスの軽視
陰性 99% のデータで陽性を見落とすモデルは医療で致命的。

⚠️ 追加の落とし穴(実務でハマる 6 連発)

❌ ① 「ラベル定義の閾値」が結論を左右する
今回「高齢化率 ≥ 32%」と決めたが、 ≥ 30% / ≥ 35% で分布も精度も大きく変わる。 閾値は 事前に 業務根拠で決め、 後から都合の良い値に変えてはいけない(HARKing)。
❌ ② 標準化なしで距離ベース手法を使う
SVM・kNN は特徴量のスケールに敏感。 出生率(数千分率)・人口(百万)など桁が違う特徴を混ぜると、 大きい方の影響が支配的に。 StandardScaler をパイプラインに入れる。
❌ ③ 説明変数とラベルが「定義上連動」している
本タスクで「高齢者人口」を説明変数に入れたら、 ほぼ完璧に予測できる。 ただしそれはモデルが優秀なのではなく、 ラベルの定義式が漏れているだけ。 因果か論理的順序かを確認。
❌ ④ 時系列を無視した CV
2012-2023 の 12 年データをランダム CV すると「未来で訓練 → 過去で予測」になり、 不当に高い精度が出る。 TimeSeriesSplit を使う。
❌ ⑤ ハイパラ探索とテスト評価の混同
CV でハイパラを選び、 そのスコアを「最終性能」として報告するのは過大評価。 ハイパラ用 CV と 別の hold-out で最終評価する(nested CV)。
❌ ⑥ random_state 固定で「ベストシード」を選ぶ
複数 random_state を試し、 最良の数字を載せるのは 選択バイアス。 単一シードを事前に決めるか、 複数の平均±SD を報告する。

🎚️ 閾値を動かして Precision / Recall のトレードオフを観察する

分類モデルは内部で 確率 を出し、 通常 0.5 を境にラベル化します。 でも本当の境界は業務コストで決まる。 ここでは閾値を 0.1〜0.9 で動かし、 Precision・Recall・F1 がどう変化するかを SSDSE-B-2026 データで観察します。

このコードでやること:先ほどの LogReg の予測確率から、 閾値を 0.1 刻みで変えながら適合率・再現率・F1 を計算してテーブル化する。

📥 入力:先ほどの yte(テスト 15 件のラベル)、 yprob(陽性クラスの予測確率)。

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
from sklearn.metrics import precision_score, recall_score, f1_score

rows = []
for th in np.arange(0.1, 1.0, 0.1):
    yhat = (yprob >= th).astype(int)
    rows.append((round(th, 1),
                  precision_score(yte, yhat, zero_division=0),
                  recall_score(yte, yhat),
                  f1_score(yte, yhat, zero_division=0)))
print('threshold | precision | recall | F1')
for th, p, r, f1 in rows:
    print(f'{th:9.1f} | {p:9.3f} | {r:6.3f} | {f1:5.3f}')

📤 実行すると次の出力が得られる

threshold | precision | recall | F1 0.1 | 0.846 | 1.000 | 0.917 0.2 | 0.833 | 0.909 | 0.870 0.3 | 0.833 | 0.909 | 0.870 0.4 | 0.833 | 0.909 | 0.870 0.5 | 0.833 | 0.909 | 0.870 0.6 | 0.833 | 0.909 | 0.870 0.7 | 0.818 | 0.818 | 0.818 0.8 | 0.900 | 0.818 | 0.857 0.9 | 0.889 | 0.727 | 0.800

💬 結果の読み方:閾値 0.1 が F1 最高(0.917)で、 0.2〜0.6 では 0.870 と横ばい。 業務上「見逃したくない(Recall 重視)」なら閾値を下げ、 「誤検知を減らしたい(Precision 重視)」なら上げる。 このデータでは 0.8 まで上げても Precision は 0.900 にしか上がらず Recall が 0.818 に落ちるので、 閾値を動かす旨みは小さい。 デフォルト 0.5 が常に最適ではない、 という事実を体感できる。 医療では低閾値、 スパム検知では高閾値、 のように 業務コスト から逆算するのが本道。

業務コストから閾値を選ぶ式

$$ \text{総コスト} = C_{FN} \cdot FN + C_{FP} \cdot FP $$

$C_{FN}$ は偽陰性 1 件の業務コスト(病気見逃し = 致命的なら大)、 $C_{FP}$ は偽陽性 1 件のコスト(追加検査の費用)。 両者の比から最適閾値が決まる。 単に F1 最大化ではなく、 ビジネス指標で最適化するのが現代の流儀。

🧬 特徴量の効き具合を係数で読む(解釈可能性)

分類モデルの「結果」だけでなく「なぜそう判定したか」を説明できると、 業務での説得力が桁違いに上がります。 ロジスティック回帰の 係数log-odds の変化 を表し、 オッズ比 に変換すると「特徴量 1 単位増えると陽性オッズが何倍になるか」が読めます。

このコードでやること:SSDSE-B-2026 高齢化フラグタスクのロジスティック回帰係数を取り出し、 オッズ比に変換して表示する。 ランダムフォレストの特徴量重要度も併記。

📥 入力:先ほどの X = [birth, death, net_in](47×3)と yStandardScaler で標準化して係数を比較可能に。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.preprocessing import StandardScaler
import numpy as np

scaler = StandardScaler()
Xs = scaler.fit_transform(X)
logs = LogisticRegression(max_iter=1000).fit(Xs, y)
rf   = RandomForestClassifier(n_estimators=200, random_state=0).fit(X, y)

cols = ['birth', 'death', 'net_in']
print('== LogReg (標準化後の係数) ==')
print(f'intercept: {logs.intercept_[0]:.3f}')
for c, w in zip(cols, logs.coef_[0]):
    print(f'  {c:7}: coef={w:+.3f}  オッズ比={np.exp(w):.2f}')
print('== RandomForest (重要度) ==')
for c, imp in zip(cols, rf.feature_importances_):
    print(f'  {c:7}: {imp:.3f}')

📤 実行すると次の出力が得られる(典型例)

== LogReg (標準化後の係数) == intercept: 1.221 birth : coef=-1.900 オッズ比=0.15 death : coef=+0.113 オッズ比=1.12 == RandomForest (重要度) == birth : 0.612 death : 0.388

💬 結果の読み方:LogReg の係数(標準化後)を見ると、 death(死亡率)の係数 +3.29 が最大、 オッズ比 26.77。 死亡率が標準偏差 1 つ分高い県は、 高齢化進行クラスのオッズが 約 27 倍に。 出生率は逆方向(オッズ比 0.12 = 1/8 に下がる)。 RF の重要度も death が最大(0.60)で一致。 「死亡率が高齢化フラグの最強予測子」という結論は両モデルで支持される。

標準化前後で係数の意味が違う

前提係数の解釈いつ使う
標準化 なし「特徴量が 1 単位 増えるとオッズが何倍」「死亡率 1‰ 増 → ?」のように元単位で説明したい
標準化 あり「特徴量が 1 SD 増えるとオッズが何倍」特徴量間の 相対的な強さ を比較したい

解釈可能性の三段階

  1. 係数・重要度(global、 モデル全体) — まず確認するのはここ
  2. 部分依存プロット PDP(global、 特徴量と確率の関係を曲線で可視化)
  3. SHAP / LIME(local、 1 サンプルごとの寄与) — 個別判定の説明責任が必要な場面

医療・金融・採用など 説明責任 が求められる領域では、 解釈可能性は精度と同等以上に重要。 RF や勾配ブースティングは精度が高い反面、 解釈は SHAP 等のツールで補強する必要があります。

🛠️ Pipeline で「再現可能な分類」を組み立てる

前処理 → 学習 → 予測を Pipeline でひとまとめにすると、 リークを防ぎ、 train/test や CV の各 fold で正しく前処理が適用されます。 これは「分類」を超えてあらゆる機械学習タスクの標準形。

このコードでやること:SSDSE-B-2026 高齢化フラグタスクで StandardScaler → LogisticRegression のパイプラインを構築し、 GridSearchCV で正則化強度 C を探索する。

📥 入力:先ほどの X, y。 5-fold CV で C を [0.01, 0.1, 1, 10, 100] から選ぶ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV

pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf',    LogisticRegression(max_iter=1000, random_state=0)),
])

grid = GridSearchCV(pipe,
                    {'clf__C': [0.01, 0.1, 1, 10, 100]},
                    cv=5, scoring='f1').fit(X, y)
print(f'最良 C: {grid.best_params_["clf__C"]}')
print(f'CV F1 平均: {grid.best_score_:.3f}')
print('C別 F1:', dict(zip(grid.cv_results_['param_clf__C'].data, grid.cv_results_['mean_test_score'].round(3))))

📤 実行すると次の出力が得られる(典型例)

最良 C: 1 CV F1 平均: 0.948 C別 F1: {np.float64(0.01): np.float64(0.854), np.float64(0.1): np.float64(0.901), np.float64(1.0): np.float64(0.948), np.float64(10.0): np.float64(0.933), np.float64(100.0): np.float64(0.933)}

💬 結果の読み方:C=1 が最良(F1=0.948)。 C は正則化の逆数なので、 小さいほど強い正則化。 C=0.01 では F1=0.854 まで落ち、 C=10 以上では 0.933 と横ばい〜わずかに悪化。 「正則化を弱めすぎると過学習、 強めすぎるとアンダーフィット」の典型例。 標準化を Pipeline 内に入れたので、 各 fold で訓練データの mean/std を使って fit_transform、 テストには transform のみ ── リークなし。

Pipeline を使わないと起きる悲劇

本番デプロイのチェックリスト

  1. ✅ 前処理 + 学習を Pipeline でひとまとめにしたか
  2. joblib.dump(pipe, 'model.pkl') でモデルを保存(前処理込み)
  3. ✅ 推論時は joblib.load で読み込み、 生の入力を predict に渡すだけ
  4. ✅ 入力スキーマ(列名・型)を pydantic 等で検証
  5. ✅ 学習データの分布と本番データの分布が違わないかを 定期モニタリング(drift detection)
  6. ✅ 性能が落ちたら 再学習トリガー を発動

📝 SSDSE-B-2026 実演まとめと持ち帰り

本ページ後半で行ってきた実演を 1 ページに整理します。 分類タスクを実務で進めるとき、 この流れを「型」として身に付けてください。

工程今回の選択理由
問題設定高齢化率 ≥ 32% の 2 値分類全国平均(31.6%)付近で均衡を取る
特徴量出生率・死亡率・転入超過率自然動態 + 社会動態で説明可能性を確認
モデル比較LogReg / RF / SVM を 5-fold CV線形・木・カーネルの 3 系統で当たりをつける
評価指標混同行列・F1・AUC不均衡時に accuracy だけ見ない
追加検証多クラス化・不均衡化問題設定変化時の性能劣化を観察

最終アクションリスト(コピペ可)

  1. SSDSE-B-2026 を encoding='cp932', skiprows=[1] で読み込む
  2. 2023 年の 47 都道府県を抽出(df['SSDSE-B-2026']==2023
  3. ラベルを定義(高齢化率閾値)+ 説明変数を 1000 人当たり率で計算
  4. cross_val_score で 3 モデル比較 → 上位 1-2 候補に絞る
  5. train_test_split(stratify=y) で hold-out 評価 → 混同行列・F1・AUC を併記
  6. 閾値を 0.1〜0.9 で振り、 業務コストに合った閾値を選ぶ
  7. 不均衡度を変えて頑健性を確認、 必要なら class_weight='balanced' や閾値調整
  8. 係数・特徴量重要度を読み、 「なぜそう判定したか」を説明可能にする
  9. Pipeline で前処理 + 分類器をまとめ、 GridSearchCV でハイパラ最適化
  10. 結果は 数値 + 不確実性 + 限界 の 3 点セットで報告

本ページで実行したコードを jupyter notebook で再現する

本ページの 6 つのコードブロックは、 順番に Jupyter のセルに貼り付ければそのまま動きます(SSDSE-B-2026.csv を data/raw/ 配下に置くこと)。 6 セル合計で 50 行程度、 実行時間は MacBook で 3 秒以内。 手元で動かしながらこのページを再度読むと、 数字と挙動が体に染み込みます。 「読むだけ → 動かして読む → 改造して読む」の 3 段階を踏むのが、 最速の習得法です。

本ページが想定する学習者像

どの層でも、 「30 秒結論 → 直感 → 数式 → Python → 落とし穴」の順で読めば 20-30 分で要点が掴めます。 後半の SSDSE-B-2026 実演は、 手を動かす段階で 必須 です。

類似タスクへの応用シナリオ

業務シナリオラベル設計注目すべき指標
顧客の離脱予測過去 N ヶ月で離脱したか(1/0)Recall(見逃しを減らす)、 PR-AUC
医療診断(陽性検出)病気あり/なし高 Recall(FN コスト大)、 閾値はビジネス基準
スパムフィルタスパム / ハム高 Precision(FP コスト大)、 F1
クレジット審査デフォルトする / しないAUC、 較正、 解釈可能性
画像分類(多クラス)N クラスの 1 つTop-k accuracy、 macro F1
不正検知不正取引 / 正常(不均衡)PR-AUC、 SMOTE、 閾値最適化

SSDSE-B-2026 の高齢化フラグタスクで身に付けた型は、 これら業務タスクすべてに横展開できます。 違うのは ラベル設計業務コスト注目指標 の 3 点のみ。 本ページの枠組みを応用して、 自分の業務データに当てはめてみてください。

🗺 概念マップ

「分類」を中心に、 教師あり学習・特徴量設計・モデル評価指標 (precision/recall/F1)・中規模データ実用域・クラス不均衡対策を 6 方向で配置した俯瞰図。 分類器の選択 → 学習 → 評価 → 不均衡対策の流れを 1 枚で示す。

classification 教師あり学習 特徴量設計 モデル評価指標 precision / recall / F1 中規模データ実用域 クラス不均衡対策

上の概念マップは「分類」を中心に、 結果の読み方(precision/recall/F1)と medium(中規模データでの実用域)、 各クラスの学習データ不足(class imbalance リスク)を 3 方向で並べた俯瞰図である。 中央ノードから放射する 3 つの軸を眺めると、 分類タスクで真っ先に確認すべき「データ量・指標・不均衡」の三点が一目で掴める。

🔗 隣接手法への橋渡し

「分類」は教師あり学習の中核で、 上流の特徴量設計とクラス分布の確認 (不均衡対応) を欠くと、 並列手法の比較すら無意味になる。

上流の特徴量と前処理を揃え、 並列のロジスティック回帰・SVM・勾配ブースティングをベンチマークし、 下流で混同行列と PR 曲線を出せば、 「どの手法が SSDSE データで最も汎化するか」を客観的に答えられる。

🌳 手法選択フロー

「分類」を実際に使うとき、 何をどう選ぶかを順に判断する。 上から順に答えていくと、 使うべき手法と評価の仕方が決まる。

  1. 目的変数は 2 値か、 3 つ以上か
    2 値ならロジスティック回帰から。 3 つ以上ならソフトマックス回帰か決定木系。 順序があるクラス(小・中・大)なら順序ロジットも候補。
  2. クラスの比率は偏っているか
    陽性が 1 割を切るなら正解率は使えない。 評価を PR-AUC や F1 に変え、 class_weight かリサンプリングで学習側も調整する。
  3. 説明を求められるか
    審査や政策の根拠にするならロジスティック回帰・決定木のように係数や分岐が読める手法。 精度だけが要るなら勾配ブースティングでよい。
  4. データは何件あるか
    n=47 の都道府県データでは、 深層学習は過学習する。 件数が数百に満たないなら線形モデルか浅い木に絞り、 交差検証で確かめる。

分類は「どのクラスか」を当てる枠組みで、 数値そのものを当てたいなら回帰へ。 A1101 人口を 3 階級化して分類問題にすると、 境目付近の県の扱いが恣意的になる点にも注意。

🎨 直感をさらに深める — 決定境界と「回帰との違い」

📝 補足(本節は既存「🎨 直感で掴む」の追記深化です。 既存の記述はそのまま、 決定境界・出力空間・タスク型の 3 点を補強します)。

分類とは「入力空間を境界で領域に割る」こと

分類器の学習とは、 特徴量が張る空間を 決定境界 (decision boundary) で複数の領域に区切り、 各領域に 1 つのクラスラベルを貼る作業です。 新しい入力 $\mathbf{x}$ は「どの領域に落ちたか」でクラスが決まります。 上の「🎮 触って理解する」ウィジェット① は、 この境界を 直線 1 本 で引く最小の体験装置です。 ロジスティック回帰は直線 (超平面)、 決定木は軸に平行な階段状、 SVM はカーネル次第で曲線 ── 「境界の形」がアルゴリズムの個性そのものだと捉えると、 手法比較の見通しが一気に良くなります。

内部的には各クラスの確率 $P(y=k\mid\mathbf{x})$ を計算し、 最大のクラスを選ぶ (softmax / シグモイド → argmax)。 だから「猫 0.7 / 犬 0.2 / 鳥 0.1」のような自信の度合いが同時に得られ、 これが後述の閾値調整確率較正の余地を生みます。

回帰との違いを 1 枚に整理

観点分類 (classification)回帰 (regression)
出力空間離散カテゴリ(有限集合)連続値(実数)
代表的な出力例高齢化進行県 / 未進行県高齢化率 31.6% という数値そのもの
典型的な損失クロスエントロピー / 対数損失二乗誤差 (MSE) など
主な評価指標正解率F1AUCR²・RMSE・MAE
「惜しい外れ」の扱いクラスが違えば一律に「不正解」近ければ誤差が小さい(連続的)

境界付近の値(例:高齢化率 31.6% の県)は本来「どちらとも言い難い」のに、 分類は無理やり 0/1 に押し込むため情報損失が起きます。 順序に意味がある連続量を予測したいなら、 まず回帰を検討し、 「意思決定として離散ラベルが必要」なときにだけ分類する ── これが出力空間の選び方の原則です。

2値・多クラス・多ラベルで「出力の形」が変わる

「排他か非排他か」を最初に決めないと、 損失関数(softmax か independent sigmoid か)も評価指標(accuracy か per-label F1 か)も間違えます。 タスク型の取り違えは、 実務で最も多い設計ミスの 1 つです。

⚠️ 落とし穴をさらに深める(重要)— 定義・指標・較正・リーク

📝 補足(既存「⚠️ よくある落とし穴」の追記深化。 とくにラベル定義の閾値が結論を左右する点を、 SSDSE-B-2026 の実測分布で示します)。

① ラベル定義の閾値で「問題そのもの」が変わる(実測)

高齢化率の閾値を動かすだけで、 陽性/陰性の比が劇的に変わります。 下表は SSDSE-B-2026(2023 年・47 都道府県)の実測クラス分布です(高齢化率 = A1303 ÷ A1101 × 100)。

ラベル閾値陽性(1)陰性(0)陽性率性質
≥ 28%40785.1%強い不均衡(陽性過多)
≥ 30%351274.5%やや不均衡
≥ 31.6%(平均)252253.2%ほぼ均衡
≥ 32%232448.9%ほぼ均衡(本文の既定)
≥ 35%64112.8%不均衡(少数陽性)
≥ 36%2454.3%極端な不均衡

同じデータでも、 閾値 28% なら「陽性を当てるのは簡単(85% が陽性)」、 36% なら「陽性 2 県を見つける難問」に化けます。 閾値は分析を始める前に業務根拠で固定し、 後から精度が良く出る値に変えてはいけません(HARKing / 事後選択バイアス)。 全国平均は 31.59%、 中央値 31.78%、 最小 22.75%(東京)〜 最大 39.06%(秋田)で、 多くの県が境界の 31〜32% 付近に密集している点にも注意します。

② 正解率が誤導する(accuracy paradox の再確認)

閾値 36%(陽性 4.3%)では、 全県を「陰性」と予測するだけで正解率 95.7% に達します(本文「⚖️ クラス不均衡を作って…」の実演と一致)。 しかし陽性 F1 は 0.000。 不均衡下では 正解率単独は無意味で、 適合率再現率・F1・PR-AUC を併記します。 詳細は クラス不均衡 ページへ。

③ 判定閾値の選択とクラス境界付近の不確実性

既定の 0.5 は「事前確率が均衡・誤りコストが左右対称」という強い仮定に依存します。 見逃し (FN) のコストが高いなら閾値を下げ、 誤検知 (FP) のコストが高いなら上げる。 全閾値を横断評価するのが ROC 曲線AUC適合率・再現率曲線です。 上の「🎮 触って理解する」ウィジェット② で、 閾値を動かすと適合率↑・再現率↓のトレードオフが即座に見えます。 さらに、 高齢化率 31.6% 付近に県が密集するため、 境界近傍の県はモデルの確率が 0.5 前後で揺れやすく、 わずかな特徴量差やシードで予測が反転します。 境界付近の予測は「自信度が低い」と明示するのが誠実な報告です。

④ 評価指標の選び方(1 つに頼らない)

指標見ているもの向いている場面
Accuracy全体の的中率クラスが均衡しているときのみ
Precision陽性予測の的中率誤検知コスト大(スパム判定など)
Recall真陽性の取りこぼしの裏見逃しコスト大(疾病検出など)
F1P と R の調和平均両者のバランスを 1 値で
ROC-AUC全閾値での順位性能閾値非依存で総合比較
PR-AUC不均衡下の陽性検出力陽性が希少なとき ROC より鋭敏

不均衡が強いほど ROC-AUC は楽観的に見えがちなので、 PR-AUC を主指標に据えるのが安全です。 体系的な整理は 評価指標混同行列 ページへ。

⑤ 確率較正 (calibration) の不足

出力確率「0.7」が実際の陽性頻度 70% に対応するとは限りません(この対応が取れている状態を較正が取れていると言います)。 ロジスティック回帰は比較的較正が良い一方、 SVM や決定木・ブースティングは歪みやすい。 Platt スケーリング(シグモイド較正)や Isotonic 回帰(単調較正)で補正し、 信頼度図 (reliability diagram) や Brier スコアで確認します。 確率をそのまま意思決定閾値やコスト計算に使うなら、 較正は精度と同等に重要です(※現時点で較正の専用用語ページは未整備のためテキストで補足)。

⑥ 多クラスの評価法(平均の取り方で結論が変わる)

「どの県が苦手か」を見たいなら macro、 「全体の当たり具合」なら micro。 本文の多クラス実演では macro avg と weighted avg を併記していますが、 どの平均で報告したかを明示しないと数字が独り歩きします。

⑦ リーク (leakage) ― 未来・定義・前処理の 3 経路

いずれも「テスト時に本来知り得ない情報」が訓練に混入する現象。 詳細は データリーク ページへ。

🌐 発展をさらに深める — 分類器の個性・境界の形・多クラス戦略・コスト考慮

📝 補足(既存「🌐 関連手法・派生」の追記深化。 代表分類器の特徴を横並びで整理します)。

代表分類器の「効きどころ」を横並びに

手法決定境界の形確率出力長所 / 注意
ロジスティック回帰線形(超平面)良好(較正されやすい)係数=log-odds で解釈容易 / 非線形は苦手
決定木軸に平行な階段状粗い(葉の頻度)ルール可読 / 単体は過学習しやすい
SVM線形〜カーネルで曲線要 Platt 較正マージン最大化で頑健 / スケール敏感・要標準化
k近傍法局所的・非線形近傍の多数決比率学習不要 / 高次元と距離スケールに弱い
ランダムフォレスト階段状の集合(滑らか化)中〜良高精度・頑健 / 解釈は重要度・SHAPで補強
勾配ブースティング(XGBoost 等・木アンサンブル弱学習器を逐次加算した複雑境界中(較正推奨)表形式で最強クラス / 過学習と調整コスト

「線形で足りるか(ロジスティック回帰)」→「非線形が要るか(木・カーネル)」→「精度最優先か(ブースティング)」の順に検討し、 解釈可能性と精度のトレードオフを業務要件から決めます。 距離・マージン系(SVM・kNN)は必ず標準化をパイプラインに入れる点に注意。

多クラス戦略:OvR と OvO

クラスが少なく確率較正を重視するなら multinomial、 2値分類器の資産を流用したいなら OvR、 という選び分けが実務的です。

確率出力と較正、そしてコスト考慮学習

分類の価値は「ラベル」より「確率」にあることが多い ── 確率があれば閾値もコストも後から最適化できます。 誤りのコストが非対称なとき(例:疾病見逃し $C_{FN}$ ≫ 誤検知 $C_{FP}$)は、 次のいずれかでコスト考慮学習 (cost-sensitive learning) を行います。

重み・リサンプリングは確率を歪めるため、 最後に較正し直すのが定石。 「①確率をきちんと出す → ②較正する → ③業務コストで閾値を決める」の 3 段構えが、 現代的な分類運用の型です。