はじめに
データ分析コンペで構造化データを扱うとき、特徴量選択の判断にFeature Importanceを使うことは多いと思います。重要度が低い特徴量を削って過学習を抑えたい、あるいは単純にモデルをシンプルにしたい、そういった場面でFeature Importanceのグラフを眺めながら「この辺は切っていいか」と判断した経験がある方も多いのではないでしょうか。
ところが、Split・Gain・SHAP・Permutationなど複数の手法を試してみると値がまったく違う、重要度が低かった特徴量を削除したら精度がかなり下がった、といった経験をしたことはないでしょうか。「どの手法を信じればいいのか」「そもそもFeature Importanceで特徴量を選んでいいのか」という疑問を持ったことがある方もいると思います。
本記事ではその背景を掘り下げます。4つの手法それぞれの仕組みを見ていくことで、なぜ同じモデル・同じデータでも値が異なるのか、そしてFeature Importanceが「残すべき特徴量のランキング」として機能しない理由を整理していきます。
4つのFeature Importance
一口に特徴量重要度といっても手法は多くあり、それぞれ「何を・どのデータを使って測るか」が異なります。本記事では勾配ブースティング系で頻用されるSplit、Gain、SHAP、Permutation Importanceの4つに注目し、それぞれどのように重要度を求めているのか、なぜ同じモデルに対して計算しても値が大きく変わるのかを見ていきます。
Split
LightGBMにおける呼称で、XGBoostではWeightと呼ばれます。全ツリーを通じて、ある特徴量が分岐点として使われた回数の合計を重要度とします。
importance_split = model.booster_.feature_importance(importance_type='split')
仕組みはシンプルで、100本のツリーがあり特徴量Aが合計350回分岐に使われていれば、AのSplitは350になります。計算はモデル内部のツリー構造から行われるため、学習後であれば追加のデータや計算は不要です。
ただし、この「使われた回数」という測り方には注意が必要です。年齢や売上金額のような連続値の特徴量は取りうる値が多く、ツリーが分岐点を設ける余地が大きいため、自然と回数が増えやすくなります。一方で「購入有無」のような0/1のバイナリ特徴量は分岐点が限られるため、どれだけ予測に貢献していても回数は伸びにくいです。つまりSplitの値はデータの性質に引っ張られやすく、重要性の高さよりもカーディナリティ(=特徴量が取りうる値の種類の数)の高さを反映してしまうことがあります。
4つの中では最も簡易的な指標で、あくまでモデルがどの特徴量を頻繁に参照したかの目安として捉えるのが無難です。
Gain
特徴量が分岐に使われたとき、その分岐によって不純度がどれだけ減少したかの平均を重要度とします。 Splitが「何回使われたか」を見るのに対し、Gainは「使われたときにどれだけ貢献したか」を見ます。
importance_gain = model.booster_.feature_importance(importance_type='gain')
決定木は各分岐でデータをより純粋なグループに分けようとします。たとえば「年収500万円以上かどうか」で分岐したとき、その前後でクラスの混じり具合(不純度)がどれだけ改善したかを測るのがGainです。使用回数に関係なく「実際に役立った分岐かどうか」を評価するため、Splitよりも信頼性が高いとされています。
ただし、Gainにも弱点があります。互いに相関した特徴量が複数ある場合、ツリーの分岐では最初に選ばれた特徴量がそのノードの情報をほぼ吸収してしまいます。
上の図の例で言えば、面積と部屋数はどちらも家賃に関係していますが、広い部屋は部屋数も多い傾向があるため両者は相関しています。ツリーのルートノードで面積が先に選ばれると、家賃の分散をほぼ説明してしまいます。その後に部屋数が使われる頃には「面積で説明し切れなかった残り」しか担当できないため、Gainが低く出てしまいます。
ただ、面積と部屋数のどちらが先に選ばれるかはツリーの学習過程に依存しており、必ずしも面積が先とは限りません。場合によっては部屋数が先に選ばれてGainが高くなることもあり、どちらが上位に来るかは半ば恣意的です。Gainの順位は特徴量の本質的な重要性ではなく、学習の過程でどちらが先に選ばれたかに左右される可能性があります。
また、Split同様に学習データ上のツリー構造から計算されるため、過学習した特徴量の重要度が高く出る場合がある点にも注意が必要です。
SHAP
ゲーム理論のShapley値に基づく手法です。特徴量のすべての組み合わせに対して「この特徴量が加わることで予測値がどれだけ変化したか」を計算し、その平均を重要度とします。
具体的に面積・部屋数・築年数の3つの特徴量があるとします。面積のSHAP値を求める場合、まず「面積だけ使ったとき」「部屋数と面積を使ったとき」「築年数と面積を使ったとき」「3つ全て使ったとき」のように、面積を加える前後で予測値がどれだけ変わるかをすべての組み合わせで計算し、それを平均します。特定の特徴量が先に選ばれることで有利・不利が生じるSplit・Gainとは異なり、全ての順序を平均することで公平に貢献度を帰属させる点がSHAPの特徴です。
勾配ブースティングモデルに対してはTree SHAPと呼ばれるアルゴリズムが使われます。本来Shapley値の計算は特徴量数に対して指数的にコストが増えますが、Tree SHAPはツリー構造を利用して計算を効率化しており、LightGBMやXGBoostにも現実的な時間で適用できます。
import shap
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_val)
if isinstance(shap_values, list):
shap_values = shap_values[1] # 二値分類の場合、正例クラスのSHAP値
shap_importance = np.abs(shap_values).mean(axis=0)
サンプルごとに計算される点もSplit・Gainとの大きな違いです。「このサンプルの予測に各特徴量がどう影響したか」を個別に把握できるため、モデル全体の傾向を見るだけでなく、特定の予測結果を説明する用途にも使われます。
一方で、相関した特徴量が存在する場合は注意が必要です。面積と部屋数のように似た情報を持つ特徴量が複数あると、全ての組み合わせを平均する過程で両者に貢献度が分散します。結果としてどちらも「そこそこ重要」な値に落ち着き、Split・Gainとは異なる順位になることがあります。
Permutation Importance
バリデーションデータ上で、ある特徴量の値をランダムにシャッフルして予測精度がどれだけ低下するかを重要度とします。 特徴量をシャッフルすることでその特徴量と目的変数の関係を意図的に壊し、精度への影響を測るという発想です。
手順はシンプルです。まずバリデーションデータで元の精度(AUCなど)を記録します。次に面積の列だけをランダムに並び替えて予測し直し、精度の低下量を計算します。これを全ての特徴量に対して繰り返し、低下量が大きいほど重要度が高いと判断します。1回のシャッフルだと乱数の影響を受けるため、複数回繰り返して平均を取るのが一般的です。
from sklearn.inspection import permutation_importance
result = permutation_importance(
model, X_val, y_val,
n_repeats=20, random_state=42, scoring='roc_auc'
)
perm_importance = result.importances_mean
Split・Gainがモデル内部の学習データから計算されるのに対し、Permutation Importanceはバリデーションデータでのモデルのふるまいを評価します。そのため学習データに過学習した特徴量の重要度が高く出にくく、汎化性能の観点に近い評価が得られます。
ただし、相関した特徴量が存在する場合は過小評価が起きやすいです。 面積をシャッフルしてもモデルは部屋数で補えるため、精度の低下が小さくなります。逆に言えば、Permutation Importanceで重要度が高い特徴量は、そのモデル・そのバリデーションデータ上では、他の特徴量で代替しにくい情報を持っている可能性が高い、と解釈することもできます。
なぜ4つで値が異なるのか
測っているものが根本的に違う
4つの指標を「何を・どのデータで測るか」で整理すると以下のようになります。
| 指標 | 何を測るか | 使うデータ |
|---|---|---|
| Split | 分岐に使われた回数 | 学習データ(モデル内部) |
| Gain | 分岐時の不純度減少量の平均 | 学習データ(モデル内部) |
| SHAP | 全ての特徴量の組み合わせにおける予測への貢献の平均 | 任意(通常バリデーション) |
| Permutation | シャッフル時の精度低下 | バリデーションデータ |
測っているものが異なるのですから、値が違うのはある意味当然です。ただ厄介なのは、同じモデル・同じデータを使っているにもかかわらず、手法によって特徴量の順位が逆転することがある点です。相関した特徴量が存在する場合がその典型例です。
相関特徴量があると順位が逆転する(実験)
以下のデータを用意します。
- 特徴量A:目的変数に強く影響(係数2)
- 特徴量B:Aと強相関(r≈0.995)
- 特徴量C:目的変数に中程度の影響(係数1)
- 特徴量D:ノイズ
import numpy as np
import pandas as pd
import lightgbm as lgb
import shap
from sklearn.inspection import permutation_importance
from sklearn.model_selection import train_test_split
np.random.seed(42)
n = 2000
feature_a = np.random.randn(n)
feature_b = feature_a + np.random.randn(n) * 0.1 # Aと強相関(r≈0.995)
feature_c = np.random.randn(n)
feature_d = np.random.randn(n)
y = (2 * feature_a + feature_c + np.random.randn(n) * 0.5 > 0).astype(int)
X = pd.DataFrame({'A': feature_a, 'B': feature_b, 'C': feature_c, 'D': feature_d})
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.3, random_state=42)
model = lgb.LGBMClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
各指標の順位を比較します。
split_imp = model.booster_.feature_importance(importance_type='split')
gain_imp = model.booster_.feature_importance(importance_type='gain')
explainer = shap.TreeExplainer(model)
shap_vals = explainer.shap_values(X_val)
if isinstance(shap_vals, list):
shap_vals = shap_vals[1]
shap_imp = np.abs(shap_vals).mean(axis=0)
perm = permutation_importance(
model, X_val, y_val,
n_repeats=20, random_state=42, scoring='roc_auc'
)
perm_imp = perm.importances_mean
features = X.columns.tolist()
df_rank = pd.DataFrame({
'Split順位': pd.Series(split_imp, index=features).rank(ascending=False).astype(int),
'Gain順位': pd.Series(gain_imp, index=features).rank(ascending=False).astype(int),
'SHAP順位': pd.Series(shap_imp, index=features).rank(ascending=False).astype(int),
'Permutation順位': pd.Series(perm_imp, index=features).rank(ascending=False).astype(int),
})
print(df_rank)
実行結果は乱数シードやLightGBMのバージョンによって変わる場合がありますが、本記事の環境では以下のようになりました。
| 特徴量 | Split順位 | Gain順位 | SHAP順位 | Permutation順位 |
|---|---|---|---|---|
| A | 2位 | 3位 | 2位 | 3位 |
| B(Aと強相関) | 3位 | 1位 | 1位 | 1位 |
| C | 1位 | 2位 | 3位 | 2位 |
| D | 4位 | 4位 | 4位 | 4位 |
SplitはCが1位になっています。AとBはr≈0.995という強い相関があるため、ツリーによってAが使われたりBが使われたりと分岐が分散します。結果としてAもBも個別の分岐回数が伸びにくく、AともBとも無相関なCが相対的に分岐回数を積み上げやすくなっていると考えられます。一方、Gain・SHAP・PermutationではBが一貫して1位で、AはGainとPermutationで3位、SHAPで2位という結果です。
ここで「AはBより重要度が低いのか?」というと、そんなことはありません。AとBはr≈0.995という非常に強い相関があり、ほぼ同じ情報を持っています。モデルの学習過程でたまたまBが先に選ばれただけで、AがなくてもBで代替できるし、BがなくてもAで代替できます。 試しにBを除いてモデルを学習し直せば、AがGain・SHAP・Permutationで1位になります。
つまりAの重要度が低いのではなく、AとBが互いに代替可能なために「どちらが上に来るかが学習の偶然に左右される」状態になっているということです。重要度の順位だけを見てAを「重要でない特徴量」と判断し削除してしまうと、実際には予測に大きく貢献している特徴量を失う可能性があります。
なぜ特徴量選択のランキングとは言えないのか
ここまで見てきたように、特徴量重要度は手法によって観点が異なり、どれが絶対的に正しいとは言い切れません。では仮に4つの手法でほぼ同じ順位が得られた場合、その順位を特徴量選択のランキングとみなして重要度が低い特徴量を削除しても問題ないのでしょうか。実はそう簡単ではありません。4つの指標はいずれも「今の学習済みモデルがその特徴量にどれだけ頼っているか」を測っているに過ぎないからです。
全て「学習済みモデルへの依存度」である
モデルを学習した後に「このモデルはどの特徴量を使っているか」を後から診断するイメージです。
実験の結果を振り返ると、Gain・SHAP・Permutationでは一貫してBが1位でした。これだけ見るとBは非常に重要な特徴量に見えます。しかし実際にBを削除して再学習すると、モデルはAを使うよう構造を変えるため精度への影響はほとんどありません。4つの指標が示していたのは「今のモデルがBに頼っている」という事実であって、「Bが予測に不可欠かどうか」ではなかったわけです。
重要度はあくまで今のモデルの状態を切り取ったものであり、削除後にどうなるかまでは教えてくれません。
削除して再学習した結果とは別問題
重要度が高い特徴量を削除しても問題ないケースがある一方で、重要度が低い特徴量を削除したら精度が大きく落ちるケースもあります。
たとえば購買予測モデルで「最終ログインからの経過日数」という特徴量があったとします。多くのユーザーではログイン間隔に大きな差がなく、また他の行動特徴量でもある程度代替できる場合、この特徴量の全体的な重要度は低く出ることがあります。しかし、長期間ログインしていないユーザーに限定すると、この特徴量が離脱や購買停止の予兆を捉える重要なシグナルになっている場合があります。全体の重要度だけを見て削除すると、このような特定セグメントの予測精度が大きく落ちる可能性があります。
重要度の高低と「削除してよいかどうか」は直結していません。 特徴量の取捨選択を判断するには、以下のサイクルを踏む必要があります。
- 重要度を参考に削除候補に目星をつける
- 削除して再学習する
- バリデーション精度(CV)で評価する
重要度は「どの特徴量を削除候補として調べるか」の出発点として使うものであり、それだけで削除を決める根拠にはなりません。
まとめ
本記事で見てきたことを整理します。
Split・Gain・SHAP・Permutation Importanceはそれぞれ異なる観点で重要度を測っており、どれが正しいと断言できるものではありません。手法によって順位が変わるのはその性質の違いによるものであり、「どの手法を使えば正確な重要度がわかるか」という問いへの答えは一つではありません。
また、重要度が高い特徴量が必ずしも不可欠というわけではなく、重要度が低い特徴量が削除してよいとも限りません。重要度はあくまで今のモデルの状態を診断するものであり、削除して再学習した後の精度とは別の話です。
より正確な重要度を把握したいなら、多重共線性を意識することが重要です。勾配ブースティング系のモデルは多重共線性があっても予測精度への影響は小さいですが、実験で示したように相関した特徴量の間で重要度が分散したり、どちらが選ばれるかが学習の偶然に左右されます。解釈の信頼性という観点では無視できない問題です。
とはいえ、まったく指針なしに特徴量を選ぶよりも、重要度をある程度の目安として使うことには意味があります。ただし、特定の手法の順位だけを根拠に特徴量の取捨選択を決めてしまうのは避けた方が無難です。重要度は「何を調べるかの出発点」として使い、最終的な判断は削除・再学習・CV評価のサイクルで行うのがよいでしょう。

