特徴量重要度は信用していいのか:RandomForestは、無関係なランダム列を「最重要」と答える

目次

はじめに

RandomForestには、feature_importances_という、特徴量の重要度を返す機能があります。「どの列が予測に効いているか」を手軽に調べられるため、よく使われます。では、この重要度は、そのまま信用してもいいのでしょうか。

この記事では、予測に無関係なランダム列を混ぜて、次の3点を確かめます。

  • 標準の重要度が、無関係な列を最重要と答えること
  • その原因が、重要度の計算方法のどこにあるのか
  • 信用できる重要度の調べ方

実験の設定

1000行のデータを作ります。ラベルが1になる確率は、次の2つの列が大きいほど高くなります。

  • binary:0か1の二値の列(効く)
  • level5:0~4の5段階の列(効く)

また、ラベルと無関係な列として、random_idを加えます。 0~1の乱数で、全行で値が違います。

import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
from sklearn.model_selection import train_test_split

rng = np.random.default_rng(0)
n = 1000
b = rng.integers(0, 2, n)                 # 効く二値の列
c = rng.integers(0, 5, n)                 # 効く5段階の列
p = 0.15 + 0.3 * b + 0.08 * c             # ラベルが1になる確率
y = (rng.uniform(size=n) < p).astype(int)
rnd = rng.uniform(size=n)                 # 無関係なID風の列

X = np.column_stack([b, c, rnd])
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0)

rf = RandomForestClassifier(n_estimators=300, random_state=0).fit(Xtr, ytr)

print(rf.feature_importances_)            # 標準の重要度
pi = permutation_importance(rf, Xte, yte, n_repeats=20, random_state=0)
print(pi.importances_mean)                # permutation importance

結果:無関係な列が、重要度の8割を占める

データの乱数を変えて、20回繰り返した平均です。

列実際の関係標準の重要度permutation importance
binary効く0.092+0.034
level5効く0.094+0.012
random_id無関係0.814-0.017

標準の重要度では、無関係なrandom_idが重要度の約8割を占め、20回すべてで1位でした。効いている2つの列は、合わせても2割に届きません。

一方、permutation importanceでは、random_idは20回のうち1位になった回がなく、平均は負の値になりました。効く列の方が、高い値になっています。

原因:訓練データで計算しているから

標準の重要度は、木が分割するたびに減った「不純度」(ラベルのばらつき)を、訓練データで合計したものです。

値の種類が多い列は、分割の候補が多くなります。random_idは全行で値が違うため、たまたまラベルをうまく切り分けられる分割点を、いくらでも見つけられます。木は深く成長するので、この偶然の分割も、そのまま学習します。この実験では、訓練データでの正解率が1.0になりました。

つまり、標準の重要度は、「訓練データにどれだけ当てはまったか」を測っています。予測に本当に効くかは測れていません。

この現象は、値の種類が多い列と、深く成長した木でおきやすいです。min_samples_leafを大きくするなどで軽くなる場合もあります。

対処法:テストデータで、シャッフルして測る

permutation importanceは、テストデータのある列の値をシャッフルして、予測の精度がどれだけ下がるかを測ります。無関係な列は、シャッフルしても精度が変わらないので、重要度がほぼ0になります。

もう一つ、無関係な乱数の列を1本混ぜておく方法があります。その列の重要度より低い特徴量は、信用できません。今回の実験では、permutation importanceで、効く2つの列がrandom_idより上に並びました。

まとめ

  • 標準の重要度は、無関係なランダム列を、重要度の約8割、20回すべてで1位と答えた
  • 原因は、訓練データで計算しているため。値の種類が多い列は偶然の分割で得をする
  • permutation importanceでは、random_idが1位になる回はなかった。テストデータで測る方が、効く列を正しく並べられる
CTA
  • URLをコピーしました!
  • URLをコピーしました!
この記事を書いた人
目次