まとめ
- RuleFit は木ベースモデル(勾配ブースティングやランダムフォレスト等)から if-then ルールを抽出し、元の特徴量と併せて L1 正則化付き線形モデルとして学習します。
- ルールは相互作用や閾値を捉え、線形項は全体のトレンドを保持するため、疎な重みによって高い説明力と予測力のバランスを取れます。
max_rulesや木の深さで複雑さを制御し、交差検証で過学習とハイパーパラメータの妥当性を確認します。- 重要ルールを図表で可視化し、ビジネス用語へ翻訳することで意思決定者へ説明しやすくなります。
1. アイデア(数式つき) #
- ルール抽出: 木の葉へ至る経路を if-then ルールとして二値特徴 (r_j(x) \in {0,1}) に変換。
- 線形項の追加: 連続特徴をスケールした線形項 (z_k(x)) として残す。
- L1 正則化付き線形回帰:
$$ \hat{y}(x) = \beta_0 + \sum_j \beta_j r_j(x) + \sum_k \gamma_k z_k(x) $$
L1 正則化によって重要なルール・線形項のみが残り、モデルが疎になります。
2. 使用データセット(OpenML: house_sales) #
King County の住宅価格データ(OpenML data_id=42092)を数値列のみで利用します。
import japanize_matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
dataset = fetch_openml(data_id=42092, as_frame=True)
X = dataset.data.select_dtypes("number").copy()
y = dataset.target.astype(float)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
3. RuleFit を学習する #
Python 実装: christophM/rulefit
from rulefit import RuleFit
import warnings
warnings.simplefilter("ignore")
rf = RuleFit(max_rules=200, tree_random_state=27)
rf.fit(X_train.values, y_train.values, feature_names=list(X_train.columns))
pred_tr = rf.predict(X_train.values)
pred_te = rf.predict(X_test.values)
def report(y_true, y_pred, name):
rmse = mean_squared_error(y_true, y_pred, squared=False)
mae = mean_absolute_error(y_true, y_pred)
r2 = r2_score(y_true, y_pred)
print(f"{name:8s} RMSE={rmse:,.0f} MAE={mae:,.0f} R2={r2:.3f}")
report(y_train, pred_tr, "Train")
report(y_test, pred_te, "Test")
max_rules, 木の本数/深さ, (GBDT を使う場合の) learning_rate などで表現力を調整します。
4. 重要ルールの確認 #
rules = rf.get_rules()
rules = rules[rules.coef != 0].sort_values(by="importance", ascending=False)
rules.head(10)
- rule: if-then 条件(
type=linearは線形項) - coef: 目的変数と同じ単位の回帰係数
- support: ルールを満たすサンプル比率
- importance: 係数とサポートから計算される指標
type=rule は境界や相互作用を示し、type=linear は単調な効果を示唆します。係数が大きくサポートも十分なルールを優先的に確認します。
5. 可視化で検証する #
単純な線形効果の確認例:
plt.figure(figsize=(6, 5))
plt.scatter(X_train["sqft_above"], y_train, s=10, alpha=0.5)
plt.xlabel("sqft_above")
plt.ylabel("price")
plt.title("sqft_above と価格の関係")
plt.grid(alpha=0.3)
plt.show()
特定ルール内外の分布比較:
rule_mask = X["sqft_living"].le(3935.0) & X["lat"].le(47.5315)
applicable_data = np.log(y[rule_mask])
not_applicable = np.log(y[~rule_mask])
plt.figure(figsize=(8, 5))
plt.boxplot([applicable_data, not_applicable],
labels=["ルール適用", "ルール非適用"])
plt.ylabel("log(price)")
plt.title("ルール適用可否での価格分布")
plt.grid(alpha=0.3)
plt.show()
6. 実務での Tips #
- 外れ値処理や Winsorize を行うとルールの安定性が向上します。
- カテゴリ変数はレベルを整理し、必要であれば頻度ベースでまとめてからエンコードします。
- 目的変数が歪んでいる場合は
log(y)などの変換も検討します。 - ルール数・深さは読みやすさと性能のトレードオフ。交差検証で適切な上限を決めましょう。
- 重要ルールをビジネス言語でサマリ化し、意思決定資料に転記すると説明責任を果たしやすくなります。
7. 参考文献 #
- Friedman, J. H., & Popescu, B. E. (2008). Predictive Learning via Rule Ensembles. The Annals of Applied Statistics, 2(3), 916–954.
- Christoph Molnar. (2020). Interpretable Machine Learning. https://christophm.github.io/interpretable-ml-book/rulefit.html