機械学習モデルは「ブラックボックス」と呼ばれることが多く、なぜその予測をしたのかが分かりにくいという課題があります。部分依存プロット(Partial Dependence Plot, PDP)は、特定の特徴量がモデルの予測にどのような影響を与えているかを可視化するための手法です。「年齢が上がると予測金額はどう変わるか?」「広告費を増やすと売上予測はどう変化するか?」といった問いに、視覚的に答えを提供します。この記事では、PDP の計算原理から実践的な活用方法まで、詳しく解説します。
部分依存プロット(PDP)とは何か
部分依存プロット(PDP)は、2001 年に Jerome Friedman が「Greedy Function Approximation」の論文で提案した手法です。ある特徴量の値を変化させたとき、モデルの予測値がどのように変化するかを「他の特徴量の影響を平均化して」表示するグラフです。つまり、注目する特徴量以外のすべての特徴量の効果を打ち消し、注目する特徴量のみの「限界効果(marginal effect)」を可視化する手法です。
PDP の計算原理 — 限界効果をどう計算するか
PDP の計算は直感的です。注目する特徴量 x_s のある値 v について、データセットのすべてのサンプルの x_s を v に置き換え、残りの特徴量はそのままにしてモデルに予測させます。そのときの予測値の平均が、x_s = v に対する部分依存の値です。これを x_s の値域にわたって繰り返すことで、PDP のカーブが得られます。数式で表すと、部分依存関数は f_s(x_s) = E_c[f(x_s, x_c)] です。ここで x_c は注目する特徴量以外の特徴量、E_c は x_c に関する期待値(データセットの平均)を示します。
- 1
注目する特徴量のグリッド値を決定
分析対象の特徴量について、値域を等間隔または分位点でグリッド分割します。通常 20〜50 のグリッド点を使用します。グリッドが粗いと曲線が滑らかにならず、細かすぎると計算コストが増大します。
- 2
各グリッド値で予測を実行
各グリッド値について、データセットのすべてのサンプルの注目特徴量をそのグリッド値に置き換え、モデルで予測します。n 個のグリッド点 × N 個のサンプル = n × N 回の予測が必要です。
- 3
予測値の平均を計算
各グリッド値について、N 個の予測値の平均を計算します。これが部分依存の値です。グリッド値と部分依存値の対をプロットすることで、PDP が得られます。
from sklearn.inspection import PartialDependenceDisplay, partial_dependence
from sklearn.ensemble import GradientBoostingRegressor
import matplotlib.pyplot as plt
import numpy as np
# モデルの学習
model = GradientBoostingRegressor(n_estimators=200, random_state=42)
model.fit(X_train, y_train)
# 1D PDP の描画(上位3つの重要な特徴量)
features = ["square_feet", "num_rooms", "distance_to_station"]
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for i, feature in enumerate(features):
PartialDependenceDisplay.from_estimator(
model, X_train, [feature],
ax=axes[i], grid_resolution=50,
line_kw={"color": "#4A90D9", "linewidth": 2},
)
axes[i].set_title(f"PDP: {feature}")
plt.tight_layout()
plt.show()1D PDP — 単一特徴量の効果を可視化
1D PDP は最も基本的な形式で、横軸に注目する特徴量の値、縦軸にモデルの予測値(の限界効果)を表示します。PDP のカーブの形状から、特徴量と予測値の関係を読み取ることができます。右肩上がりの直線なら正の線形関係、S 字カーブなら飽和効果(ある値を超えると効果が頭打ちになる)、U 字型なら極端に低い値と高い値の両方で予測値が高くなる非線形関係です。
PDP の縦軸の値は「予測値そのもの」ではなく「予測値の変化分」として読むのが正しい解釈です。ベースライン(y 軸のゼロ付近)からの上下の振れ幅が、その特徴量の影響の大きさを示しています。
2D PDP — 2 つの特徴量の相互作用を可視化
2D PDP は、2 つの特徴量の値を同時に変化させたときの予測値の変化をヒートマップや等高線図で表示します。これにより、特徴量間の相互作用(interaction effect)を視覚的に確認できます。例えば、「面積」と「築年数」の 2D PDP を描画すると、「面積が大きくても築年数が古いと価格はそこまで上がらない」といった相互作用が見えてきます。1D PDP では見えない関係を発見できるのが 2D PDP の強みです。
# 2D PDP の描画
fig, ax = plt.subplots(figsize=(8, 6))
PartialDependenceDisplay.from_estimator(
model, X_train,
features=[("square_feet", "building_age")], # 2特徴量の組み合わせ
ax=ax,
kind="average",
)
ax.set_title("2D PDP: 面積 × 築年数")
plt.tight_layout()
plt.show()
# 部分依存値を数値で取得
result = partial_dependence(
model, X_train,
features=["square_feet"],
grid_resolution=50,
kind="average",
)
print(f"グリッド値: {result['grid_values'][0][:5]}")
print(f"部分依存値: {result['average'][0][:5]}")ICE プロット — 個別サンプルの振る舞いを確認
PDP は「平均」を表示するため、データ全体のトレンドは分かりますが、個別のサンプルがどのように振る舞っているかは見えません。ICE(Individual Conditional Expectation)プロットは、PDP の平均化する前のステップを可視化する手法です。各サンプルについて、注目する特徴量を変化させたときの予測値の変化を個別のラインとしてプロットします。ICE ラインがすべて同じ方向に向かっていれば、特徴量の効果は一様です。ICE ラインの向きが分かれている場合は、サブグループによって特徴量の効果が異なること(相互作用の存在)を示唆しています。
- 1
ICE プロットの解釈
ICE の各ラインは 1 つのサンプルに対応します。ラインが密集して同じ方向に動いていれば、特徴量の効果が全サンプルで一貫していることを意味します。ラインが交差したり、方向がバラバラな場合は、他の特徴量との相互作用がある証拠です。
- 2
Centered ICE(c-ICE)プロット
ICE ラインの開始点を 0 に揃えた変形版です。各サンプルの「変化量」に注目できるため、相互作用の有無がより明確になります。scikit-learn では kind='both' を指定すると、PDP と ICE を重ねて表示できます。
PDP と SHAP の違い — どちらを使うべきか
PDP と SHAP はどちらもモデルの解釈に使われますが、観点が異なります。PDP は「特徴量の値を変化させたときの予測値への平均的な影響」を可視化するのに対し、SHAP は「個別の予測に対する各特徴量の貢献度」を計算します。PDP は特徴量の効果の「形状」(線形、非線形、飽和など)を理解するのに適しており、SHAP は「この予測がなぜこの値になったのか」を説明するのに適しています。実務では、PDP で全体的なトレンドを把握し、SHAP で個別の予測を説明するという使い分けが効果的です。
- 1
PDP が適しているケース
特徴量とターゲットの全体的な関係を把握したいとき、ステークホルダーに「この特徴量を増やすと予測値はどう変わるか」を説明したいとき、特徴量間の相互作用を探索したいとき。
- 2
SHAP が適しているケース
個別の予測結果の根拠を説明したいとき(「なぜこの顧客は解約と予測されたのか」)、特徴量の重要度ランキングを算出したいとき、正と負の両方の貢献を同時に把握したいとき。
- 3
併用が効果的なケース
PDP で「年収が高いほど承認率が上がる」という全体トレンドを確認し、SHAP で「この申請者は年収が高いにもかかわらず否認された理由は信用スコアが低いため」と個別に説明する。
PDP には「特徴量の独立性」を仮定するという限界があります。相関が強い 2 つの特徴量(例:身長と体重)がある場合、PDP は「身長は高いが体重は軽い」といった現実にはありえない組み合わせを含む予測を平均してしまいます。この問題を緩和するには、ALE(Accumulated Local Effects)プロットの使用を検討してください。
PDP の形状パターンと解釈
PDP のカーブにはいくつかの典型的なパターンがあり、それぞれ異なるビジネスインサイトを示唆します。右肩上がりの直線パターンは、特徴量と予測値の線形な正の関係を示し、特徴量が 1 単位増えるごとに予測値が一定量増加します。S 字カーブは飽和効果を示し、ある閾値を超えると効果が頭打ちになります。U 字型は、特徴量の中間値で予測が最小化され、両端で高くなるパターンです。フラットなカーブは、その特徴量がモデルの予測にほとんど影響を与えていないことを示します。
PDP の限界と注意点
PDP は強力な解釈ツールですが、いくつかの限界があります。第一に、前述の特徴量の独立性の仮定です。相関の高い特徴量がある場合、PDP は現実にはありえないデータの組み合わせに基づいた予測を含むため、誤解を招く可能性があります。第二に、PDP は平均を表示するため、異なるサブグループで逆方向の効果がある場合(Simpson's paradox のような状況)、それらが相殺されて効果が小さく見えることがあります。ICE プロットを併用することで、この問題を部分的に緩和できます。第三に、計算コストの問題です。大規模データセットでは PDP の計算に時間がかかるため、サンプリングが必要になります。
# ICE プロットと PDP を重ねて表示
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# ICE + PDP(individual ラインと平均ライン)
PartialDependenceDisplay.from_estimator(
model, X_train, ["square_feet"],
ax=axes[0],
kind="both", # PDP + ICE を同時描画
subsample=100, # ICE ラインは 100 サンプルに制限
ice_lines_kw={"color": "#4A90D9", "alpha": 0.1, "linewidth": 0.5},
pd_line_kw={"color": "#E74C3C", "linewidth": 2},
)
axes[0].set_title("ICE + PDP: square_feet")
# Centered ICE で変化量を強調
PartialDependenceDisplay.from_estimator(
model, X_train, ["square_feet"],
ax=axes[1],
kind="both",
centered=True, # 開始点を 0 に揃える
subsample=100,
ice_lines_kw={"color": "#4A90D9", "alpha": 0.1, "linewidth": 0.5},
pd_line_kw={"color": "#E74C3C", "linewidth": 2},
)
axes[1].set_title("Centered ICE: square_feet")
plt.tight_layout()
plt.show()Qast の PDP 可視化機能
Qast では、学習済みモデルの解釈ツールとして PDP が統合されています。モデル詳細画面の「特徴量の影響」タブから、各特徴量の 1D PDP を対話的に確認できます。重要度の高い特徴量が自動的に上位に表示され、カーブの形状から「この特徴量はどのように予測に影響しているか」を直感的に理解できます。また、2 つの特徴量を選択して 2D PDP をヒートマップ形式で表示することも可能です。ICE プロットの表示もワンクリックで切り替えられるため、全体のトレンドと個別サンプルの振る舞いを素早く比較できます。
Qast の PDP は SHAP の特徴量重要度と組み合わせて使うことで、より深いモデル解釈が可能になります。SHAP で「この特徴量が重要」と分かったら、PDP で「どのように重要か」(線形に効くのか、閾値があるのか)を確認するのがベストプラクティスです。

