金融风控入门赛01

我的机器学习实践之旅还在继续,这次我继续参加了DataWhale的组队学习活动,题目是金融风控。

一、背景介绍

赛题以金融风控中的个人信贷为背景,要求选手根据贷款申请人的数据信息预测其是否有违约的可能,以此判断是否通过此项贷款,这是一个典型的分类问题。通过这道赛题来引导大家了解金融风控中的一些业务背景,解决实际问题,帮助竞赛新人进行自我练习、自我提高。

二、数据介绍

赛题以预测用户贷款是否违约为任务,数据集报名后可见并可下载,该数据来自某信贷平台的贷款记录,总数据量超过120w,包含47列变量信息,其中15列为匿名变量。其中,80万条作为训练集,20万条作为测试集A,20万条作为测试集B,同时会对employmentTitle、purpose、postCode和title等信息进行脱敏。

Field

Description

id

为贷款清单分配的唯一信用证标识

loanAmnt

贷款金额

term

贷款期限(year)

interestRate

贷款利率

installment

分期付款金额

grade

贷款等级

subGrade

贷款等级之子级

employmentTitle

就业职称

employmentLength

就业年限(年)

homeOwnership

借款人在登记时提供的房屋所有权状况

annualIncome

年收入

verificationStatus

验证状态

issueDate

贷款发放的月份

purpose

借款人在贷款申请时的贷款用途类别

postCode

借款人在贷款申请中提供的邮政编码的前3位数字

regionCode

地区编码

dti

债务收入比

delinquency_2years

借款人过去2年信用档案中逾期30天以上的违约事件数

ficoRangeLow

借款人在贷款发放时的fico所属的下限范围

ficoRangeHigh

借款人在贷款发放时的fico所属的上限范围

openAcc

借款人信用档案中未结信用额度的数量

pubRec

贬损公共记录的数量

pubRecBankruptcies

公开记录清除的数量

revolBal

信贷周转余额合计

revolUtil

循环额度利用率,或借款人使用的相对于所有可用循环信贷的信贷金额

totalAcc

借款人信用档案中当前的信用额度总数

initialListStatus

贷款的初始列表状态

applicationType

表明贷款是个人申请还是与两个共同借款人的联合申请

earliesCreditLine

借款人最早报告的信用额度开立的月份

title

借款人提供的贷款名称

policyCode

公开可用的策略_代码=1新产品不公开可用的策略_代码=2

n系列匿名特征

匿名特征n0-n14,为一些贷款人行为计数特征的处理

三、赛题理解

本次的场景属于典型的金融风控场景,其中预测的目标为用户是否违约,训练集数据总量80万条,测试集数据量20万条,总特征数为47,其中,无缺失特征为25,首先先要对数据进行处理,这里主要做的处理为区分缺失列及转换特殊格式。

数据读取

import pandas as pd
import numpy as np

train = pd.read_csv('../data/train.csv')
testA = pd.read_csv('../data/testA.csv')

print('Train data shape:',train.shape) #Train data shape: (800000, 47)
print('TestA data shape:',testA.shape) #TestA data shape: (200000, 48)
print(train.columns)
#Index(['id', 'loanAmnt', 'term', 'interestRate', 'installment', #'grade',
#       'subGrade', 'employmentTitle', 'employmentLength', #'homeOwnership',
#       'annualIncome', 'verificationStatus', 'issueDate', #'isDefault',
#       'purpose', 'postCode', 'regionCode', 'dti', #'delinquency_2years',
#       'ficoRangeLow', 'ficoRangeHigh', 'openAcc', 'pubRec',
#       'pubRecBankruptcies', 'revolBal', 'revolUtil', 'totalAcc',
#       'initialListStatus', 'applicationType', 'earliesCreditLine', #'title',
#       'policyCode', 'n0', 'n1', 'n2', 'n2.1', 'n4', 'n5', 'n6', 'n7', 'n8',
#       'n9', 'n10', 'n11', 'n12', 'n13', 'n14'], dtype='object')

区分缺失列及非缺失列

not_null_column = ['id','loanAmnt','term','interestRate','installment','grade','subGrade','homeOwnership',
                'annualIncome','verificationStatus','issueDate','purpose','regionCode',
                'delinquency_2years','ficoRangeLow','ficoRangeHigh','openAcc','pubRec','revolBal',
                'totalAcc','initialListStatus','applicationType','earliesCreditLine','policyCode','isDefault']
null_column = [col for col in train.columns if col not in not_null_column]

转换特殊格式

list1=sorted(train['subGrade'].astype(str).unique())
subGrade_dic = {list1[i]:i for i in range(len(list1))}
grade_dic = {'E':5, 'D':4, 'A':1, 'C':3, 'B':2, 'F':6, 'G':7}
earlies_dic = {'Aug':'08', 'May':'05', 'Jul':'07', 'Oct':'10', 'Dec':'12', 
'Apr':'04', 'Jan':'01', 'Nov':'11', 'Feb':'02','Mar':'03', 'Jun':'06', 'Sep':'09'}

train['issueDate']=train['issueDate'].apply(lambda x:str(x)[:4]+str(x)[5:7]+str(x)[-2:])
train['grade']=train['grade'].map(grade_dic)
train['earliesCreditLine'] = train['earliesCreditLine'].apply(lambda x:x[4:]+earlies_dic[x[:3]])
train['subGrade'] = train['subGrade'].map(subGrade_dic)

然后,我还画出了数据数量与时间的相关关系。

java 项目增加风控 java金融风控项目_Line


从图中可以看到,大概从14年5月到18年年初用户交易较为活跃。

特征相关性分析

for i in not_null_column:
    print(i,'isDefault',train[i].corr(train['isDefault']))

# id isDefault -0.00035108389556033935
# loanAmnt isDefault 0.06520961446281096
# term isDefault 0.17512564943237638
# interestRate isDefault 0.2592022258683037
# installment isDefault 0.05152448921221738
# grade isDefault 0.2618575780880932
# subGrade isDefault 0.26772357566751687
# homeOwnership isDefault 0.05459850810406215
# annualIncome isDefault -0.04278186579523253
# verificationStatus isDefault 0.08855737298108195

从相关性可以看出,贷款利率、贷款等级、贷款等级之子级与是否违约相关性较强。

catboost-baseline

from catboost import CatBoostClassifier
from sklearn.model_selection import train_test_split
import numpy as np

X_train, X_validation, y_train, y_validation = train_test_split(train[not_null_column],train['isDefault'],test_size=0.3 , random_state=1234)
model = CatBoostClassifier(iterations=100, depth=5,learning_rate=0.5, loss_function='Logloss',
                            logging_level='Verbose')

model.fit(X_train,y_train,eval_set=(X_validation, y_validation),plot=True)