説明できないモデルは、精度が高くても使われない
退職リスクの上位者リストを人事チームに出したとき、返ってきた最初の質問は精度の話ではありませんでした。 「なぜこの人がリスク高と出たんですか」です。
これに答えられないと、リストは使われません。「モデルがそう言っているので」では、 面談を設定する側が動けない。何を話題にすればいいのか分からないからです。 予測を業務に載せるうえで、解釈は精度と同じくらい重要でした。
この章では、モデル全体で何が効いているかを見る大域的解釈と、 個人ごとの根拠を出す局所的解釈の両方を扱います。あわせて、 出せてしまう情報をどこまで誰に見せるかという運用の線引きも書きます。 技術的にできることと、人事としてやっていいことが一致しない場面が出てくるので。
まずは大域的に見ます。LightGBMやランダムフォレストなら変数重要度がそのまま取れますし、
tidymodels のワークフローからは vip で引き出せます。
library(tidymodels) library(vip) # ワークフローから重要度を取り出す final_fit |> extract_fit_parsnip() |> vip(num_features = 10) # 数値で欲しい場合 final_fit |> extract_fit_parsnip() |> vi() |> arrange(desc(Importance))
実際の退職予測で出た上位はこうでした。
1. supervisor_diff1 上司スコアの前年差分 28% 2. job_fit_diff1 職務適性スコアの前年差分 22% 3. satisfaction_diff2 満足度の2年前差分 18% 4. spi_type 適性検査のタイプ分類 14% 5. eval_raw_scaled 評価粗点の標準化値 11%
上位3つがすべて差分である点が結果として重要でした。 エンゲージメントサーベイの絶対値ではなく、同じ人の前年からの変化が効いていた。 回答スタイルの個人差が絶対値に乗ってしまうので、差分を取ることでそれが落ちたのだと考えています。
そして「上司スコアの急落がいちばん退職と連動している」という結果は、経営層への説明で かなり腹落ちしてもらえました。理由は精度ではなく、打ち手が想像できる変数だったからだと思います。 「勤続年数が効いています」では誰も動けませんが、「上司との関係が急に悪化した人が危ない」なら、 次に何をするかの議論が始まります。
モデルを作る側は精度で選びたくなりますが、使う側は「介入できるか」で見ています。 同程度の精度なら、操作可能な変数が上位に来るモデルのほうが実際には価値が高い。 変数選択の段階でこれを意識しておくと、あとの説明がずいぶん楽になります。
便利な指標ですが、扱いには注意が要ります。実際に踏んだものを3つ挙げます。
LightGBMの重要度には gain(分岐による損失の減少量)と split(分岐に使われた回数)があり、 どちらを見るかで順位が入れ替わります。カテゴリ数の多い変数は split が大きく出やすい。 報告するときは、どの方法で出した数字かを明記してください。
これが差分変数で顕著でした。上司スコアの差分と職務適性スコアの差分は連動しやすく、 木が片方を選ぶともう片方の重要度が下がります。 本当は同じくらい効いているのに、片方だけが目立つ。 重要度が低い=関係がない、ではありません。
いちばん誤解されるところです。「上司スコアの低下が退職を引き起こす」とは言えません。 辞めると決めた人が上司への評価を下げている、という逆向きの流れも十分あり得ます。 施策の根拠として使うときは、この点を先に断ったうえで話したほうが安全です。
モデルに依存しない見方として、Permutation Importance も併せて確認します。 値をシャッフルしたときに性能がどれだけ落ちるかで測るので、算出方法の癖が入りにくい。
library(DALEXtra) explainer <- explain_tidymodels( final_fit, data = train_x, y = as.numeric(train_y == "退職"), label = "turnover_model" ) # Permutation Importance model_parts(explainer, loss_function = loss_one_minus_auc) |> plot()
重要度は「何が効くか」までしか教えてくれません。 現場から次に来るのは「どのくらい下がったら声をかけるべきか」という質問です。 ここは部分依存プロット(PDP)や累積局所効果(ALE)の出番になります。
# 上司スコアの差分と退職確率の関係 model_profile(explainer, variables = "supervisor_diff1") |> plot() # 相関の強い変数が多いときは ALE のほうが素直に読める model_profile(explainer, variables = "supervisor_diff1", type = "accumulated") |> plot()
曲線が急に立ち上がる位置が見えると、閾値の議論が具体的になります。 「1段階下がった程度なら様子見、2段階なら面談」といった運用ルールに落とせる形です。 第18章で書いた確率の閾値とは別に、変数側にも実務的な線引きが要るということでした。
なお、変数どうしの相関が強い場合、PDPは実際には起こらない組み合わせを平均に含めてしまいます。 差分変数を大量に入れているモデルではALEを優先したほうが読み違えが減ります。
「なぜこの人が」に直接答えるなら局所的解釈です。 SHAPやBreak Downを使えば、1人の予測確率に対して各変数がどれだけ寄与したかを分解できます。
target <- test_x |> slice(1) # Break Down:予測をどう積み上げたか predict_parts(explainer, new_observation = target) |> plot() # SHAP:順序依存を減らした寄与度 predict_parts(explainer, new_observation = target, type = "shap", B = 25) |> plot()
出力はこういう形になります。
予測確率 0.73(ベースライン 0.08) supervisor_diff1 = -2 → +0.31 job_fit_diff1 = -1 → +0.18 eval_raw_scaled = -0.8 → +0.09 tenure_years = 6 → +0.05 grade = G3 → +0.02
これで「上司スコアが2段階下がったことが最も効いています」と説明できます。 技術的には解決です。問題はこの先でした。
SHAPまで出すと、特定の個人について「この人が辞めそうな理由」を数値で語れてしまいます。 これは想像以上に強い情報です。扱いを間違えると、モデルの精度とは関係のないところで運用が壊れます。
「あなたのメンバーのAさんは退職確率73%です」という伝え方は避けました。 本人が知らないところで付いた数字が、上司との関係に影響します。 面談の場に無意識のバイアスが持ち込まれ、結果として本当に退職を早めることもあり得ます。
実際に採ったのは、スコアは人事が保持し、アクションの形に変換して渡す設計です。 マネージャーに伝えるのは「このメンバーと近いうちに1on1の機会を作ってください」まで。 数字も、その根拠となった変数も渡しません。この一段階を挟むかどうかで、 現場の受け入れられ方がまったく違いました。
解釈手法の使い分けとしては、こう整理しています。
サーベイの案内文で「個人が特定される形では利用しません」と伝えているなら、 この線引きは約束の一部です。第22章で自由記述について書いたことと、考え方は同じです。
LightGBMは精度が出ますが、なぜその予測になったのかを説明するのに一手間かかります。 ロジスティック回帰なら係数がそのまま「この変数が1増えるとオッズが何倍」という形で読めるので、 説明責任の面では圧倒的に楽です。
実務では、まずロジスティック回帰で動くものを作り、精度が足りないと判断してから LightGBMに移るのが現実的だと思っています。最初から複雑なモデルを組むと、 説明を求められたときに手が止まります。
人事の意思決定に使う以上、説明できないモデルは、精度が高くても使われない。 これは第18章の評価指標の話と同じ結論に行き着きます。 数字を良くすることと、業務に載ることは別の問題です。
どの変数が効いてどれが効かなかったか、なぜ差分変数に切り替えたのか、 ロジスティック回帰からLightGBMに移した判断基準まで含めた記録は、noteにまとめています。
【実務公開】退職予測モデルを作ったら最初に「罠」に落ちた話|ES差分×LightGBMで精度92%に至るまで(有料記事)
※ 当サイトはAmazonアソシエイトプログラムに参加しています