【机器学习-贷款用户逾期情况分析2】2.特征工程

2.0 任务说明

特征选择:分别用IV值和随机森林进行特征选择。再用【算法实践】中的7个模型(逻辑回归、SVM、决策树、随机森林、GBDT、XGBoost和LightGBM),进行模型评估。

 

2.1 特征选择

特征选择( Feature Selection )也称特征子集选择( Feature Subset Selection , FSS ),或属性选择( Attribute Selection )。是指从已有的M个特征(Feature)中选择N个特征使得系统的特定指标最优化,是从原始特征中选择出一些最有效特征以降低数据集维度的过程,是提高学习算法性能的一个重要手段。

    2.1.1 IV值进行特征选择

(1)IV值含义

IV是什么?全称是Information Value,中文意思是信息价值,或者信息量。

那它有什么内在含义呢?变量的预测能力。且通常来讲,变量的IV值越高,则该变量的预测能力越强

这就对选取哪些x进行建模,起到了关键的作用了,但是IV也有其限制的范围。

首先、模型必须是有监督模型(即有y标签变量),其次、y标签必须是二分类(即y只有两类y1,y2)

常见的IV取值范围代表意思如下:

若IV在(-∞,0.02]区间,视为无预测力变量

若IV在(0.02,0.1]区间,视为较弱预测力变量

若IV在(0.1,+∞)区间,视为预测力可以,而实际应用中,也是保留IV值大于0.1的变量进行筛选。

(2)IV值的计算

在了解IV计算过程之前,必须明白另一个概念"WOE"

WOE的全称是“Weight of Evidence”,即证据权重。计算公式为:

简单的理解就是 该分箱 坏样本(即b)占比除以好样本(即g)占比的自然对数。(如果对分箱有疑问的同学,可以先简单理解成如果x=0、1、2、3,那么x=0就是一箱,x=1、2、3也是各为一箱)

而从公式也可以体现出WOE的含义:当前分箱中“坏样本占所有坏样本的比例”和“好样本占所有好样本的比例”的差异。很容易可以看出,当差异越大,则该分箱响应坏样本的的可能性就越大;当差异越小,则该分箱响应坏样本的可能性就越小。

IV值的计算公式:

(3)代码

def CalcIV(Xvar, Yvar): 
   N_0  = np.sum(Yvar==0)   #坏样本
   N_1 = np.sum(Yvar==1)     #好样本
   N_0_group = np.zeros(np.unique(Xvar).shape)   #分组
   N_1_group = np.zeros(np.unique(Xvar).shape)
   for i in range(len(np.unique(Xvar))):    
       N_0_group[i] = Yvar[(Xvar == np.unique(Xvar)[i]) & (Yvar == 0)].count()   #坏样本里的各个WOE值
       N_1_group[i] = Yvar[(Xvar == np.unique(Xvar)[i]) & (Yvar == 1)].count()   #好样本里的各个WOE值
   iv = np.sum((N_0_group/N_0 - N_1_group/N_1) * np.log((N_0_group/N_0)/(N_1_group/N_1)))   #IV值
   return  iv   
   
def caliv_batch(df, Yvar):
    ivlist = []
    for col in df.columns:
        iv = CalcIV(df[col], Yvar)
        ivlist.append(iv)
    names = list(df.columns)
    iv_df = pd.DataFrame({'Var': names, 'Iv': ivlist}, columns=['Var', 'Iv'])
    return iv_df, ivlist

y=label #数据标签
X = data.copy()  #数据
im_iv, ivl = caliv_batch(X, y)

然后我们把IV值0.02以下的剔除:

threshold = 0.02
data_index = []
for i in range(len(ivl)):
    if im_iv['Iv'][i] < threshold:
        data_index.append(im_iv['Var'][i])
data.drop(data_index, axis=1, inplace=True)

剔除的colum如下:

(4)模型训练

分别用逻辑回归、SVM、决策树、随机森林、GBDT、XGBoost和LightGBM,进行模型评估。这个代码在博主之前的文章里。

模型评估结果如下,列表里从左到右分别是准确率,查准率,查全率,F1值,AUC值

ROC曲线如下:

   2.1.2 随机森林进行特征值选择

(1)原理

用随机森林进行特征重要性评估的思想其实很简单,说白了就是看看每个特征在随机森林中的每颗树上做了多大的贡献,然后取个平均值,最后比一比特征之间的贡献大小。通常可以用基尼指数(Gini index)或者袋外数据(OOB)错误率作为评价指标来衡量贡献。

(2)代码

from sklearn.ensemble import RandomForestClassifier

def RandomForest(X):
    feat_lables = X.columns
    forest = RandomForestClassifier(n_estimators=10000, random_state=0, n_jobs=1)
    forest.fit(X, y)
    importance = forest.feature_importances_
    imp_result = np.argsort(importance)[::-1]
    for i in range(X.shape[1]):
        print("%2d. %-*s %f" % (i+1, 30, feat_lables[i], importance[imp_result[i]]))
    threshold = 0.01
    data_index = list(X.columns[importance < threshold])
    print(X.shape)
    X.drop(data_index, axis=1, inplace=True)
    print(X.shape)
    return X

X=RandomForest(X)

部分结果如下:

由打印的信息可以看到最开始有86个特征,剔除之后变成了50个

(3) 模型评估

跟上面一样,别用逻辑回归、SVM、决策树、随机森林、GBDT、XGBoost和LightGBM,进行模型评估。这个代码在博主之前的文章里。

模型评估结果如下,列表里从左到右分别是准确率,查准率,查全率,F1值,AUC值

ROC曲线:

 

2.2前面所有代码

这篇博客和上篇博客所有代码如下:

import csv
import os
import numpy as np
import random
import requests
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import sklearn
from sklearn.linear_model import LogisticRegressionCV,LinearRegression,LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn import metrics
from sklearn.svm import SVC

def CalcIV(Xvar, Yvar):
    N_0 = np.sum(Yvar == 0)    # 非响应客户
    N_1 = np.sum(Yvar == 1)    # 响应客户
    N_0_group = np.zeros(np.unique(Xvar).shape)   # 分组

    N_1_group = np.zeros(np.unique(Xvar).shape)
    for i in range(len(np.unique(Xvar))):
        # 计算非响应客户和响应客户的各个组内的相关值
        N_0_group[i] = Yvar[(Xvar == np.unique(Xvar)[i]) & (Yvar == 0)].count()
        N_1_group[i] = Yvar[(Xvar == np.unique(Xvar)[i]) & (Yvar == 1)].count()
    # iv值
    iv = np.sum((N_0_group / N_0 - N_1_group / N_1) * np.log((N_0_group / N_0) / (N_1_group / N_1)))
    if iv >= 1.0:  # 处理极端值
        iv = 1
    return iv 
   
def caliv_batch(df, Yvar):
    ivlist = []
    for col in df.columns:
        iv = CalcIV(df[col], Yvar)
        ivlist.append(iv)
    names = list(df.columns)
    iv_df = pd.DataFrame({'Var': names, 'Iv': ivlist}, columns=['Var', 'Iv'])
    return iv_df, ivlist

from sklearn.ensemble import RandomForestClassifier

def RandomForest(X):
    feat_lables = X.columns
    forest = RandomForestClassifier(n_estimators=10000, random_state=0, n_jobs=1)
    forest.fit(X, y)
    importance = forest.feature_importances_
    imp_result = np.argsort(importance)[::-1]
    for i in range(X.shape[1]):
        print("%2d. %-*s %f" % (i+1, 30, feat_lables[i], importance[imp_result[i]]))
    threshold = 0.01
    data_index = list(X.columns[importance < threshold])
    print(X.shape)
    X.drop(data_index, axis=1, inplace=True)
    print(X.shape)
    return X

data0 = pd.read_csv('F:/data.csv',encoding='gbk')
label = data0.status
data = data0.drop(['status'], axis=1)
object_column = ['trade_no', 'bank_card_no', 'reg_preference_for_trad', 'source',
                 'id_name', 'latest_query_time', 'loans_latest_time']
data_obj = data[object_column]
data=data.drop(columns=['Unnamed: 0','id_name', 'trade_no','bank_card_no','custid','source'])
data.isnull().sum(axis=0)
data_isnull = data.isnull().sum(axis=0)
data_isnull[data_isnull != 0].sort_values(ascending=False)
data=data.drop(columns='student_feature')
data.fillna(method='ffill', inplace=True)
from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
reg_preference_1hot = encoder.fit_transform(data[['reg_preference_for_trad']].astype(str))
reg_preference_df = pd.DataFrame(reg_preference_1hot, columns=encoder.classes_)
data.drop(['reg_preference_for_trad'], axis=1, inplace=True)   #将data里的'reg_preference_for_trad'删除
data = pd.concat([data, reg_preference_df], axis=1)   #删除后用独热编码替代
data[['latest_query_time', 'loans_latest_time']]=data[['latest_query_time', 'loans_latest_time']].applymap(lambda x:float(str(x).split('-')[0]+str(x).split('-')[1]+str(x).split('-')[2]))
y=label #数据标签
X = data.copy()  #数据
im_iv, ivl = caliv_batch(X, y)
threshold = 0.02
data_index = []
for i in range(len(ivl)):
    if im_iv['Iv'][i] < threshold:
        data_index.append(im_iv['Var'][i])
data_index
# data.drop(data_index, axis=1, inplace=True)

y=label #数据标签
X = data.copy()  #数据
X=RandomForest(X)

2.3参考文章

1.https://blog.csdn.net/zjuPeco/article/details/77371645?locationNum=7&fps=1

2.https://blog.csdn.net/weixin_38940048/article/details/82316900

3.https://zhuanlan.zhihu.com/p/55913000

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值