機器學習 scikit-learn9 - 預測貸款使用者是否會逾期 - 特徵篩選 IV 和 隨機森林
阿新 • • 發佈:2018-11-30
特徵挑選
1 說明
主要是根據 IV值 和 隨機森林 這兩種方法來挑選特徵
程式碼連結: https://github.com/spareribs/kaggleSpareribs/blob/master/Overdue/ml/features/feature_iv_rf.py
2 程式碼使用方法
sklearn_gcv.py 預設使用Logistic Regression 做示例
- 【必須】執行 features 中的 base.py 先把資料處理好 [PS:需要根據實際情況修改]
- 【可選】執行 features 中的 feature_iv_rf.py 進行特徵篩選
- 【必須】再通過 code 中的 sklearn_train.py 訓練,觀察結果
3 核心程式碼說明
3.1 IV值挑選特徵
關於 IV值的計算方法可以參考這個部落格 https://blog.csdn.net/kevin7658/article/details/50780391/
IV 值 計算參考 https://blog.csdn.net/l75326747/article/details/84326897
IV值 範圍 選擇 參考 https://www.jianshu.com/p/bd350351aa5c
# 計算 IV 函式
def cal_iv(x, y, n_bins=6, null_value=np.nan, ):
# 剔除空值
x = x[x != null_value]
# 若 x 只有一個值,返回 0
if len(x.unique()) == 1 or len(x) != len(y):
return 0
if x.dtype == np.number:
# 數值型變數
if x.nunique() > n_bins:
# 若 nunique 大於箱數,進行分箱
x = pd.qcut(x, q=n_bins, duplicates='drop')
# 計算IV
groups = x.groupby([x, list(y)]).size().unstack().fillna(0)
t0, t1 = y.value_counts().index
groups = groups / groups.sum()
not_zero_index = (groups[t0] > 0) & (groups[t1] > 0)
groups['iv_i'] = (groups[t0] - groups[t1]) * np.log(groups[t0] / groups[t1])
iv = sum(groups['iv_i'])
return iv
fea_iv = x_train.apply(lambda x: cal_iv(x, y_train), axis=0).sort_values(ascending=False)
print(fea_iv)
# 篩選 IV > 0.2 的特徵: 0.3 到0.5 之間的資料非常少,這裡取值0.02
imp_fea_iv = fea_iv[fea_iv > 0.02].index
3.2 隨機森林挑選特徵
可以參考 sklearn 官網的例子 https://scikit-learn.org/stable/auto_examples/ensemble/plot_forest_importances.html
主要是 feature_importances_ 輸出每個特徵的重要程度,理論上是 gini 值
# 隨機森林引數
clfs = {
'rf': RandomForestClassifier(n_estimators=40, criterion='gini', max_depth=9),
}
隨機森林得到 feature_importances_ 的結果輸出
clf_name = "rf"
forest = clfs[clf_name]
forest.fit(x_train, y_train)
# print(sorted(zip(map(lambda x: round(x, 4), forest.feature_importances_), x_train.columns), reverse=True))
rf_impc = pd.Series(forest.feature_importances_, index=x_train.columns).sort_values(ascending=False)
print(rf_impc)
# 篩選 重要性前15個特徵
imp_fea_rf = rf_impc.index[:15]
3.3 將 IV值 和 隨機森林的特徵結合
# 合併特徵並篩選出有用特徵
imp_fea = list(set(imp_fea_iv) | set(imp_fea_rf))
X_imp = x_train[imp_fea]
print(type(X_imp))
# print(y_train)
# 歸一化處理
standardScaler = StandardScaler()
scaler = standardScaler.fit(X_imp)
X_imp = scaler.transform(X_imp)
print(X_imp)
3.4 訓練模型輸出結果
[LibLinear][LibSVM]測試模型 & 模型引數如下:
StackingCVClassifier(classifiers=[LogisticRegression(C=0.1, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='warn',
n_jobs=None, penalty='l1', random_state=None, solver='warn',
tol=0.0001, verbose=0, warm_start=False), SVC(C=1.0, cache_size=....0, reg_lambda=0.0, silent=True,
subsample=1.0, subsample_for_bin=200000, subsample_freq=0)],
cv=2,
meta_classifier=LogisticRegression(C=0.1, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='warn',
n_jobs=None, penalty='l1', random_state=None, solver='warn',
tol=0.0001, verbose=0, warm_start=False),
shuffle=True, store_train_meta_features=False, stratify=True,
use_clones=True, use_features_in_secondary=False,
use_probas=True, verbose=3)
====================
訓練集正確率: 0.8250
訓練集f1分數: 0.5403
訓練集auc分數: 0.6870
4 結果對比
結果看來,比原來模型提高了一丟丟
模型融合 | 特徵篩選 |
---|---|
訓練集正確率: 0.8220 訓練集f1分數: 0.5331 訓練集auc分數: 0.6833 |
訓練集正確率: 0.8250 訓練集f1分數: 0.5403 訓練集auc分數: 0.6870 |
5 問題
- 問題1: 如果不進行歸一化處理,lr模型會報錯
原因未知,需要找時間排查,先記下來 KeyError: “’[ 0 1 8 … 4749 4750 4751] not in index’\nPlease check that X and y are NumPy arrays. If X and y are pandas DataFrames,\ntry passing them as X.values and y.values.” - 整理文件1:IV值的由來和計算方法
- 整理文件2:隨機森林挑選特徵的原理