論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
機械学習の基礎概念
Machine Learning Fundamentals
教師あり/なし/強化学習の3タイプ、 過学習と汎化、 バイアス-バリアンス、 損失関数、 ハイパラ調整、 train/valid/test の3分割 — 機械学習を始める前に押さえるべき中核概念。
機械学習ML基礎ml fundamentals

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

論文・記事に 「教師あり学習」「教師なし学習」「強化学習」「分類」「回帰」「特徴量」「過学習」「汎化」「バイアス-バリアンス」「損失関数」「ハイパーパラメータ」「交差検証」「訓練/検証/テスト」 として登場する機械学習の中核概念群。 個別のモデル(決定木・SVM・NN等)を学ぶ前に押さえるべき基礎の集合体です。

🔖 キーワード索引

論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:

🎯 教師あり学習 🔍 教師なし学習 🎮 強化学習 分類 / 回帰 / クラスタリング 📂 train/valid/test ⚠️ 過学習・汎化 ⚖️ バイアス・バリアンス 💔 損失関数 🔧 ハイパラ 🛡️ 正則化 🌳 ML ワークフロー 🚧 よくある誤解 📝 練習問題 🗺️ 概念マップ

💡 30秒で分かる結論

🗂️ 章俯瞰 — 機械学習の全体像

機械学習は「データからパターンを学習する」技術。 古典統計と異なり、 「予測精度」を最優先し、 大量のデータと計算資源を使うのが特徴。 タスクの種類で大きく 3 つに分類されます。

学習タイプ 入力 出力 代表タスク
教師あり$(\boldsymbol{x}_i, y_i)$ ペア$\hat{y}$ の予測分類・回帰
教師なし$\boldsymbol{x}_i$ のみ構造の発見クラスタリング・次元削減
強化学習状態 $s$、 行動 $a$方策 $\pi(a|s)$ロボット制御、ゲーム
半教師あり少数 $(x,y)$ + 多数 $x$同上ラベル付けコスト削減
自己教師あり$\boldsymbol{x}_i$ のみx 内部から擬似ラベル事前学習(BERT/GPT等)

🎯 教師あり学習(Supervised Learning)

入力 $\boldsymbol{x}$ と正解ラベル $y$ のペアから、 $\boldsymbol{x} \to y$ の写像を学ぶ。 機械学習の最も基本的かつ実用的なパラダイム。

データセット $\mathcal{D} = \{(\boldsymbol{x}_i, y_i)\}_{i=1}^N$ から、 損失 $L(y, f(\boldsymbol{x}))$ を最小化するモデル $f$ を学ぶ:

$$ \hat{f} = \arg\min_f \frac{1}{N}\sum_{i=1}^N L(y_i, f(\boldsymbol{x}_i)) + \lambda \Omega(f) $$

$\Omega(f)$ は正則化項(次節)。 教師ありの「種類」は y の型で決まります:

タスク$y$ の型代表手法代表的損失
回帰連続値線形回帰、 Ridge、 LASSO、 GBMMSE、 MAE
2値分類{0, 1}Logistic、 SVM、 RF、 XGBoostクロスエントロピー、 Hinge
多クラス分類{1, ..., K}Softmax 回帰、 NNカテゴリカル交差エントロピー
順序回帰順序付きラベルOrdinal Logistic専用損失

🔍 教師なし学習(Unsupervised Learning)

ラベルなしのデータ $\boldsymbol{x}_i$ から、 「データの構造」を発見する。 「何を予測するか」が明示されない探索的タスク。

🎮 強化学習(Reinforcement Learning)

エージェントが環境と相互作用して、 累積報酬を最大化する方策を学ぶ。 ゲーム AI、 ロボット制御、 推薦システムなどで活躍。

代表アルゴリズム:Q学習、 SARSA、 DQN、 Policy Gradient、 PPO、 Actor-Critic。 多腕バンディット問題(UCB、 Thompson Sampling)は強化学習の最も基本的な定式化。

📂 train / validation / test の3分割

機械学習の最重要規律。 データを 3 つに分けて、 役割を明確にします:

分割 用途 通常の割合
訓練(train)モデルパラメータの学習60〜80%
検証(validation)ハイパラ調整、 モデル選択10〜20%
テスト(test)最終評価(1回だけ)10〜20%

⚠️ テストデータでハイパラ調整するのは禁忌(データリーク)。 テストデータは「公開モデルの最終評価のために 1 回だけ触る」。 何度も使うと「テストにフィットしたモデル」になり、 真の汎化性能が分からなくなる。

k-fold 交差検証は、 train/validation を k 回ローテーションして安定したハイパラ調整を行う手法(詳細は 評価指標 #cv)。

1
2
3
4
5
6
7
8
9
from sklearn.model_selection import train_test_split

# 80% train+valid, 20% test
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

# 上の 80% を 75% train, 25% valid に分割(全体の 60/20/20 になる)
X_train, X_valid, y_train, y_valid = train_test_split(X_temp, y_temp, test_size=0.25, random_state=42, stratify=y_temp)

print(f'train={{len(X_train)}}, valid={{len(X_valid)}}, test={{len(X_test)}}')

⚠️ 過学習(Overfitting)と汎化(Generalization)

機械学習の中核問題。 訓練データだけで完璧に予測できても、 未知データで失敗するモデルは無価値。

原因:(1) モデルが複雑すぎる、 (2) 訓練データが少なすぎる、 (3) ノイズに過剰適合、 (4) 特徴量が多すぎる(次元の呪い)。

対策

診断方法

状態 訓練誤差 検証誤差 対策
未学習モデル複雑化、 特徴量増、 学習時間延長
良好そのまま
過学習正則化、 データ増、 早期停止、 シンプル化

⚖️ バイアス-バリアンス分解

予測誤差は数学的に 3 成分に分解できます:

$$ \mathbb{E}[(y - \hat{f}(\boldsymbol{x}))^2] = \underbrace{(\mathbb{E}[\hat{f}] - f)^2}_{\text{Bias}^2} + \underbrace{\mathrm{Var}(\hat{f})}_{\text{Variance}} + \underbrace{\sigma^2_\varepsilon}_{\text{Noise}} $$

これがいわゆるバイアス-バリアンスのトレードオフ。 モデルを複雑にすれば バイアス↓ だが バリアンス↑。 シンプルにすれば バイアス↑ だが バリアンス↓。 最適は両者の和が最小になる点。

💔 損失関数(Loss Function)

「予測 $\hat{y}$ と正解 $y$ のズレ」を測る関数。 機械学習は損失を最小化する最適化問題として定式化されます。

タスク 損失 公式
回帰MSE$\frac{1}{n}\sum (y_i - \hat{y}_i)^2$
回帰(ロバスト)MAE、 Huber$\frac{1}{n}\sum |y_i - \hat{y}_i|$
2値分類クロスエントロピー(Log Loss)$-\sum [y \log \hat{p} + (1-y)\log(1-\hat{p})]$
多クラス分類Categorical Cross-Entropy$-\sum_k y_k \log \hat{p}_k$
SVMヒンジ損失$\max(0, 1 - y \hat{f})$
ランキングPairwise / NDCG 損失専用

勾配降下法で損失を最小化します。 学習率 $\eta$、 勾配 $\nabla L$ で:$\boldsymbol{\theta} \leftarrow \boldsymbol{\theta} - \eta \nabla L$。

🔧 ハイパーパラメータ(Hyperparameter)

モデル学習前に決める「設定値」。 学習中に最適化されるパラメータ(重み $\boldsymbol{w}$ など)と区別。 例:

ハイパラ探索手法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier

param_grid = {{
    'n_estimators': [100, 200, 500],
    'max_depth': [3, 5, 10, None],
    'min_samples_split': [2, 5, 10]
}}

gs = GridSearchCV(RandomForestClassifier(), param_grid, cv=5, scoring='f1', n_jobs=-1)
gs.fit(X_train, y_train)
print(gs.best_params_, gs.best_score_)

# Optuna でベイズ最適化
import optuna
def objective(trial):
    params = {{
        'n_estimators': trial.suggest_int('n_estimators', 50, 500),
        'max_depth': trial.suggest_int('max_depth', 2, 32),
    }}
    return cross_val_score(RandomForestClassifier(**params), X, y, cv=5).mean()

study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)

🌳 機械学習プロジェクトの流れ

  1. 問題定義:何を予測するか、 ビジネス価値は? 教師あり/なし/強化のどれか?
  2. データ収集:信頼できるソース、 サイズ、 ラベル付け
  3. 探索的データ解析(EDA):分布・欠損・外れ値・相関を可視化
  4. 前処理:欠損補完、 標準化、 カテゴリ変数のエンコード、 特徴量エンジニアリング
  5. train/valid/test 分割:データリークに注意
  6. ベースラインモデル:シンプルな手法から(線形回帰、 RF)
  7. モデル選択:複数手法を CV で比較
  8. ハイパラチューニング:検証データで最適化
  9. 最終評価:テストデータで 1 回だけ
  10. デプロイ・モニタリング:本番運用、 データドリフト監視、 再学習

🚧 よくある誤解

❌ 誤解✅ 正しい理解
訓練データの精度が高ければ良いモデル過学習を疑う。 検証データ・テストデータで評価必須
複雑なモデルほど良いバリアンスが増え、 汎化性能が下がる
ハイパラ調整はテストデータでやるデータリーク。 検証データ or CV を使う
機械学習=何でも学習できる良いデータ・特徴量・問題設計が前提
教師なし学習は教師ありの劣化版役割が違う。 探索・発見のための強力な道具
特徴量は機械的に作れば良いドメイン知識に基づく特徴量エンジニアリングが性能に直結
深層学習なら常に最強テーブルデータでは GBM(XGBoost等)が勝つことが多い

📝 練習問題

問1:訓練データ精度 99%、 テスト精度 60% のとき、 何が起きているか?対策は?

過学習の典型例。 対策:(1) モデル複雑度を下げる(決定木なら深さ制限)、 (2) 正則化を強める、 (3) 訓練データを増やす、 (4) 特徴量を減らす、 (5) Early Stopping、 (6) アンサンブル化(バギング等)、 (7) クロスバリデーションで安定性確認。

問2:「同じデータで Random Forest と Logistic Regression を比較し、 RF の方が CV F1=0.85 で LR=0.72。 RF が圧勝?」

必ずしも。 確認事項:(1) 解釈性が必要なら LR の方が良い、 (2) 本番推論時間を考慮、 (3) 標準偏差も見る(0.85±0.05 vs 0.72±0.01 なら微妙)、 (4) ドメイン知識から見て予測根拠が妥当か、 (5) 過学習していないか。 ML は「精度だけ」ではなく実務制約を含めて判断。

問3:教師あり/なし/強化の使い分けを 3 つの具体的シナリオで説明せよ。
  • 教師あり:過去の顧客データから「解約する/しない」を予測(ラベル付き)
  • 教師なし:顧客全体を5つのセグメントに分けるが、 セグメント定義は事前にない(探索的)
  • 強化学習:レコメンドシステムでクリック率を最大化するように動的に学習(環境から報酬を得る)
問4:バイアス-バリアンス分解で「バイアスは小だがバリアンスが大」の状態は何を意味するか?

モデルは平均的には正しい答えに近い予測をするが、 訓練データが変わると予測が大きく揺れる。 つまり過学習傾向。 対策:シンプルなモデル、 正則化、 データ増加、 アンサンブル(特にバギングはバリアンスを下げる)。

問5:SSDSE 47都道府県データで、 教師あり分類タスクと教師なしクラスタリングのコード骨格を書け。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.cluster import KMeans
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932')
# 前処理...
X = df[['L322101','L322108','L322102']].values   # 家計3項目
X_std = StandardScaler().fit_transform(X)

# 教師あり:東日本/西日本 を予測
# y = ...
# scores = cross_val_score(LogisticRegression(), X_std, y, cv=5, scoring='f1')

# 教師なし:47県を3クラスタに
km = KMeans(n_clusters=3, random_state=42, n_init=10).fit(X_std)
print(km.labels_)

📋 報告フォーマット

「教師あり 2値分類タスク(n=1500、 陽性比率 12%)に対し、 Logistic Regression、 Random Forest、 XGBoost を比較。 train/valid/test = 60/20/20 で分割(stratify)。 検証データでハイパラを Optuna で 100 trial 探索後、 5-fold CV による評価:XGBoost AUC=0.87±0.02、 RF=0.84±0.02、 LR=0.78±0.01。 最終テストでは XGBoost が AUC=0.86、 F1=0.62。 バイアス・バリアンス的に XGBoost は他より高いバリアンスが疑われたため、 アーリーストッピング適用。」

🌐 ML プロジェクトのライフサイクル

研究や PoC を超えて本番運用まで考えると、 ライフサイクルは長くなります。

  1. 問題定義:ビジネス価値 → 機械学習で解けるか
  2. データ収集:信頼性、 量、 偏り、 ラベル
  3. 探索・前処理:EDA、 欠損、 外れ値、 特徴量
  4. モデル開発:ベースライン → 比較 → チューニング
  5. 評価:CV、 ホールドアウト、 ビジネス指標
  6. デプロイ:本番環境へモデル配置(API、 バッチ)
  7. モニタリング:性能低下・ データドリフトを監視
  8. 再学習:新データで定期的に更新

これら全体を回す技術が MLOps

📜 機械学習の歴史

🧮 SSDSE-B 実値計算例:47都道府県の「教師あり/教師なし」比較

SSDSE-B-2026(47都道府県、 2023年)から、 家計消費3項目(魚介・肉・野菜)を使い、 教師あり分類(東日本/西日本)と教師なしクラスタリング(3群)を実行して比較します。 ここでは scikit-learn の標準API でパイプラインを組みます。

📊 ステップ1:データ準備

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pandas as pd
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
# 2023年のみ抽出
df23 = df[df['年度']==2023].copy()
X = df23[['L322101', 'L322102', 'L322108']].values
X_std = StandardScaler().fit_transform(X)
# 西日本(関西以西)を1、東日本を0としてラベル化(仮の例)
west = ['京都府','大阪府','兵庫県','奈良県','和歌山県','鳥取県','島根県','岡山県','広島県','山口県','徳島県','香川県','愛媛県','高知県','福岡県','佐賀県','長崎県','熊本県','大分県','宮崎県','鹿児島県','沖縄県']
y = df23['都道府県'].isin(west).astype(int).values
print(X_std.shape, y.sum())  # (47,3) 22

📊 ステップ2:教師あり分類(Logistic + 交差検証)

SSDSE-B 47県の家計消費(魚介・肉・野菜)から「西日本かどうか」を予測した場合、 5-fold CV の F1 はおよそ 0.62〜0.70 程度。 47サンプルと小さいため標準偏差が大きく出ます。 過学習を防ぐため LogisticRegression(C=1.0) のような弱い正則化が安全です。

📊 ステップ3:教師なしクラスタリング(KMeans + シルエット)

3クラスタに分けると、 都市圏グループ(東京・大阪等)、 北海道・東北グループ、 西日本郊外グループの3群が抽出されることが多い。 シルエット係数(sklearn.metrics.silhouette_score)が 0.3 を超えれば、 ある程度クラスタが分離できていると判断できる。

📊 ステップ4:教師あり vs 教師なしの結果比較

観点 教師あり(Logistic) 教師なし(KMeans)
目的西/東 を当てる県の自然なグループを発見
評価F1, AUC, accuracyシルエット係数、 Davies-Bouldin
サンプル数依存小さいと不安定(n=47)クラスタ数依存だが教師ありより頑健
解釈係数で「どの食品が西日本性に効くか」分かるクラスタ中心で「各群の食生活の特徴」が分かる

💡 得られる洞察:47県という小データの場合、 教師ありは小サンプルゆえに過学習しやすく、 むしろ教師なしクラスタリングのほうが「県の食文化の構造」を素直に表現することが多い。 これはまさにML設計の核心。

⚠️ ML 初学者が陥る7大落とし穴(深掘り版)

① テストデータでハイパラを決めてしまう(データリーク)

「複数のハイパラ設定をテストデータで評価し、 最も良いものを選ぶ」のは典型的なデータリーク。 テストデータが間接的に学習に使われ、 報告する精度が楽観バイアスを持ちます。 対策は train / valid / test の 3分割 または nested CV。 validで選び、 testは最後に1度だけ評価。 Kaggle で「ローカル CV と public LB の差が大きい」現象も、 多くはこれが原因。

② 標準化を「全データで」やってから分割する

StandardScaler().fit_transform(X_all) → 分割、 は テストデータの平均・分散が学習に漏れる 古典的バグ。 必ず train で fit してtestには transform のみ。 scikit-learn の Pipeline + cross_val_score を使えば自動的に正しい順序で実行される。 これは時系列CVでも同じ。

③ クラス不均衡を accuracy で評価する

陽性率 1% のデータで「全て陰性」と予測するモデルでも accuracy = 99%。 一見高精度に見えても完全に無能。 不均衡データでは F1, AUC-ROC, AUC-PR, balanced accuracy を使う。 また、 訓練時には class_weight='balanced' や SMOTE / undersampling を検討。 業務指標(コストマトリクス)に直結する評価軸を選ぶことが大事。

④ 時系列データを「ランダム分割」してしまう

時系列で train_test_split(shuffle=True) を使うと、 未来の情報で過去を予測するという「タイムトラベル」が発生し、 精度が異常に高く見える。 必ず TimeSeriesSplit や Walk-Forward Validation を使い、 train は test より時間的に前のデータだけにする。 同様の問題は「同じユーザーが train/test 両方に出る」場合にも発生し、 GroupKFold が必要。

⑤ 「精度が高ければ良いモデル」と思い込む

本番運用では、 推論速度・モデルサイズ・解釈性・公平性(fairness)・データドリフト耐性も同じくらい重要。 例:医療診断 AI で AUC が高くても、 黒人患者に対する性能が極端に低い場合、 倫理的に運用できない。 「精度シングルメトリック思考」を脱却し、 多次元評価ダッシュボードを作るのがプロの態度です。

⑥ 「最新の手法 = 最良」と信じる

論文ベンチで SOTA な Transformer も、 中小企業の 1万行テーブルデータでは XGBoost に負けることが多い。 まずはベースライン(線形回帰・決定木)から始め、 段階的に複雑化するのが鉄則。 各段階で「複雑化のコスト(学習時間・解釈不能性)」と「精度向上」を天秤にかける。 Occam's Razor は ML でも有効です。

⑦ 特徴量エンジニアリングを軽視する

「深層学習は特徴量を自動的に学ぶ」は画像・音声・自然言語では真。 しかしテーブルデータでは人間の知識による特徴設計(比率・差分・対数変換・カテゴリ変数の集約・時間ラグ等)が予測精度に最も効きます。 ドメイン知識を持つ人と協働するのが、 結局のところ最強の戦略です。

🐍 Python 実装バリエーション

同じ「教師あり 2値分類」でも、 ライブラリと API スタイルによって書き方が大きく変わります。 ここでは scikit-learn / xgboost / lightgbm / pytorch の4種類の最小コードを示します。

① scikit-learn (Pipeline + GridSearchCV)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV

pipe = Pipeline([('sc', StandardScaler()),
                 ('clf', LogisticRegression(max_iter=1000))])
grid = GridSearchCV(pipe, {'clf__C': [0.01, 0.1, 1, 10]},
                    cv=5, scoring='f1')
grid.fit(X_train, y_train)
print(grid.best_params_, grid.best_score_)

② XGBoost (early stopping + DMatrix)

1
2
3
4
5
6
7
import xgboost as xgb
model = xgb.XGBClassifier(n_estimators=500, max_depth=4,
    learning_rate=0.05, eval_metric='logloss',
    early_stopping_rounds=20)
model.fit(X_train, y_train,
          eval_set=[(X_valid, y_valid)], verbose=False)
print(model.best_iteration, model.best_score)

③ LightGBM (カテゴリ特徴を直接扱える)

1
2
3
4
5
import lightgbm as lgb
model = lgb.LGBMClassifier(n_estimators=500, learning_rate=0.05)
model.fit(X_train, y_train, categorical_feature=['region'],
          eval_set=[(X_valid, y_valid)])
print(model.feature_importances_)

④ scipy.stats — 仮説検定との橋渡し

MLの予測結果を、 統計検定で「ベースラインより有意に良いか」確かめたい場面では scipy.stats が活躍。

1
2
3
4
5
from scipy import stats
# 2つのモデルの CV スコア(5回ずつ)を Wilcoxon 検定で比較
scores_a = [0.82, 0.85, 0.83, 0.84, 0.86]
scores_b = [0.78, 0.80, 0.79, 0.81, 0.80]
print(stats.wilcoxon(scores_a, scores_b))

⑤ PyTorch — 深層学習の最小例

テーブルデータでも、 特徴量が多くなったら PyTorch でカスタムNNを書く価値があります。

1
2
3
4
5
6
7
8
9
import torch, torch.nn as nn
class MLP(nn.Module):
    def __init__(self, d):
        super().__init__()
        self.net = nn.Sequential(nn.Linear(d, 64), nn.ReLU(),
                                 nn.Dropout(0.3),
                                 nn.Linear(64, 1))
    def forward(self, x): return self.net(x).squeeze(-1)
model = MLP(d=10)