数据挖掘之金融风控-贷款违约预测 03特征工程

数据挖掘之金融风控-贷款违约预测 03特征工程

1. 学习目标

  • 学习特征预处理、缺失值、异常值处理、数据分桶等特征处理方法
  • 学习特征交互、编码、选择的相应方法
  • 完成相应学习打卡任务,两个选做的作业不做强制性要求,供学有余力同学自己探索

2. 内容大概

  • 数据预处理
    • 缺失值的填充
    • 时间格式处理
    • 对象类型特征转换到数值
  • 异常值处理
    • 基于3segama原则
    • 基于箱型图
  • 数据分箱
    • 固定宽度分箱
    • 分位数分箱
    • 离散数值型数据分箱
    • 连续数值型数据分箱
  • 特征交互
    • 特征和特征之间组合
    • 特征和特征之间衍生
  • 特征编码
    • one-hot编码
    • label-encode编码
  • 特征选择
    • 1 Filter
    • 2 Wrapper (RFE)
    • 3 Embedded

3. 学习过程

3.1 导入包并读取数据

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import datetime
import warnings
warnings.filterwarnings('ignore')
plt.rcParams['font.sans-serif'] = 'SimHei'   ## 设置中文显示
plt.rcParams['axes.unicode_minus']=False       #解决负数坐标显示问题
% matplotlib inline
from tqdm import tqdm
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import MinMaxScaler
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
import xgboost as xgb
import lightgbm as lgb
from catboost import CatBoostRegressor
import warnings
from sklearn.model_selection import StratifiedKFold, KFold
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score, log_loss
warnings.filterwarnings('ignore')
fdata_train = pd.read_csv('train .csv')
fdata_testA = pd.read_csv('testA.csv')

3.2 数据预处理

3.2.1 缺失值处理

查看缺失值数量:

fdata_train.isnull().sum()

在这里插入图片描述

# 查找对象特征与数值特征
numerical_fea = list(fdata_train.select_dtypes(exclude=['object']).columns)
category_fea = list(filter(lambda x: x not in numerical_fea,list(fdata_train.columns)))
label = 'isDefault'
numerical_fea.remove(label)
category_fea  # 对象类型

[‘grade’, ‘subGrade’, ‘employmentLength’, ‘issueDate’, ‘earliesCreditLine’]

缺失值填充

  • 把所有缺失值替换为指定的值0

    data_train = data_train.fillna(0)

  • 向用缺失值上面的值替换缺失值

    data_train = data_train.fillna(axis=0,method=‘ffill’)

  • 纵向用缺失值下面的值替换缺失值,且设置最多只填充两个连续的缺失值

    data_train = data_train.fillna(axis=0,method=‘bfill’,limit=2)

# 按照平均数填充数值型
fdata_train[numerical_fea] = fdata_train[numerical_fea].fillna(fdata_train[numerical_fea].median())
fdata_testA[numerical_fea] = fdata_testA[numerical_fea].fillna(fdata_train[numerical_fea].median())
# 查看数值型特征空值数量
fdata_train[numerical_fea].isnull().sum()

在这里插入图片描述
数值型特征查看空值数量已为0。

#按照众数填充类别型特征
for fea in category_fea:
    fdata_train[fea] = fdata_train[fea].fillna(fdata_train[fea].mode())
    print(fdata_train[fea].isnull().sum())
fdata_train['employmentLength'] = fdata_train['employmentLength'].fillna('10+ years') 
for fea in category_fea:
    fdata_testA[fea] = fdata_testA[fea].fillna(fdata_train[fea].mode())
    print(fdata_train[fea].isnull().sum())
fdata_testA['employmentLength'] = fdata_testA['employmentLength'].fillna('10+ years')

类别型特征使用众数填充,查看填充后是否包含空值:

fdata_train[category_fea].isnull().sum()

在这里插入图片描述
3.2.2 转化时间格式

#转化成时间格式
for data in [fdata_train, fdata_testA]:
    data['issueDate'] = pd.to_datetime(data['issueDate'],format='%Y-%m-%d')
    startdate = datetime.datetime.strptime('2007-06-01', '%Y-%m-%d')
    #构造时间特征
    data['issueDateDT'] = data['issueDate'].apply(lambda x: x-startdate).dt.days
fdata_train['issueDateDT'].head() # 查看特征

在这里插入图片描述
创建issueDateDT特征,数值代表贷款发放时间至最早发放时间2007-06-01的间隔天数。

3.2.3 对象类型特征转换到数值

# 就业年限转化为数值
def employmentLength_to_int(s):
    if pd.isnull(s):
        return s
    else:
        return np.int8(s.split()[0])
for data in [fdata_train, fdata_testA]:
    data['employmentLength'].replace(to_replace='10+ years', value='10 years', inplace=True)
    data['employmentLength'].replace('< 1 year', '0 years', inplace=True)
    data['employmentLength'] = data['employmentLength'].apply(employmentLength_to_int)

将就业年限转换为数值,<1 year转为 0,10+ years转为10,其他正常转换为数值。

fdata_train['employmentLength'].head()

在这里插入图片描述

# earliesCreditLine的转换
# 取年
for data in [fdata_train, fdata_testA]:
    data['earliesCreditLine'] = data['earliesCreditLine'].apply(lambda s: int(s[-4:]))
fdata_train['earliesCreditLine'].head()

在这里插入图片描述

# 部分类别特征
cate_features = ['grade', 'subGrade', 'employmentTitle', 'homeOwnership', 'verificationStatus', 'purpose', 'postCode', 'regionCode', \
                 'applicationType', 'initialListStatus', 'title', 'policyCode']
for f in cate_features:
    print(f, '类型数:', data[f].nunique())

在这里插入图片描述
以上为类别型特征的类型数量统计。

# 转换grade特征为数值
for data in [fdata_train, fdata_testA]:
    data['grade'] = data['grade'].map({'A':1,'B':2,'C':3,'D':4,'E':5,'F':6,'G':7})
fdata_train['grade'].head()

在这里插入图片描述

3.2.4 异常值处理

方法一:均方差
在统计学中,如果一个数据分布近似正态,那么大约 68% 的数据值会在均值的一个标准差范围内,大约 95% 会在两个标准差范围内,大约 99.7% 会在三个标准差范围内。

# # 异常值处理
# 均方差
# 判断异常值
def find_outliers_by_3segama(data,fea):
    data_std = np.std(data[fea])
    data_mean = np.mean(data[fea])
    outliers_cut_off = data_std * 3
    lower_rule = data_mean - outliers_cut_off
    upper_rule = data_mean + outliers_cut_off
    data[fea+'_outliers'] = data[fea].apply(lambda x:str('异常值') if x > upper_rule or x < lower_rule else '正常值')
    return data
fdata_train0 = fdata_train.copy()
for fea in numerical_fea:
    fdata_train0 = find_outliers_by_3segama(fdata_train0,fea)
    print(fdata_train0[fea+'_outliers'].value_counts())
    print(fdata_train0.groupby(fea+'_outliers')['isDefault'].sum())
    print('*'*10)

查看结果:

正常值 800000
Name: id_outliers, dtype: int64
id_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 800000
Name: loanAmnt_outliers, dtype: int64
loanAmnt_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 800000
Name: term_outliers, dtype: int64
term_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 794259
异常值 5741
Name: interestRate_outliers, dtype: int64
interestRate_outliers
异常值 2916
正常值 156694
Name: isDefault, dtype: int64


正常值 792046
异常值 7954
Name: installment_outliers, dtype: int64
installment_outliers
异常值 2152
正常值 157458
Name: isDefault, dtype: int64


正常值 800000
Name: employmentTitle_outliers, dtype: int64
employmentTitle_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 799701
异常值 299
Name: homeOwnership_outliers, dtype: int64
homeOwnership_outliers
异常值 62
正常值 159548
Name: isDefault, dtype: int64


正常值 793973
异常值 6027
Name: annualIncome_outliers, dtype: int64
annualIncome_outliers
异常值 756
正常值 158854
Name: isDefault, dtype: int64


正常值 800000
Name: verificationStatus_outliers, dtype: int64
verificationStatus_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 783003
异常值 16997
Name: purpose_outliers, dtype: int64
purpose_outliers
异常值 3635
正常值 155975
Name: isDefault, dtype: int64


正常值 798931
异常值 1069
Name: postCode_outliers, dtype: int64
postCode_outliers
异常值 221
正常值 159389
Name: isDefault, dtype: int64


正常值 799994
异常值 6
Name: regionCode_outliers, dtype: int64
regionCode_outliers
异常值 1
正常值 159609
Name: isDefault, dtype: int64


正常值 798440
异常值 1560
Name: dti_outliers, dtype: int64
dti_outliers
异常值 466
正常值 159144
Name: isDefault, dtype: int64


正常值 778245
异常值 21755
Name: delinquency_2years_outliers, dtype: int64
delinquency_2years_outliers
异常值 5089
正常值 154521
Name: isDefault, dtype: int64


正常值 788261
异常值 11739
Name: ficoRangeLow_outliers, dtype: int64
ficoRangeLow_outliers
异常值 778
正常值 158832
Name: isDefault, dtype: int64


正常值 788261
异常值 11739
Name: ficoRangeHigh_outliers, dtype: int64
ficoRangeHigh_outliers
异常值 778
正常值 158832
Name: isDefault, dtype: int64


正常值 790889
异常值 9111
Name: openAcc_outliers, dtype: int64
openAcc_outliers
异常值 2195
正常值 157415
Name: isDefault, dtype: int64


正常值 792471
异常值 7529
Name: pubRec_outliers, dtype: int64
pubRec_outliers
异常值 1701
正常值 157909
Name: isDefault, dtype: int64


正常值 794120
异常值 5880
Name: pubRecBankruptcies_outliers, dtype: int64
pubRecBankruptcies_outliers
异常值 1423
正常值 158187
Name: isDefault, dtype: int64


正常值 790001
异常值 9999
Name: revolBal_outliers, dtype: int64
revolBal_outliers
异常值 1359
正常值 158251
Name: isDefault, dtype: int64


正常值 799948
异常值 52
Name: revolUtil_outliers, dtype: int64
revolUtil_outliers
异常值 23
正常值 159587
Name: isDefault, dtype: int64


正常值 791663
异常值 8337
Name: totalAcc_outliers, dtype: int64
totalAcc_outliers
异常值 1668
正常值 157942
Name: isDefault, dtype: int64


正常值 800000
Name: initialListStatus_outliers, dtype: int64
initialListStatus_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 784586
异常值 15414
Name: applicationType_outliers, dtype: int64
applicationType_outliers
异常值 3875
正常值 155735
Name: isDefault, dtype: int64


正常值 775134
异常值 24866
Name: title_outliers, dtype: int64
title_outliers
异常值 3900
正常值 155710
Name: isDefault, dtype: int64


正常值 800000
Name: policyCode_outliers, dtype: int64
policyCode_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 782773
异常值 17227
Name: n0_outliers, dtype: int64
n0_outliers
异常值 3485
正常值 156125
Name: isDefault, dtype: int64


正常值 790500
异常值 9500
Name: n1_outliers, dtype: int64
n1_outliers
异常值 2491
正常值 157119
Name: isDefault, dtype: int64


正常值 789067
异常值 10933
Name: n2_outliers, dtype: int64
n2_outliers
异常值 3205
正常值 156405
Name: isDefault, dtype: int64


正常值 789067
异常值 10933
Name: n2.1_outliers, dtype: int64
n2.1_outliers
异常值 3205
正常值 156405
Name: isDefault, dtype: int64


正常值 788660
异常值 11340
Name: n4_outliers, dtype: int64
n4_outliers
异常值 2476
正常值 157134
Name: isDefault, dtype: int64


正常值 790355
异常值 9645
Name: n5_outliers, dtype: int64
n5_outliers
异常值 1858
正常值 157752
Name: isDefault, dtype: int64


正常值 786006
异常值 13994
Name: n6_outliers, dtype: int64
n6_outliers
异常值 3182
正常值 156428
Name: isDefault, dtype: int64


正常值 788430
异常值 11570
Name: n7_outliers, dtype: int64
n7_outliers
异常值 2746
正常值 156864
Name: isDefault, dtype: int64


正常值 789625
异常值 10375
Name: n8_outliers, dtype: int64
n8_outliers
异常值 2131
正常值 157479
Name: isDefault, dtype: int64


正常值 786384
异常值 13616
Name: n9_outliers, dtype: int64
n9_outliers
异常值 3953
正常值 155657
Name: isDefault, dtype: int64


正常值 788979
异常值 11021
Name: n10_outliers, dtype: int64
n10_outliers
异常值 2639
正常值 156971
Name: isDefault, dtype: int64


正常值 799434
异常值 566
Name: n11_outliers, dtype: int64
n11_outliers
异常值 112
正常值 159498
Name: isDefault, dtype: int64


正常值 797585
异常值 2415
Name: n12_outliers, dtype: int64
n12_outliers
异常值 545
正常值 159065
Name: isDefault, dtype: int64


正常值 788907
异常值 11093
Name: n13_outliers, dtype: int64
n13_outliers
异常值 2482
正常值 157128
Name: isDefault, dtype: int64


正常值 788884
异常值 11116
Name: n14_outliers, dtype: int64
n14_outliers
异常值 3364
正常值 156246
Name: isDefault, dtype: int64


# 删除异常值
for fea in numerical_fea:
    fdata_train0 = fdata_train0[fdata_train0[fea+'_outliers']=='正常值']
    fdata_train0 = fdata_train0.reset_index(drop=True) 
# 删除异常值后的数据集大小
fdata_train0.shape 
# (612742, 89)

方法二:箱型图

  • 四分位数会将数据分为三个点和四个区间,IQR = Q3 -Q1,下触须=Q1 − 1.5x IQR,上触须=Q3 + 1.5x IQR
# 箱型图
def find_outliers_by_tukey(data,fea):
    per = np.percentile(data[fea],[0,25,50,75,100])
    IQR = per[3] - per[1]
    uplimit = per[3] + 1.5*IQR
    downlimit = per[1] - 1.5*IQR
    data[fea+'_outliers'] = data[fea].apply(lambda x:str('异常值') if x > uplimit or x < downlimit else '正常值')
    return data
# 判断异常值
fdata_train2 = fdata_train.copy()
for fea in numerical_fea:
    fdata_train2 = find_outliers_by_tukey(fdata_train2,fea)
    print(fdata_train2[fea+'_outliers'].value_counts())
    print(fdata_train2.groupby(fea+'_outliers')['isDefault'].sum())
    print('*'*10)

查看结果:

正常值 800000
Name: id_outliers, dtype: int64
id_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 795754
异常值 4246
Name: loanAmnt_outliers, dtype: int64
loanAmnt_outliers
异常值 875
正常值 158735
Name: isDefault, dtype: int64


正常值 606902
异常值 193098
Name: term_outliers, dtype: int64
term_outliers
异常值 62484
正常值 97126
Name: isDefault, dtype: int64


正常值 785197
异常值 14803
Name: interestRate_outliers, dtype: int64
interestRate_outliers
异常值 7061
正常值 152549
Name: isDefault, dtype: int64**


正常值 775008
异常值 24992
Name: installment_outliers, dtype: int64
installment_outliers
异常值 5327
正常值 154283
Name: isDefault, dtype: int64


正常值 746829
异常值 53171
Name: employmentTitle_outliers, dtype: int64
employmentTitle_outliers
异常值 9971
正常值 149639
Name: isDefault, dtype: int64


正常值 799701
异常值 299
Name: homeOwnership_outliers, dtype: int64
homeOwnership_outliers
异常值 62
正常值 159548
Name: isDefault, dtype: int64


正常值 760986
异常值 39014
Name: annualIncome_outliers, dtype: int64
annualIncome_outliers
异常值 5695
正常值 153915
Name: isDefault, dtype: int64


正常值 800000
Name: verificationStatus_outliers, dtype: int64
verificationStatus_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 797893
异常值 2107
Name: purpose_outliers, dtype: int64
purpose_outliers
异常值 320
正常值 159290
Name: isDefault, dtype: int64


正常值 797285
异常值 2715
Name: postCode_outliers, dtype: int64
postCode_outliers
异常值 562
正常值 159048
Name: isDefault, dtype: int64


正常值 785052
异常值 14948
Name: regionCode_outliers, dtype: int64
regionCode_outliers
异常值 2992
正常值 156618
Name: isDefault, dtype: int64


正常值 796729
异常值 3271
Name: dti_outliers, dtype: int64
dti_outliers
异常值 1017
正常值 158593
Name: isDefault, dtype: int64


正常值 645715
异常值 154285
Name: delinquency_2years_outliers, dtype: int64
delinquency_2years_outliers
异常值 33160
正常值 126450
Name: isDefault, dtype: int64


正常值 772333
异常值 27667
Name: ficoRangeLow_outliers, dtype: int64
ficoRangeLow_outliers
异常值 2071
正常值 157539
Name: isDefault, dtype: int64


正常值 772333
异常值 27667
Name: ficoRangeHigh_outliers, dtype: int64
ficoRangeHigh_outliers
异常值 2071
正常值 157539
Name: isDefault, dtype: int64


正常值 772561
异常值 27439
Name: openAcc_outliers, dtype: int64
openAcc_outliers
异常值 6394
正常值 153216
Name: isDefault, dtype: int64


正常值 664765
异常值 135235
Name: pubRec_outliers, dtype: int64
pubRec_outliers
异常值 30914
正常值 128696
Name: isDefault, dtype: int64


正常值 700481
异常值 99519
Name: pubRecBankruptcies_outliers, dtype: int64
pubRecBankruptcies_outliers
异常值 22653
正常值 136957
Name: isDefault, dtype: int64


正常值 752645
异常值 47355
Name: revolBal_outliers, dtype: int64
revolBal_outliers
异常值 7847
正常值 151763
Name: isDefault, dtype: int64


正常值 799953
异常值 47
Name: revolUtil_outliers, dtype: int64
revolUtil_outliers
异常值 21
正常值 159589
Name: isDefault, dtype: int64


正常值 786554
异常值 13446
Name: totalAcc_outliers, dtype: int64
totalAcc_outliers
异常值 2753
正常值 156857
Name: isDefault, dtype: int64


正常值 800000
Name: initialListStatus_outliers, dtype: int64
initialListStatus_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 784586
异常值 15414
Name: applicationType_outliers, dtype: int64
applicationType_outliers
异常值 3875
正常值 155735
Name: isDefault, dtype: int64


正常值 685619
异常值 114381
Name: title_outliers, dtype: int64
title_outliers
异常值 17331
正常值 142279
Name: isDefault, dtype: int64


正常值 800000
Name: policyCode_outliers, dtype: int64
policyCode_outliers
正常值 159610
Name: isDefault, dtype: int64


正常值 619697
异常值 180303
Name: n0_outliers, dtype: int64
n0_outliers
异常值 39234
正常值 120376
Name: isDefault, dtype: int64


正常值 784172
异常值 15828
Name: n1_outliers, dtype: int64
n1_outliers
异常值 4074
正常值 155536
Name: isDefault, dtype: int64


正常值 778543
异常值 21457
Name: n2_outliers, dtype: int64
n2_outliers
异常值 6075
正常值 153535
Name: isDefault, dtype: int64


正常值 778543
异常值 21457
Name: n2.1_outliers, dtype: int64
n2.1_outliers
异常值 6075
正常值 153535
Name: isDefault, dtype: int64


正常值 766052
异常值 33948
Name: n4_outliers, dtype: int64
n4_outliers
异常值 7529
正常值 152081
Name: isDefault, dtype: int64


正常值 765107
异常值 34893
Name: n5_outliers, dtype: int64
n5_outliers
异常值 6671
正常值 152939
Name: isDefault, dtype: int64


正常值 753229
异常值 46771
Name: n6_outliers, dtype: int64
n6_outliers
异常值 10060
正常值 149550
Name: isDefault, dtype: int64


正常值 767866
异常值 32134
Name: n7_outliers, dtype: int64
n7_outliers
异常值 7595
正常值 152015
Name: isDefault, dtype: int64


正常值 769787
异常值 30213
Name: n8_outliers, dtype: int64
n8_outliers
异常值 6081
正常值 153529
Name: isDefault, dtype: int64


正常值 780548
异常值 19452
Name: n9_outliers, dtype: int64
n9_outliers
异常值 5504
正常值 154106
Name: isDefault, dtype: int64


正常值 773216
异常值 26784
Name: n10_outliers, dtype: int64
n10_outliers
异常值 6279
正常值 153331
Name: isDefault, dtype: int64


正常值 799434
异常值 566
Name: n11_outliers, dtype: int64
n11_outliers
异常值 112
正常值 159498
Name: isDefault, dtype: int64


正常值 797585
异常值 2415
Name: n12_outliers, dtype: int64
n12_outliers
异常值 545
正常值 159065
Name: isDefault, dtype: int64


正常值 756401
异常值 43599
Name: n13_outliers, dtype: int64
n13_outliers
异常值 9869
正常值 149741
Name: isDefault, dtype: int64


正常值 779424
异常值 20576
Name: n14_outliers, dtype: int64
n14_outliers
异常值 6060
正常值 153550
Name: isDefault, dtype: int64


以上结果箱型图的四分位数判断异常值,n0-n14基本上异常值数量大于均方差法,结果中加粗的部分为异常值数量大于均方差法的特征,个别特征异常值数量较少,其中term的值有两类为3与5,在箱型图判断中将值为5的样本全归为异常值,大量的employmentTitle特征样本也归为异常值,造成大量异常值误判。箱型图或许更适合连续数值特征。

fdata_train['term'].value_counts()
'''
3    606902
5    193098
Name: term, dtype: int64
'''

删除异常值后的结果中,正常值不到原本的四分之一。

fdata_train1.shape
# (170085, 89)
clabels = ['term','employmentTitle','purpose', 'postCode','regionCode','title']
# 过滤个别类别型特征
nlabels = list(filter(lambda x: x not in clabels,numerical_fea))
fdata_train2 = fdata_train.copy()
for fea in nlabels:
    fdata_train2 = find_outliers_by_tukey(fdata_train2,fea)
    print(fdata_train2[fea+'_outliers'].value_counts())
    print(fdata_train2.groupby(fea+'_outliers')['isDefault'].sum())
    print('*'*10)
for fea in nlabels:
    fdata_train2 = fdata_train2[fdata_train2[fea+'_outliers']=='正常值']
    fdata_train2 = fdata_train2.reset_index(drop=True) 
fdata_train2.shape
# (299639, 83)

过滤个别类别特征后,数据集仍然缺少极大部分,其他数值型特征在箱型图判别异常值时,数量仍旧偏多。
这里更适合选择均方差检测异常值。具体原因再探。

3.2.5 其他类型转换one hot encode

# 类型数在2之上,又不是高维稀疏的,且纯分类特征
# one hot encode
fdata_train1 = fdata_train0.iloc[:,0:48]
fdata_train1
for data in [fdata_train, fdata_testA]:
    data = pd.get_dummies(data, columns=['subGrade', 'homeOwnership', 'verificationStatus', 'purpose', 'regionCode'], drop_first=True)
fdata_train1.shape
# (612742, 138)

3.3 数据分箱

3.3.1 固定宽度分箱

# 通过除法映射到间隔均匀的分箱中,每个分箱的取值范围都是loanAmnt/1000
fdata_train1['loanAmnt_bin1'] = np.floor_divide(fdata_train1['loanAmnt'], 1000)
# 通过对数函数映射到指数宽度分箱
fdata_train1['loanAmnt_bin2'] = np.floor(np.log10(fdata_train1['loanAmnt']))

3.3.2 分位数分箱

fdata_train1['loanAmnt_bin3'] = pd.qcut(fdata_train1['loanAmnt'], 10, labels=False)

在这里插入图片描述

3.4 特征编码

#label-encode:subGrade,postCode,title
# 高维类别特征需要进行转换
for col in tqdm(['employmentTitle', 'postCode', 'title']):
    le = LabelEncoder()
    le.fit(list(fdata_train1[col].astype(str).values) + list(fdata_testA[col].astype(str).values))
    fdata_train1[col] = le.transform(list(fdata_train1[col].astype(str).values))
    fdata_testA[col] = le.transform(list(fdata_testA[col].astype(str).values))
print('Label Encoding 完成')

在这里插入图片描述

3.5 特征选择

特征选择可以降低模型复杂度,删除不必要或对目标值影响很小的特征,整个过程删繁就简,前提是确保不丢失重要特征。在模型训练中,无论是遗漏特征还是特征冗余对结果都造成很大的影响,通过特征选择的方法可以选择最优特征组。
特征选择的方法:

  • 1 Filter
    • 方差选择法
    • 相关系数法(pearson 相关系数)
    • 卡方检验
    • 互信息法
  • 2 Wrapper (RFE)
    • 递归特征消除法
  • 3 Embedded
    • 基于惩罚项的特征选择法
    • 基于树模型的特征选择

3.5.1 Filter

  • 基于特征变量与目标变量的相关性、互信息等计算出结果,过滤特征。

(1)方差选择法: 方法简单,认为高方差包含信息较多,低方差包含信息较少应舍去。虽然方法简单快捷,但对噪声鲁棒性差,没有考虑特征与目标变量的相关性,只是单纯根据方差大小选取特征。

# 删除个别无用特征
fdata_trainco.drop(['Unnamed: 0','id','policyCode'],axis=1,inplace=True)
fdata_testAo.drop(['Unnamed: 0','id','policyCode','isDefault'],axis=1,inplace=True)

from sklearn.feature_selection import VarianceThreshold
# 其中参数threshold为方差的阈值
# 使用方差选择法,先要计算各个特征的方差,然后根据阈值,选择方差大于阈值的特征。
fdata_trainco_target = fdata_trainco['isDefault'] # 目标变量
fdata_trainco1 = fdata_trainco.copy()
fdata_trainco1.drop('isDefault',axis=1,inplace=True) # 除开目标变量的其他变量
# fdata_trainco1.std() # 查看方差
# 创建选择器
selectior = VarianceThreshold(threshold=3)
selectior.fit_transform(fdata_trainco1,fdata_trainco_target)
# 获选特征的掩码,结果为布尔值
selectior.get_support()
dt_col = fdata_trainco1.columns
fea_v_selr1 = dt_col[fea_v_sel==True] # 获取选择的特征
fea_v_selr1.shape

(2)相关系数法:Pearson 相关系数 皮尔森相关系数是一种最简单的,可以帮助理解特征和响应变量之间关系的方法,该方法衡量的是变量之间的线性相关性。结果的取值区间为 [-1,1] , -1 表示完全的负相关, +1表示完全的正相关,0 表示没有线性相关。

# 相关系数法
from sklearn.feature_selection import SelectKBest
from scipy.stats import pearsonr
#选择K个最好的特征,返回选择特征后的数据
#第一个参数为计算评估特征是否好的函数,该函数输入特征矩阵和目标向量,
#输出二元组(评分,P值)的数组,数组第i项为第i个特征的评分和P值。在此定义为计算相关系数
#参数k为选择的特征个数
# 默认k=10
selector_kb = SelectKBest()
selector_kb.fit_transform(fdata_trainco1,fdata_trainco_target)
fea_v_selkb = selector_kb.get_support()
fea_v_selrkb = dt_col[fea_v_selkb==True]
fea_v_selrkb.shape

(3)卡方检验:

  • 经典的卡方检验是用于检验自变量对因变量的相关性。假设自变量有N种取值,因变量有M种取值,考虑自变量等于i且因变量等于j的样本频数的观察值与期望的差距。 其统计量如下:
    χ2=∑(A−T)2T,其中A为实际值,T为理论值
    (注:卡方只能运用在正定矩阵上,否则会报错Input X must be non-negative)
# 先将数据集归一化
fdata_trainco1_minmax = MinMaxScaler().fit_transform(fdata_trainco1)
fdata_trainco1_minmax
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#参数k为选择的特征个数

selector_chi = SelectKBest(chi2)
selector_chi.fit_transform(fdata_trainco1_minmax,fdata_trainco_target)
fea_v_selchi = selector_chi.get_support()
fea_v_selrchi = dt_col[fea_v_selchi==True]
fea_v_selrchi

(4)互信息法:经典的互信息也是评价自变量对因变量的相关性的。 在feature_selection库的SelectKBest类结合最大信息系数法可以用于选择特征,相关代码如下:

from sklearn.feature_selection import SelectKBest
from minepy import MINE
#由于MINE的设计不是函数式的,定义mic方法将其为函数式的,
#返回一个二元组,二元组的第2项设置成固定的P值0.5
def mic(x, y):
    m = MINE()
    m.compute_score(x, y)
    return (m.mic(), 0.5)
#参数k为选择的特征个数
selector_mi = SelectKBest(lambda X, Y: np.array(list(map(lambda x:mic(x, Y), X.T))).T)
selector_mi.fit_transform(fdata_trainco1,fdata_trainco_target)
fea_v_selmi = selector_mi.get_support()
fea_v_selmi

3.5.2 Wrapper (RFE)
递归特征消除法 递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练。

# 逻辑回归为例
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
#递归特征消除法,返回特征选择后的数据
#参数estimator为基模型
#参数n_features_to_select为选择的特征个数

selectorRFE = RFE(estimator=LogisticRegression(), n_features_to_select=2)
selectorRFE.fit_transform(fdata_trainco1 ,fdata_trainco_target)
fea_v_selREF =selectorRFE.get_support()
fea_v_selREF 

3.5.3 Embedded

3.6 模型训练

3.6.1 预处理
数据集删除一些无用特征,然后用计算协方差的方式看一下特征间相关性,然后进行模型训练。

fdata_train.drop(['id','policyCode','issueDate'],axis=1,inplace=True)
fdata_testA.drop(['id','policyCode','issueDate'],axis=1,inplace=True)
#计算协方差
fdata_train_corr = fdata_train.corrwith(fdata_train.isDefault)  # 计算各个特征与目标变量的相关性
result = pd.DataFrame(columns=['features', 'corr'])
result['features'] = fdata_train_corr.index
result['corr'] = fdata_train_corr.values
# 可视化
fdata_numeric = fdata_train[numerical_fea]
correlation = fdata_numeric.corr()
f , ax = plt.subplots(figsize = (7, 7))
plt.title('Correlation of Numeric Features with Price',y=1,size=16)
sns.heatmap(correlation,square = True,  vmax=0.8)

在这里插入图片描述

features = [f for f in fdata_trainco1.columns if f not in '_outliers' not in f]
x_train = fdata_trainco1[features]
x_test = fdata_testAo[features]
y_train = fdata_trainco_target

4. 总结

特征工程是机器学习,是深度学习中最为重要的一部分。本章主要内容之一缺失值异常值的处理,可选择合适的方法处理。分箱操作有不同的方法,需要自行探索。特征选择可以简化模型,降低模型复杂度,在不影响模型性能的前提下,提升模型效率。

5. 学习资料

项目地址:https://github.com/datawhalechina/team-learning-data-mining/blob/master/FinancialRiskControl/Task3%20%E7%89%B9%E5%BE%81%E5%B7%A5%E7%A8%8B.md

比赛地址:https://tianchi.aliyun.com/competition/entrance/531830/introduction

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值