実戦で使えるAIの交差検証 Vol.2

AI

前回の記事(Vol.1)では、AIの汎用性を証明する技術としてK-Fold Cross-Validationをマスターしました。
これで「特定のデータに依存しない、安定した性能」を持つモデルを開発する基礎は固まりました。

しかし、記事の最後で私たちは大きな壁に直面しました。
それは、実際のビジネスで頻繁に遭遇する「不均衡データ」です。

モデルが 99% の正解率を出しても、本当に重要な1%(例:購入顧客、詐欺事例など)を見逃していたとしたら、そのAIは実戦では全く価値がありません。
通常の K-Fold CV は、この重要な 1% を見逃す可能性が高く、さらに「正解率」という評価指標だけでは、その見逃しを見抜くことができません。

そこで、本記事 (Vol.2) 、Vol.1で提示された二つの課題を一挙に解決します。

  1. 検証の信頼性確保: 不均衡データでも検証結果が歪まない「Stratified K-Fold CV(層化K分割交差検証)」を実装し、その本質を理解します。
  2. 真の性能測定: 「正解率の罠」から脱却し、「再現率」「適合率」、そして不均衡データで最も信頼される「F1スコア」を導入し、あなたのAIが本当にビジネス目標を達成できるかを厳密に評価します。

第1章:LLM開発における検証技術の重要性と実用性

Stratified K-Fold CV(層化K分割交差検証)やそれに類する技術は、多くのユーザーに使用されているGeminiなどの大規模AIモデル(Large Language Models, LLMs)の開発・評価プロセスにおいて、極めて重要な役割を果たしています。

※ ただし、LLMsの検証は非常に複雑なため、単純なStratified K-Fold CVがそのまま使われているわけではなく、その検証哲学と概念が応用されています。

1.1. Stratified の概念の応用

Stratified CVの目的は、「テストセットが、実環境でのデータの偏りを公平に反映している状態を意図的に作り出し、検証結果の信頼性を確保すること」です。

通常の分類タスクでは、データをクラス(陽性/陰性)の比率で層化します。
しかし、LLMの学習や評価データは、単なる二値分類データよりも遥かに複雑な「タスクの種類」や「言語の多様性」という「層」を持っています。

  • LLMの層化: 評価セットを「タスクの種類」(例:要約、翻訳、コーディング、質問応答)や「言語・地域性」の比率で層化し、分割します。

例に挙げた Gemini の評価においても、特定のタスクや言語だけにモデルの性能が偏っていないかを確認するために、この層化の概念が不可欠となります。

1.2. Cross-Validation(交差検証)の概念の応用

Stratified K-Fold CVは、データセットが有限である場合に、最大限の情報を引き出してモデルを訓練・評価するために用いられます。

LLMの場合、データセットは膨大ですが、最終的な「性能評価ベンチマーク」は限られています。
開発チームは、この重要な評価ベンチマークを、モデルの進化の各段階で公平に、かつ頻繁に使用する必要があります。

交差検証の「データの分割と平均化」という精神は、異なる評価データサブセットや異なる利用者のフィードバックデータを用いてモデルの性能を測定し、その平均的な安定性を測るプロセスに深く根付いています。

Stratified K-Fold CVは、データサイエンスの「プロフェッショナルにとっての基本」であると言えます。
大規模AIモデル (LLMs) も、その基礎となる検証の哲学と技術の上に成り立っているのです。

第2章:不均衡データに対応する Stratified K-Fold CVの実装

本章の目的は、この基本技術をマスターし、「不均衡データに対する検証の脆弱性」を克服することです。

Stratified K-Fold CVの実装は非常にシンプルですが、その真価を実感するには、K-Fold CVを使った場合に検証結果がどれほど信頼できなくなるかを確認するのが効果的でしょう。

したがって、本章では次の流れで進めます。

  1. 問題の再現: 不均衡データを作成し、K-Fold CVで検証の安定性が崩壊する様を明確に示します。
  2. 解決策の実装: その崩壊した結果を、Stratified K-Fold CVの実装によってどのように安定させ、信頼性を回復させるかを証明します。

この対比を通して、Stratified K-Fold CVがまさに「プロフェッショナルの基本」であることを明確に実感しましょう。

2.1. 課題の再現:不均衡データの検証問題

ここでは、実戦を想定し、意図的に極端な不均衡データを作成し、通常のK-Fold CVがどのように機能不全に陥るかを検証します。

2.1.1. 不均衡データセットの作成

1000個のデータのうち、陽性(Positive)クラスがわずか1%(10個)しかない、極端な不均衡データを作成します。

新規 Python ファイル imbalance_check.py のコードは次の通りです。

import numpy as np
from sklearn.model_selection import cross_val_score, KFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification

# 1. 極端な不均衡データセットの作成 (陽性クラスがわずか1%)
X, y = make_classification(
    n_samples=1000,          # サンプル総数
    n_features=20,           # 特徴量数
    n_informative=10,
    n_redundant=10,
    n_classes=2,
    n_clusters_per_class=1,
    weights=[0.99, 0.01],    # クラスの比率を設定: 陰性(99%), 陽性(1%)
    flip_y=0,
    random_state=42
)

# 2. モデルの準備
model = RandomForestClassifier(random_state=42)

2.1.2. 通常のK-Fold CVによる検証

この不均衡データに、Vol.1で使用した通常のK-Fold CVを適用します。
ここでは、K-Foldクラスを明示的に使用し、分割方法を確認しやすくします。

imbalance_check.py に、以下のプログラムを追加してください。

# 通常のK-Fold分割器を準備 (ランダム分割)
kf = KFold(n_splits=5, shuffle=True, random_state=42)

# 通常のK-Fold CVで検証を実行
# scoring='accuracy'(正解率)を使用
kfold_scores = cross_val_score(model, X, y, cv=kf, scoring='accuracy')

print("--- 通常のK-Fold CV 結果 ---")
print(f"各Foldの精度スコア: {kfold_scores}")
print(f"平均精度 (汎用性能): {kfold_scores.mean():.4f}")
print(f"標準偏差 (信頼性のばらつき): {kfold_scores.std():.4f}")

2.1.3. 実行結果の確認

上記のコードを実行すると、次のような結果が得られます。(環境によって異なる場合があります

実行結果
--- 通常のK-Fold CV 結果 ---
各Foldの精度スコア: [0.99  1.    0.995 0.995 0.99 ]
平均精度 (汎用性能): 0.9940
標準偏差 (信頼性のばらつき): 0.0037

この結果は一見、平均精度が 99.4% と非常に高く、標準偏差も低く安定しているように見えます。
しかし、これは「正解率の罠」であり、検証が完全に失敗している可能性があります。

なぜなら、データ全体の 99% が陰性であるため、AIが「全て陰性だと予測する」だけでも99%の正解率を出せてしまうからです。
つまりは、「正解率(精度)」だけでは結果の正当性を保証することができないわけです。

正解率以外の指標として、再現率と適合率のバランスを取ったF1スコアがあります。
「F1スコアを通常のK-Fold CVに指定 (scoring='f1') すれば良いのでは?」と考えましたが、この方法では次の致命的・技術的問題が発生します。

F1スコアは、再現率(Recall)と適合率(Precision)の平均です。そして、再現率と適合率は、どちらも少数派クラスが正しく検出されたかどうか(真陽性 \(TP\))と、実際にあるべき数(偽陰性 \(FN\))を分母に含みます。

ここで、再現率 (Recall) は \(\displaystyle \frac{TP}{TP + FN}\) で計算されます。

データセット全体で陽性が \(1\%\) しかない場合、通常の K-Fold CV では、ある Fold で陽性データ (\(TP + FN\)) が \(0\) になる可能性があります。
通常のK-Fold CVの分割方法は、ランダム分割だからです。

  • 陽性データが 0 の Fold: \(TP + FN = 0\) となり、分母がゼロになります。
  • 結果: この Fold での再現率 (Recall) の計算が技術的に失敗し、F1 スコアも計算できなくなります。

以上のことから、通常の K-Fold CV は、信頼できる F1 スコアを計算するための「土台」として機能しないと言えるのです。

次のセクションでは、この問題をStratified K-Fold CVがいかに簡単に解決するかを証明します。

2.2. Stratified K-Fold CVの実装

通常の K-Fold CV は、不均衡データに対して検証結果が信用できないだけでなく、F1スコア計算の分母が \(\mathbf{0}\) になるリスクという致命的な問題を抱えていることが分かりました。

この問題を解決し、「信頼できる F1 スコア」を得るための検証の土台を築くのが、Stratified K-Fold CVです。

2.2.1. Stratified K-Fold の導入と実装

Stratified K-Fold CV の実装は KFold の代わりに、StratifiedKFold を使用します。

新規 Python ファイル stratified_validation.py のコードは次の通りです。

import numpy as np
from sklearn.model_selection import StratifiedKFold, cross_validate
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification

# 前セクションで作成した不均衡データセットを再利用
X, y = make_classification(
    n_samples=1000,
    n_features=20,
    n_informative=10,
    n_redundant=10,
    n_classes=2,
    n_clusters_per_class=1,
    weights=[0.99, 0.01],
    flip_y=0,
    random_state=42
)

model = RandomForestClassifier(random_state=42)

# Stratified K-Fold 分割器を準備
# K=5 (5分割) を設定し、shuffle=Trueでランダム性も加える
# 重要な点:StratifiedKFold は cross_validate に渡す際に y の情報を使って自動で層化します
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

# cross_validate で複数の評価指標を同時に計算
scoring_metrics = ['accuracy', 'f1']

# Stratified K-Fold CVで検証を実行
# cv=skf (Stratified 分割器) を使用し、scoringで複数の指標を指定
cv_results = cross_validate(
    model, 
    X, 
    y, 
    cv=skf, 
    scoring=scoring_metrics,
    return_train_score=False # 学習データに対するスコアは不要
)

print("--- Stratified K-Fold CV 結果 ---")
print(f"各Foldの精度スコア (Accuracy): {cv_results['test_accuracy']}")
print(f"各FoldのF1スコア: {cv_results['test_f1']}")
print("-" * 30)
print(f"平均精度 (Accuracy): {cv_results['test_accuracy'].mean():.4f}")
print(f"標準偏差 (Accuracyのばらつき): {cv_results['test_accuracy'].std():.4f}")
print(f"平均F1スコア: {cv_results['test_f1'].mean():.4f}")
print(f"標準偏差 (F1スコアのばらつき): {cv_results['test_f1'].std():.4f}")

2.2.2. cross_validate の解説

cross_validate関数は、複数の指標を一度に計算できるだけでなく、Foldごとの結果を辞書形式で整理して返すため、実際の開発現場では頻繁に使用されます。

  • scoring=['accuracy', 'f1']: この設定を cross_validate 関数の引数に渡すことにより、test_accuracytest_f1というキーで、それぞれの Fold のスコアを取得できます。
  • cv=skf: ここに StratifiedKFoldのインスタンスを渡すことで、「Stratified」な分割方法が適用されます。

2.2.3. Stratified CVが信頼性を保証する仕組み

Stratified K-Fold CVの強みは、その名が示す「層化(Stratification)」にあります。

  • 陽性データの存在を保証: Stratified K-Fold CVは、データ全体のクラス比率(この例では陽性 \(1\%\))を計算し、分割されたすべての Fold に対して、その比率を可能な限り維持するようにデータを割り振ります。
  • 計算エラーの回避: これにより、F1スコア計算で分母が \(0\) になるリスクを意図的に回避し、すべての Fold で F1 スコアが安定して計算される状態を保証します。

2.3. 結果の比較:信頼性の証明

セクション2.1で実行した通常の K-Fold CV と、セクション2.2で実装した Stratified K-Fold CV の実際の実行結果を比較し、Stratified CVの優位性を証明します。

通常のK-Fold CVの実行結果(再掲)
--- 通常のK-Fold CV 結果 ---
各Foldの精度スコア: [0.99  1.    0.995 0.995 0.99 ]
平均精度 (汎用性能): 0.9940
標準偏差 (信頼性のばらつき): 0.0037
Stratified K-Fold CVの実行結果
--- Stratified K-Fold CV 結果 ---
各Foldの精度スコア (Accuracy): [0.995 0.99  0.995 0.99  0.995]
各FoldのF1スコア: [0.66666667 0.         0.66666667 0.         0.66666667]
------------------------------
平均精度 (Accuracy): 0.9930
標準偏差 (Accuracyのばらつき): 0.0024
平均F1スコア: 0.4000
標準偏差 (F1スコアのばらつき): 0.3266

ご覧の通り、「平均スコア」と「標準偏差」にはほとんど差がありません。
「標準偏差」で、ほんの0.0013ほど Stratified K-Fold CV の検証結果のばらつきが小さくなった(安定した)ことを示しているぐらいでしょうか。
この結果は想定内で、「正解率(精度)」そのものにはあまり差が出ないからです。

重要なのは、今回追加した評価指標の「F1スコア」です。

Stratified CVの平均 F1スコアは \(0.4000\) という、モデルの検出能力を示す数値を安定的に算出しました。
それに対し、K-Fold CVでは項 2.1.3 で説明した通りF1スコアを使用できません。

この違いにより、同じ「正解率(精度)」であっても、信ぴょう性が変ってくるということです。

F1スコアの一般的な評価基準

F1スコアは \(0}\) から \(1\) の値を取り、\(1\) に近いほど理想的(完全な検出能力)であることを示します。

今回のケースでは、「陽性(異常データ)」を検出したいという目的があり、F1スコア \(0.4000\) は半分にも満たないため、「このままでは実戦で使えず、改善が必要な水準である」と判断します。

まとめ:交差検証における最終課題

本記事で、私たちは不均衡データという最大の難敵に対し、Stratified K-Fold CVという技術で立ち向かいました。

検証の不安定性を改善させ、F1スコアという新たな指標を追加し、信ぴょう性の高い検証の土台を築くという意味では一定の成功を収めたと言って良いでしょう。

しかし、ここにきて最も重要な問いが残ります。

「F1スコア \(0.4000\) という数値は、具体的に、モデルがどのようなミスを犯した結果なのだろうか?」

モデルが陽性データを検出する能力の片鱗を捉えはしたものの、見逃しが多いのか、それとも誤報が多いのか、その内訳はまだわかりません。
この内訳が分からなければ、モデルを改善するための具体的な行動指針も立てられません。

そこで次回の記事「実戦で使えるAIの交差検証 Vol.3」では、このF1スコア \(0.4000\) の謎を解き明かすための最後の分析ツールを習得します。

  • 混同行列(Confusion Matrix): AIの予測ミスをたった4つの数字で分類する集計表。
  • 再現率(Recall)と適合率(Precision): F1スコアの構成要素であり、ビジネスリスク(見逃し vs. 誤報)に応じてモデルを最適化するための羅針盤。

この技術を習得することで、交差検証との長い闘いに終止符を打ち、実戦で通用するAIモデルを開発・調整する力を手に入れることになるでしょう。

コメント

タイトルとURLをコピーしました