1. 程式人生 > >機器學習 scikit-learn9 - 預測貸款使用者是否會逾期 - 特徵篩選 IV 和 隨機森林

機器學習 scikit-learn9 - 預測貸款使用者是否會逾期 - 特徵篩選 IV 和 隨機森林

特徵挑選

1 說明

主要是根據 IV值 和 隨機森林 這兩種方法來挑選特徵
程式碼連結: https://github.com/spareribs/kaggleSpareribs/blob/master/Overdue/ml/features/feature_iv_rf.py

2 程式碼使用方法

sklearn_gcv.py 預設使用Logistic Regression 做示例

  1. 【必須】執行 features 中的 base.py 先把資料處理好 [PS:需要根據實際情況修改]
  2. 【可選】執行 features 中的 feature_iv_rf.py 進行特徵篩選
  3. 【必須】再通過 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:隨機森林挑選特徵的原理