数据挖掘-金融风控

数据挖掘-金融风控

特征工程

数据读入

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import datetime
from tqdm import tqdm
from sklearn.preprocessing import LabelEncoder
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
from sklearn.preprocessing import MinMaxScaler
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')

读入数据后对数据进行处理,上方导入的包,如果没有,都可以通过pip安装,window,mac版本应该不可以

特征预处理

在数据预处理阶段,我们对数据进行的总体了解与解析中已经了解了部分问题,在这一部分,就是要对分析出来的问题,进行解决。
首先我们查找出数据中的对象特征和数值特征

numerical_fea=list(train.select_dtypes(exclude=['object']).columns)
category_fea=list(filter(lambda x:x not in numerical_fea,list(train.columns)))
label='isDefault'
numerical_fea.remove(label)
对缺失值的填充

对缺失值的处理一般有删除、填充众数、填充平均数、或者填充特定的数值
我们可以用代码train.isnull().sum()来查看缺失值的情况。
在本次的处理中可以选择填充平均数或众数

# 按照平均数值填充数值型特征
train[numerical_fea]=train[numerical_fea].fillna(train[numerical_fea].median())
test[numerical_fea]=test[numerical_fea].fillna(test[numerical_fea].median())
# 按照众数来填充类别型特征
train[category_fea]=train[category_fea].fillna(train[category_fea].mode())
test[category_fea]=test[category_fea].fillna(train[category_fea].mode())

时间格式的处理
# 转化成时间格式
for data in [train,test]:
    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

train['employmentLength'].value_counts(dropna=False).sort_index()
对象类型转换为数值型
# 对象类型特征转换到数值
def employmentLength_to_int(s):
    if pd.isnull(s):
        return s
    else:
        return np.int8(s.split()[0])
for data in [train,test]:
    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)

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

异常值处理

发现异常值后,一定要先分清是什么原因导致的异常值,然后再考虑如何处理。
首先,如果这一异常值并不代表一种规律性的,而是极其偶然的现象,或者说你并不想研究这种偶然的现象,这时可以将其删除。
其次,如果异常值存在且代表了一种真实存在的现象,那就不能随便删除。
在现有的欺诈场景中很多时候欺诈数据本身相对于正常数据勒说就是异常的,我们要把这些异常点纳入,重新拟合模型,研究其规律。能用监督的用监督模型,不能用的还可以考虑用异常检测的算法来做。
*注意test的数据不能删。

检测方法(一)-方差
在统计学中,如果一个数据分布近似正态,那么大约 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

得到特征的异常值后可以进一步分析变量异常值和目标变量的关系

# 得到特征的异常值后可以进一步分析变量异常值和目标变量的关系
train =train.copy()
for fea in numerical_fea:
    train=find_outliers_by_3segama(train,fea)
    print(train[fea+'_outliers'].value_counts())
    print(train.groupby(fea+'_outliers')['isDefault'].sum())
    print('*'*8)

# 删除异常值
for fea in numerical_fea:
    train=train[train[fea+'_outliers']=='正常值']
    train=train.reset_index(drop=True)

检测方法(二)-箱型图
总结一句话:四分位数会将数据分为三个点和四个区间,IQR = Q3 -Q1,下触须=Q1 − 1.5x IQR,上触须=Q3 + 1.5x IQR

# 通过除法映射到间隔均匀的分箱中,每个分箱的取值范围都是loanAmnt/1000
data['loanAmnt_bin1']=np.floor_divide(data['loanAmnt'],1000)

# 通过除法映射到间隔均匀的分箱中,每个分箱的取值范围都是loanAmnt/1000
data['loanAmnt_bin1']=np.floor_divide(data['loanAmnt'],1000)

# 通过对数函数映射到指数宽度分箱
data['loanAmnt_bin2']=np.floor(np.log10(data['loanAmnt']))

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

特征交互

交互特征的构造非常简单,使用起来却代价不菲。如果线性模型中包含有交互特征对,那它的训练时间和评 分时间就会从 O(n) 增加到 O(n2),其中 n 是单一特征的数量。

for col in ['grade','subGrade']:
    temp_dict=train.groupby([col])['isDefault'].agg(['mean']).reset_index().rename(columns={'mean':col+'_target_mean'})
    temp_dict.index=temp_dict[col].values
    temp_dict=temp_dict[col+'_target_mean'].to_dict()
    train[col+'_target_mean']=train[col].map(temp_dict)
    test[col+'_target_mean']=test[col].map(temp_dict)

# 其他衍生变量mean和str
for df in [train,test]:
    for item in ['n0','n1','n2','n3','n4','n5','n6','n7','n8','n9','n10','n11','n12','n13','n14']:
        df['grade_to_mean_'+item]=df['grade']/df.groupby([item])['grade'].transform('mean')
        df['grade_to_std'+item]=df['grade']/df.groupby([item])['grade'].transform('std')
特征编码
for col in tqdm(['employmentTitle','postCode','title','subGrade']):
    le=LabelEncoder()
    le.fit(list(train[col].astype(str).values)+list(test[col].astype(str).values))
    train[col]=le.transform(list(train[col].astype(str).values))
    test[col]=le.transform(list(test[col].astype(str).values))
print('Label Encoding 完成')

特征选择

.特征选择技术可以精简掉无用的特征,以降低终模型的复杂性,它的终目的是得到一个简约模型,在不降低预测准确率或对预测准确率影响不大的情况下提高计算速度。特征选择不是为了减少训练时间(实际上,一些技术会增加总体训练时间),而是为了减少模型评分时间。

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

数据处理
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值