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