金融リスク管理における特徴量選択の実践:ランダムフォレストとRFEの活用

金融リスク管理における特徴量選択の重要性

金融リスク管理の現場では、ユーザーの行動ログ、決済履歴、外部信用情報など、膨大な次元の特徴量を扱います。しかし、これらの中にはノイズや冗余な情報が多く含まれています。特に金融ドメインでは、モデルの予測精度だけでなく「説明可能性(Explainability)」が強く求められます。規制当局への対応や審査プロセスの透明性を確保するため、どの特徴量がリスク判断に寄与したかを明確にする必要があります。

実務で頻繁に遭遇する金融データの特性には、以下のものがあります。

  • 高疎性(High Sparsity):アプリの操作ログなど、値のほとんどがゼロである。
  • 多重共線性(Multicollinearity):直近1ヶ月と3ヶ月の照会回数など、特徴量間に強い相関がある。
  • 時間的変動:キャンペーン期間や大型連休前後で行動パターンが変化する。
import pandas as pd

# 金融リスク管理用特徴量行列の例
credit_profile = pd.DataFrame({
    'inquiry_30d': [3, 0, 10, 2],       # 直近30日の信用照会件数
    'inquiry_90d': [10, 2, 25, 5],      # 直近90日の信用照会件数
    'avg_repayment': [50000, 20000, 150000, 30000], # 平均返済額
    'overdue_count': [0, 0, 2, 0]       # 過去の延滞回数
})

ランダムフォレストによる特徴量の重要度算出

ランダムフォレストの feature_importances_ は、埋め込み型(Embedded)手法として非常に強力です。フィルタリング法とは異なり、モデルの学習過程で特徴量の寄与度を評価するため、特徴量間の相互作用を一定程度考慮できます。

重要度算出のメカニズム

各決定木において、ある特徴量が分割に使用された際の「不純度(ジニ係数やエントロピー)」の減少量を集計し、森林全体で平均化したものが重要度となります。

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt

# ダミーデータの生成
X_data, y_label = make_classification(
    n_samples=2000, n_features=15, 
    n_informative=8, n_redundant=3, 
    random_state=7
)

# モデルの学習
model_rf = RandomForestClassifier(n_estimators=150, random_state=42)
model_rf.fit(X_data, y_label)

# 重要度の取得と可視化
feat_importance = model_rf.feature_importances_
indices = feat_importance.argsort()[::-1]

plt.figure(figsize=(10, 6))
plt.title("Random Forest Feature Importance")
plt.bar(range(X_data.shape[1]), feat_importance[indices])
plt.xticks(range(X_data.shape[1]), indices)
plt.show()

SelectFromModelによる動的閾値の設定

特徴量をいくつ残すべきかは、モデルの性能と複雑性のトレードオフです。SelectFromModel を用いることで、平均値や特定の値以上の重要度を持つ特徴量を自動抽出できます。

from sklearn.feature_selection import SelectFromModel
import numpy as np
from sklearn.model_selection import cross_val_score

# 閾値を段階的に変えて最適なポイントを探索
threshold_candidates = np.linspace(0.01, feat_importance.max(), 10)
validation_scores = []

for t in threshold_candidates:
    selector = SelectFromModel(model_rf, threshold=t, prefit=True)
    X_reduced = selector.transform(X_data)
    score = cross_val_score(model_rf, X_reduced, y_label, cv=3).mean()
    validation_scores.append(score)

best_t = threshold_candidates[np.argmax(validation_scores)]
print(f"Optimal Threshold: {best_t}")

再帰的特徴消去(RFE)の実践

RFEはラッパー型(Wrapper)手法の一種で、最も寄与度の低い特徴量を一つずつ削除していくプロセスを繰り返します。金融ドメインでは、特徴量のサブセットが持つ頑健性を確認するために有効です。

RFECV:最適な特徴量数の自動特定

固定の数を指定する代わりに、クロスバリデーションを用いて最適な特徴量数を決定する RFECV が実務では多用されます。

from sklearn.feature_selection import RFECV
from sklearn.model_selection import StratifiedKFold

# RFECVの設定
cv_strategy = StratifiedKFold(5)
rfecv_selector = RFECV(
    estimator=RandomForestClassifier(n_estimators=50),
    step=1,
    cv=cv_strategy,
    scoring='roc_auc',
    min_features_to_select=5
)
rfecv_selector.fit(X_data, y_label)

print(f"最適な特徴量数: {rfecv_selector.n_features_}")
print(f"特徴量ランキング: {rfecv_selector.ranking_}")

産業レベルの特徴量選択パイプライン

実際の運用システムでは、複数のフィルタを組み合わせた多段階のパイプラインを構築します。

  1. 前処理フィルタ:分散が極端に低いものや、欠損率が高いものを除去。
  2. 相関フィルタ:相関係数が0.9以上のペアの一方を削除。
  3. 精査フェーズ:RFECVやランダムフォレスト重要度による絞り込み。
from sklearn.pipeline import Pipeline
from sklearn.feature_selection import VarianceThreshold
from sklearn.preprocessing import StandardScaler

# 特徴量選択パイプラインの構築
risk_pipeline = Pipeline([
    ('low_variance_filter', VarianceThreshold(threshold=0.01)),
    ('std_scaler', StandardScaler()),
    ('rfe_select', RFECV(estimator=RandomForestClassifier(n_estimators=50), step=2, cv=3)),
    ('final_clf', RandomForestClassifier(n_estimators=200))
])

risk_pipeline.fit(X_data, y_label)

運用におけるモニタリング

特徴量を選択してモデルをデプロイした後も、重要度の「ドリフト(変遷)」を監視する必要があります。例えば、特定の外部データの仕様変更や市場環境の変化により、主要な特徴量の寄与度が急落することがあります。

def check_importance_drift(prev_imp_dict, curr_imp_dict, tolerance=0.25):
    """
    特徴量重要度の変化を検知する
    """
    drift_detected = []
    for feat, val in curr_imp_dict.items():
        if feat in prev_imp_dict:
            change_ratio = abs(val - prev_imp_dict[feat]) / prev_imp_dict[feat]
            if change_ratio > tolerance:
                drift_detected.append((feat, change_ratio))
    return drift_detected

タグ: Scikit-learn RandomForest FeatureSelection MachineLearning DataScience

9月9日 09:12 投稿