AIモデルの解釈性向上:SHAPとLIMEによる包括的比較

Tech

AIモデルの解釈性向上:SHAPとLIMEによる包括的比較

要点(3行)

  • SHAPとLIMEは、AIモデルの予測根拠を説明する主要な解釈手法であり、それぞれの特性を理解することで、より信頼性の高いモデル運用が可能になります。

  • SHAPはゲーム理論に基づき特徴量の予測貢献度を公平に分配する一方、LIMEはモデルの局所的な振る舞いをシンプルな代理モデルで説明します。

  • 用途や計算リソースに応じて適切な手法を選択し、解釈の忠実度や安定性を評価しながら進めることが推奨されます。

背景(課題/先行研究/最新動向)

AIモデルの普及に伴い、その「ブラックボックス性」が大きな課題となっています。特に医療診断、金融取引、司法判断といった高リスク分野では、AIがなぜそのような予測や決定をしたのかを説明する「説明責任」が強く求められます。この要求に応えるため、モデルの透明性、理解性、信頼性を高めることを目指すExplainable AI(XAI)の分野が重要視されています。

その中でも、SHAP (SHapley Additive exPlanations) [1](2017年12月4日公開)とLIME (Local Interpretable Model-agnostic Explanations) [2](2016年8月14日公開)は、最も広く用いられるモデル非依存(Model-agnostic)な解釈手法として確立されています。両手法は、個々の予測がなぜなされたのかを特徴量の貢献度として可視化することで、モデルの意思決定プロセスを人間が理解しやすくします。

最新動向(直近90日)

  • 2025年9月15日、Google CloudのVertex AIにおけるExplainable AI機能が強化され、より大規模なデータセットや複雑なモデルへの対応が図られています [4]。

  • 2025年9月1日、Google AI Blogにて、大規模言語モデル(LLM)の解釈性に関する最新の研究動向が紹介され、アテンションメカニズムや因果的介入による説明手法が議論されています [5]。

  • 2024年7月20日公開の最新サーベイ論文では、XAI手法の分類、評価指標、倫理的側面、そして将来的な研究課題が包括的にまとめられています [3]。

提案手法 / モデル構造

本セクションでは、SHAPとLIMEそれぞれの理論的背景と動作原理、および一般的なパイプラインにおける適用方法を解説します。

SHAP (SHapley Additive exPlanations)

SHAPは、協調ゲーム理論におけるShapley値に基づき、各特徴量がモデルの予測にどれだけ貢献したかを計算します。Shapley値は、特徴量の組み合わせ(連合)を考慮し、予測に対する各特徴量の「公正な貢献度」を算出するため、特徴量間の相互作用も捉えることができます。厳密なShapley値の計算は特徴量数に対して指数関数的に増加するため困難ですが、KernelSHAPTreeSHAPDeepSHAPなどの近似アルゴリズムが存在し、モデルタイプに応じて効率的に計算されます。SHAPは、個々の予測に対する局所的な説明と、モデル全体の平均的な特徴量重要度を示す大域的な説明の両方を提供可能です。

LIME (Local Interpretable Model-agnostic Explanations)

LIMEは、解釈したいデータ点(インスタンス)の「近傍」において、元の複雑なモデルの振る舞いを近似するシンプルな解釈可能なモデル(代理モデル)を学習します。具体的には、対象インスタンスの近傍でデータを摂動させて多数の仮想データ点を生成し、それらに対する元のモデルの予測結果を用いて、線形モデルや決定木といったシンプルな代理モデルを学習します。この代理モデルが、元のモデルの局所的な振る舞いを説明することで、ブラックボックスモデルにも適用可能な解釈を提供します。

SHAPとLIMEのワークフロー比較

graph TD
    A["入力データ点 X と 学習済みモデル f"] --> B{"解釈対象の予測 f(X)"}

    B --> C1["SHAP: Shapley値計算"]
    C1 --> C1a["特徴量連合の生成"]
    C1a --> C1b["各連合での予測差分評価"]
    C1b --> C1c["Shapley値の公平な分配"]
    C1c --> D1["SHAP値による特徴量貢献度"]

    B --> C2["LIME: 局所的摂動と代理モデル学習"]
    C2 --> C2a["X の近傍で摂動データ点 X' を多数生成"]
    C2a --> C2b["摂動データ点 X' にて f(X') を予測"]
    C2b --> C2c["近傍の重み付けと線形代理モデル g(X') を学習"]
    C2c --> D2["局所線形モデルによる説明"]

    D1 --> E["予測の根拠を可視化・解釈"]
    D2 --> E

擬似コード / 最小Python

以下は、SHAPとLIMEを呼び出してモデル予測を解釈するためのPython関数の例です。

# AIモデル解釈パイプライン (SHAPとLIMEの呼び出し例)


# 入力: model (学習済みモデル), X (numpy.array or pandas.DataFrame; 解釈対象の入力データ),


#       X_train (numpy.array or pandas.DataFrame; モデルの学習データ、SHAPの背景データに利用)


# 出力: explanations (dict; 'shap'と'lime'のそれぞれの説明オブジェクトを含む)


# 計算量: n_features=特徴量数, n_instances=インスタンス数


#         SHAP: KernelSHAPの場合 O(n_instances * n_features * n_samples_background * subset_evals) (worst case),


#               TreeSHAPの場合 O(n_instances * n_features * n_trees * tree_depth)。


#         LIME: O(n_instances * n_perturbations * (model_prediction_cost + n_features^2))。


# メモリ: モデルサイズとデータサイズに依存。特にSHAPの背景データやLIMEの摂動データが大規模な場合注意。

import shap
import lime
import lime.lime_tabular # 表形式データの場合
import numpy as np
import pandas as pd

def explain_model_predictions(model, X, X_train=None, method='both', num_perturbations=1000):
    explanations = {}

    # モデルの予測関数を定義

    if hasattr(model, 'predict_proba'): # 確率予測を持つ分類モデル
        predict_fn = model.predict_proba
    else: # 回帰モデルやクラス予測のみの分類モデル
        predict_fn = model.predict

    # SHAPによる説明

    if method == 'shap' or method == 'both':
        print("Calculating SHAP values...")

        # KernelSHAPは背景データX_trainが必須

        if X_train is not None:

            # 大規模なX_trainの場合、サンプリングを推奨

            if isinstance(X_train, (pd.DataFrame, np.ndarray)):

                # KernelSHAPの背景データとして学習データの一部を利用 (例: 100サンプル)

                X_train_sample = shap.utils.sample(X_train, 100) if len(X_train) > 100 else X_train
            else:
                X_train_sample = X_train # X_trainが既にリストや配列として渡された場合

            explainer = shap.KernelExplainer(predict_fn, X_train_sample)
            shap_values = explainer.shap_values(X)

            # feature_namesを適切に設定 (pandas DataFrameの場合)

            feature_names = X.columns.tolist() if isinstance(X, pd.DataFrame) else [f'feature_{i}' for i in range(X.shape[1])]
            explanations['shap'] = shap.Explanation(shap_values, explainer.expected_value, X.values, feature_names=feature_names)
        else:

            # TreeSHAPはモデルに依存するため、ここでは汎用的なKernelSHAPに焦点を当てる。


            # X_trainがない場合、KernelSHAPは実行できないため警告

            print("Warning: X_train (background data) is required for KernelSHAP to provide accurate explanations.")
            print("SHAP calculation skipped or may not be accurate.")


    # LIMEによる説明

    if method == 'lime' or method == 'both':
        print("Calculating LIME explanations...")

        if X_train is not None:
            feature_names = X.columns.tolist() if isinstance(X, pd.DataFrame) else [f'feature_{i}' for i in range(X.shape[1])]
            class_names = getattr(model, 'classes_', ['class_0', 'class_1']) # 分類モデルの場合

            # LimeTabularExplainerを初期化

            lime_explainer = lime.lime_tabular.LimeTabularExplainer(
                training_data=X_train.values,
                feature_names=feature_names,
                class_names=class_names,
                mode='classification' if hasattr(model, 'predict_proba') else 'regression'
            )

            lime_explanations_list = []

            # 各インスタンスについてLIME説明を生成

            for i in range(len(X)):
                data_row = X.iloc[i].values if isinstance(X, pd.DataFrame) else X[i]
                exp = lime_explainer.explain_instance(
                    data_row=data_row,
                    predict_fn=predict_fn,
                    num_features=len(feature_names), # 説明する特徴量の数
                    num_samples=num_perturbations
                )
                lime_explanations_list.append(exp)
            explanations['lime'] = lime_explanations_list
        else:
            print("Warning: LIME requires training_data for feature statistics. LIME calculation skipped.")

    return explanations

# # 使用例 (ダミーデータとモデル)


# # import pandas as pd


# # from sklearn.ensemble import RandomForestClassifier


# # from sklearn.model_selection import train_test_split


# # from sklearn.datasets import make_classification


# #


# # # ダミーデータ生成


# # X_data, y_data = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=0, random_state=42)


# # feature_names = [f'feature_{i}' for i in range(X_data.shape[1])]


# # X_df = pd.DataFrame(X_data, columns=feature_names)


# #


# # X_train_df, X_test_df, y_train, y_test = train_test_split(X_df, y_data, test_size=0.2, random_state=42)


# #


# # # ダミーモデル学習


# # rf_model = RandomForestClassifier(random_state=42)


# # rf_model.fit(X_train_df, y_train)


# #


# # # 解釈の実行 (最初のテストインスタンスを解釈)


# # instance_to_explain = X_test_df.iloc[[0]]


# # explanations = explain_model_predictions(rf_model, instance_to_explain, X_train_df, method='both')


# #


# # if 'shap' in explanations and explanations['shap'] is not None:


# #     print("\nSHAP Explanation (first instance):")


# #     # Classificationの場合、shap_valuesはクラスごとのリスト。ここではクラス1の説明を表示


# #     shap.plots.waterfall(explanations['shap'][0], max_display=10) # 修正: shap.Explanationオブジェクトの直接プロット


# #


# # if 'lime' in explanations and explanations['lime']:


# #     print("\nLIME Explanation (first instance):")


# #     exp = explanations['lime'][0]


# #     print(exp.as_list())


# #     # exp.show_in_notebook(show_table=True, show_all=False) # Jupyter Notebook向け

計算量/メモリ/スケーリング

SHAPとLIMEの計算コストは、モデルの種類、特徴量数、インスタンス数、および設定されるハイパーパラメータによって大きく異なります。

SHAP

  • 厳密なShapley値計算: 特徴量数 F に対して O(F * 2^F) の計算量が必要となり、現実的には非常に困難です。

  • KernelSHAP: M 個の摂動サンプルを生成してShapley値を近似します。計算量は O(M * F * モデル予測コスト) となり、M は通常 2 * F から 2 * F^2 の範囲で選択されます。特徴量数が増えると計算コストが急増する傾向があります。

  • TreeSHAP: 決定木ベースのモデル(XGBoost, LightGBM, RandomForestなど)に特化しており、O(T * F * D) (T は木の数、D は木の深さ) と非常に効率的な計算が可能です。

  • DeepSHAP / GradientSHAP: ディープラーニングモデル向けに、バックプロパゲーションを利用して効率的な計算を実現します。

  • メモリ: KernelSHAPの場合、背景データセット (X_train) のサイズが大きすぎると、メモリ使用量がボトルネックになることがあります。

LIME

  • 計算量: num_perturbations P と特徴量数 F に対し、O(P * モデル予測コスト + P * F^2) 程度の計算量となります。各インスタンスごとに独立して摂動生成と局所モデル学習を行うため、単一インスタンスの解釈ではSHAPよりも高速な場合が多いです。

  • メモリ: 摂動データセット P と局所モデルの学習データがメモリに一時的に保持されます。

スケーリング

  • SHAP: 特徴量数が増えると、特にKernelSHAPの計算コストが急増します。大規模データセットや高次元データでは、TreeSHAPのような効率的な実装や、背景データのサンプリングが不可欠です。

  • LIME: 各インスタンスを独立して解釈するため、並列化が容易です。しかし、num_perturbations の値が大きすぎると、予測コストが高いモデルでは時間がかかります。

実験設定/再現性

SHAPとLIMEの比較実験を行う場合、以下のような設定が考えられます。

  • データセット: UCI Machine Learning Repositoryから、例えば「Adult」データセット(分類タスク)や「California Housing」データセット(回帰タスク)など、特徴量とデータ点数が中程度のものを選択します。

  • 対象モデル: Scikit-learnライブラリのRandomForestClassifierXGBoostClassifierMLPClassifier(多層パーセプトロン)など、異なるアルゴリズムと複雑性を持つモデルを学習させます。

  • 実装ライブラリ:

    • SHAP: Python shapライブラリ (バージョン0.44.0, 2024年10月1日更新) を使用。KernelExplainer、TreeExplainer、DeepExplainerなど、モデルに応じた適切なExplainerを選択します。

    • LIME: Python limeライブラリ (バージョン0.2.0.1, 2023年5月10日更新) を使用。LimeTabularExplainerを適用します。

  • 評価指標:

    • 忠実度 (Fidelity): 生成された説明が、元のモデルの予測をどれだけ正確に反映しているか。LIMEの場合、代理モデルのR^2値や適合度で評価します。SHAPの場合、Shapley値に基づく予測と元のモデル予測の差分を評価します。

    • 安定性 (Stability): 入力データにごくわずかな摂動(例: 微小なノイズ付与)を加えた際に、生成される説明(SHAP値やLIMEの重み)がどれだけ一貫しているかを評価します。

    • 計算時間: 各手法で単一または複数のインスタンスを解釈するのに要する時間を計測し、スケーラビリティを比較します。

    • 人間による評価 (定性): 可能であれば、ドメイン専門家が説明をどの程度理解し、信頼できると感じるかを定性的に評価します。

  • 環境設定: Python 3.9+、scikit-learn 1.3+、numpy 1.26+、pandas 2.1+。すべての実験において乱数種(random_state=42など)を固定し、再現性を確保します。

結果(表)

SHAPとLIMEの主要な特性を比較した表を以下に示します。

項目 SHAP (Shapley Additive exPlanations) LIME (Local Interpretable Model-agnostic Explanations)
理論的背景 協調ゲーム理論 (Shapley値) 局所摂動と代理モデル (線形モデル等)
解釈の範囲 局所的 (個々の予測) および 大域的 (モデル全体) 局所的 (個々の予測)
モデル依存性 モデル非依存 (KernelSHAPは汎用、TreeSHAPは決定木ベースモデルに最適) モデル非依存
計算コスト 高 (特にKernelSHAPは特徴量数に対して指数関数的に増加しうる) 中 (摂動回数と特徴量数に依存、単一インスタンスではSHAPより速いことが多い)
説明の安定性 比較的安定しているが、近似手法や背景データに依存 摂動戦略や近傍の定義に敏感で、不安定になる場合がある
忠実度 Shapley値の数学的保証により高忠実度 (近似は誤差を生じる可能性あり) 局所的な近似の良さに依存。摂動のサンプリングや代理モデル選択が重要
特徴量間の相互作用 考慮される 直接的には考慮されないが、摂動により間接的に反映されうる
適用データ 表形式、テキスト、画像 (専用のExplainer利用) 表形式、テキスト、画像 (専用のExplainer利用)
出力形式 SHAP値 (各特徴量の貢献度)、依存プロット、概要プロット 特徴量と重みのリスト (線形モデルの場合)、可視化
長所 数学的根拠が強固、公平な貢献度、大域/局所説明、相互作用考慮 高速、直感的、モデル非依存、局所的な振る舞いを明確に、比較的実装が容易
短所 計算コストが高い、背景データに依存、実装が複雑 局所説明のみ、摂動戦略の選択、近傍定義の曖昧さ、説明の不安定性、高次元データでの品質維持が難しい

考察(仮説と根拠を分離)

SHAPとLIMEは、異なる理論的背景と動作原理を持つため、それぞれの特性を理解し、適用シナリオに応じて適切に使い分けることが重要です。

  • 理論的基盤の差異: SHAPはゲーム理論に基づく一貫性と公平性という強い数学的保証を持つ一方、LIMEはヒューリスティックな局所近似に依存しています。この違いが、特徴量間の相関が高いデータや、モデルの非線形性が強い領域における説明の質に影響を与えます。

  • 解釈の範囲: SHAPは、個々の予測に対する詳細な貢献度(局所説明)だけでなく、モデル全体でどの特徴量が平均的に重要であるか(大域説明)も提供できます。対照的に、LIMEは本質的に特定の予測インスタンスの近傍に限定された局所的な説明に特化しています。モデルの全体像を把握したい場合はSHAPが、特定の予測理由を知りたい場合はLIMEがより適しています。

  • 計算コスト vs. 速度: 大規模データセットや多数のインスタンスを解釈する場合、特に汎用的なKernelSHAPの計算負荷は高くなります。リアルタイム性が求められるシステムでは、単一インスタンスの解釈が速いLIMEが選択されることがあります。ただし、LIMEの場合、説明の品質を確保するために十分な摂動回数が必要です。

  • 頑健性と安定性: 高相関な特徴量を持つデータでは、SHAPはそれらの特徴量に貢献度を「分配」するため、個々の特徴量の重要度が低く見積もられることがあります。LIMEは摂動の仕方や近傍の定義によって、説明が不安定になる可能性があります [3]。これは、摂動戦略の選択とハイパーパラメータチューニングの重要性を示唆しています。

失敗例・感度分析

AIモデルの解釈手法は万能ではなく、特定の状況下では信頼性の低い説明を生成したり、ハイパーパラメータに敏感に反応したりすることがあります。

SHAPの失敗例・感度

  • 特徴量間の共線性: 特徴量間に高い相関がある場合、SHAPは貢献度を複数の相関する特徴量に分散させるため、個々の特徴量の真の重要性を過小評価したり、分かりにくくしたりすることがあります。

  • 背景データの選択: KernelSHAPにおいて、Shapley値を近似するための背景データ(X_train)の選択が不適切だと、説明の質が大きく低下する可能性があります。背景データが解釈対象の分布を代表していない場合、信頼性の低いSHAP値が生成されます。

  • 感度分析: X_trainのサンプリングサイズや、特定のexplainerの選択(KernelSHAP vs TreeSHAP)は、SHAP値の安定性や計算時間に大きな影響を与えます。これらの選択は、解釈の忠実度と実用性に直接関わります。

LIMEの失敗例・感度

  • 局所性の定義の曖昧さ: 「局所性」の定義(摂動の範囲や近傍の重み付け関数 kernel_width など)が曖昧であるため、これらの設定によってLIMEの説明が大きく変動し、不安定な結果を生じることがあります。特に、モデルの決定境界が複雑で非線形性が強い領域では、シンプルな線形代理モデルの忠実度が低くなる傾向があります。

  • 摂動ノイズの影響: 摂動生成プロセスにおけるノイズや、num_perturbations(摂動回数)が少なすぎると、局所モデルの学習が不十分になり、信頼性の低い説明が生成される可能性があります。

  • 感度分析: num_perturbationskernel_width などのハイパーパラメータは、生成される説明の忠実度と安定性に直接的な影響を与えるため、ドメイン知識や実験を通じて慎重な調整が必要です。

限界と今後

SHAPとLIMEは強力なXAI手法ですが、いくつかの限界も存在し、今後の研究開発が期待されます。

  • 因果関係の解釈: SHAPもLIMEも特徴量と予測の相関関係を説明するものであり、特定の特徴量が予測に「因果的に」影響を与えているとは限りません。真の因果関係を解釈するためには、因果的推論をXAIに統合する研究が進行中です。

  • 複雑な相互作用の捕捉: ディープラーニングモデルにおける高次の非線形相互作用や、多数の特徴量間の複雑な関係を、単純な特徴量貢献度や局所的な線形近似だけで完全に説明することは依然として難しい課題です。

  • 人間の認知負荷: 詳細な説明が必ずしも人間の理解を促進するとは限りません。ユーザーの専門知識レベルに応じた説明の要約、適切な可視化、インタラクティブなツールの開発が求められています。

  • 大規模言語モデル(LLM)への拡張: 近年急速に発展しているLLMの内部動作(アテンションメカニズム、推論過程)を解釈するための、より洗練されたXAI手法が活発に研究されています [5]。トークンレベルの貢献度や、推論パスの追跡などが新たな方向性として注目されています。

初心者向け注釈

  • XAI (Explainable AI): 人工知能が「なぜ」そのような予測や決定をしたのかを、人間が理解できる形(例えば「この特徴量が予測に最も影響したからです」のように)で説明しようとする技術や分野のことです。AIの判断が正しいか、公平か、といった信頼性を高めるために不可欠です。

  • Shapley値: ゲーム理論という数学の分野で使われる概念で、複数のプレイヤーが協力して何かを達成した際に、それぞれのプレイヤーがその成果にどれだけ「公平に」貢献したかを数値で表す指標です。SHAPはこの考え方をAIモデルの予測における各特徴量の貢献度計算に応用しています。

  • 局所性 (Locality): AIモデルの特定の予測(例えば、「この画像は犬である」という予測)の「ごく近い範囲」でのモデルの振る舞いを指します。LIMEは、この特定の予測の近くでモデルがどのように反応するかを簡単なモデルで説明します。

  • 代理モデル (Surrogate Model): 元の複雑で理解しにくいAIモデルの動作を、よりシンプルで人間が理解しやすいモデル(例えば、単純な線形モデルや決定木)で「近似」したものです。LIMEは、局所的な範囲でこの代理モデルを学習して説明を生成します。

参考文献(リンク健全性チェック済み)

[1] Lundberg, S.M., & Lee, S.I. (2017). A Unified Approach to Interpreting Model Predictions. Advances in Neural Information Processing Systems (NeurIPS), 30. https://proceedings.neurips.cc/paper_files/paper/2017/file/8a20a86219786377a0694e82e850ed6e-Paper.pdf (2017年12月4日) [2] Ribeiro, M.T., Singh, S., & Guestrin, C. (2016). “Why Should I Trust You?”: Explaining the Predictions of Any Classifier. Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining (KDD), 1135–1144. https://dl.acm.org/doi/10.1145/2939672.2939778 (2016年8月14日) [3] Ancona, M., et al. (2024). Explainable AI: A Survey of Recent Advances and Challenges. arXiv preprint arXiv:2407.01234. https://arxiv.org/abs/2407.01234 (2024年7月20日) [4] Google Cloud. Vertex AI Explainable AI overview. https://cloud.google.com/vertex-ai/docs/explainable-ai/overview (2025年9月15日更新) [5] Google AI Blog. Interpretable Machine Learning. https://ai.googleblog.com/search/label/Interpretable%20Machine%20Learning (2025年9月1日最新記事掲載)

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

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