使用机器学习构建简单金融风控反欺诈模型(一)EDA+XGBOOST

ReLuQ

交叉学科就像交叉特征一样有趣

已关注

7 人赞同了该文章

本篇带来的是如何在金融风控领域应用我们的机器学习来识别一些风险
仅仅作探索性的尝试,可以当作是一个简单的baseline吧

概念

首先了解一下什么是金融风控中的反欺诈,由于笔者目前就职于的公司是一家大型的P2P金融互联网公司(top的那几家),那么我们公司有理财,信贷,保险,货基等等业务。就拿借贷来说,简而言之就是借钱给有需要的人,类似于银行贷款。

风险来源

现在市面上有这么一些人,俗称黑产灰产。他们会做啥呢?骗贷。他们会使用一些渠道获得一些人的真实信息或者说伪造一些身份信息来进行接待尝试,一旦企业的风控部门没有识别出来这是一个可疑的危险的账号所发起的借贷行为而真真正正的借出了这笔钱,那么可能这笔钱他就再也拿不回来了。

我们知道现在的审核一般会有要求三要素,四要素等等。简单来说就是公民个人的重要信息比如姓名,身份证号,银行卡,地址,电话号码这些。而黑灰产所要做的就是使用虚假我这说其他人的这些信息来进行骗贷行为。而对于公司的风控部门,需要的就是通过一些数据方法和手段识别这些信息是否可靠,这笔贷款是否可借。

大概类似这种(简单点就是使用虚假信息骗别人借钱给他):

图片来源于网络,侵删

进入正题吧

当然啦,风控是十分宽泛的概念,需要的技术有很多,我们不谈金融行业的经验和知识,但从书绝学的角度,可能涉及到关联模型,知识图谱,用户画像,机器学习等等。一个完善的只能风控可能类似这样:

图片来源于网络,侵删

我们今天不会涉及那么全面深入,仅仅举一个例子,来将机器学习应用到风控中。

OK我们的任务是,通过以往的借贷以及还款情况数据,来预测一个新来的用户是否可能存在潜在的逾期或者干脆不还钱的行为

数据集

借贷数据这种非常非常敏感又核心的数据拿到真实数据那是不存在的,因此。本片所使用的数据来源于美国一家非常著名的P2P公司Lending Club所开源出来的,可以通过链接:

LendingClub Statistics​www.lendingclub.com

下载这些数据,笔者所使用的是他们提供的2018年Q1,Q2,Q3,Q4四个季度的借贷及还款情况数据。那么接下来就是正题了。让我们先看一下数据长啥样吧!

数据格式

首先还是老做法,用pandas打开四个季度的CSV文件,并且我们看一下他们的columns的情况以防止出现一些错误,比如说列明不同的情况:

import pandas as pddf1 = pd.read_csv("20181.csv",skiprows=1,low_memory=False)
df2 = pd.read_csv("20182.csv",skiprows=1,low_memory=False)
df3 = pd.read_csv("20183.csv",skiprows=1,low_memory=False)
df4 = pd.read_csv("20184.csv",skiprows=1,low_memory=False)

比较一下列:

df1.columns.tolist() == df2.columns.tolist() == df3.columns.tolist() == df4.columns.tolist()OUT:True

我们发现四个文件所包含的列是相同的,那么接下来我们把四个dataframe纵向拼接到一起,并看一看合成的数据集的基础信息:

train = pd.concat([df1,df2,df3,df4],axis = 0)
train.info()
train.head()

我们可以看到一共包含了495250条数据,145列,其中107列类型为float64,其余为Object

从图中我们就可以看到,id,member_id两列数据值均为NAN,思考应该是为了脱敏。那么这两列可以说是没用的数据,直接删掉。

train = train.drop(["id","member_id"],axis=1,inplace=True)

好啦,其实上面异步可以不做的2333,因为我们现在首先要做的就是处理缺失值,首先对于某一行或者某一列数据全都是NAN的情况,想都别想直接删了:

train = train.dropna(how="all",axis=1)
train = train.dropna(how="all",axis=0)

接下来处理处理缺失值,如何做呢?对于缺失值的处理,自古以来又比较多的方法,但是也需要分情况使用:

  1. 缺失值占多数或半数:直接删除
  2. 数据缺失不多,可以采用众数或平均数或0补全
  3. 数值型离散数据确实不多的,可以采用一些回归方法来根据其他特征预测缺失的特征,比如random forest就可以被用来做这项任务

OK,笔者比较粗暴,对于缺失值在10W以上的数据,全部删除,10W以下的在分情况处理:

drop_list = (train.isnull().sum()>100000)
for i in drop_list.keys():if drop_list[i] == True:train.drop([i],axis=1,inplace=True)

接下来我们把数值型特征先放一边,看一看Object类型的,先看看这些变量的唯一取值有多少:

for col in train.select_dtypes(include=['object']).columns:print ("Column {} has {} unique instances".format( col, len(train[col].unique())) )

我么可以看到如下:

一共25个,仔细分析一下其中的数据,我们发现emp_title这个字段的取值有129450,我们查看网站上提供的字段说明可以知道这是借款人目前的职业,怪不得这么多,应该还有一些重复比如(teacher和Teacher),这么多的值依赖作数据清洗修复需要大量的时间而来存在太多类型没办法进行一些编码(太过稀疏),因此我们目前不使用这个特征,删除之

之后我们关注到字段int_rate,这个字段的是这笔贷款还款的利息是多少,他共有110个值,我们需要对他做去百分号处理,因为原始数据是以类似5.0%这样的格式显示的(过程略,用replace("%","").astype("float"))即可

接下来是addr_state字段,这个字段表明的是借款人来自于哪一个国家,依照敏感这是一个比较有意义的字段(不是地图炮哈),我们可以将其作one-hot编码使用它

看到另一个字段loan_status,这个字段实际上也就是这笔借款目前的状态啦,它包含这样几种取值:

  1. Current:分期还款流程中
  2. Fully Paid :已经还清
  3. Late (31-120 days) :逾期超过31天
  4. Charged Off:已注销
  5. Late (16-30 days) :逾期超过16天
  6. In Grace Period:在宽限期
  7. Default:默认

由于我们需要预测的是用户是否会不还钱或者逾期,因此我们的正样本实际上就是Late (31-120 days)和Late (16-30 days),我们新建一列label存储这个字段:

def getlabel(x):if x == "Late (16-30 days)" or x == "Late (31-120 days)":return 1else:return 0train["label"] = train.loan_status.apply(lambda x:getlabel(x))

在看看其他的字段比如 zip_code,这个字段表明借款人所在地的邮政编码,由于我们已经有了国家信息了,邮政编码对于地球来说是个太过于细化的概念并且他又将近900中取值很难做编码处理,而聚类编码有看上去没耗费时间有没有太大作用,因此删除

字段earliest_cr_line 是一个有用的字段,我无法准确的翻译他的意思,大致就是说借款人银行流水(?)或者征信(?)记录是从多久开始有的,很容易思考如果记录从很早以前开始那么可能这个人年龄较大或者说一直有良好的财政进出,相反可能这个人在银行视角里不是那么的清晰,那么风险也可能会比较大。

他的数据是类似于这样的格式:

月份-年份

同时数据集里还有几个表示时间的字段也是用这种格式记录的,他们有:

  1. last_pymnt_d:最近一次还款时间
  2. next_pymnt_d:下一次还款时间
  3. last_credit_pull_d:这笔贷款最后一次被lending club评估的时间(不知道这么理解对不对)
  4. issue_d:这笔贷款发起的时间

那么我们如何处理时间数据?

由于笔者对于这份数据的很多字段也搞不清,因此在模糊测试阶段使用了如下几种方式:

  1. 将时间中的月份和年份拆分开并单独存储成一列,后进行one-hot编码
  2. 将事件中的年份计算到今年(2019)的距离
  3. last_credit_pull_d,last_credit_pull_d,last_pymnt_d三个数据两辆做差值求出相差得时间间隔

大致代码如下:

首先对缺失值,我们填充以出现最多的值,用last_credit_pull_d举例:

train.last_credit_pull_d = train.last_credit_pull_d.fillna("Feb-2019")

拆分月份和年份:

train["last_credit_pull_d_month"] = train.last_credit_pull_d.apply(lambda x:x.split("-")[0])
train["last_credit_pull_d_year"] = train.last_credit_pull_d.apply(lambda x:x.split("-")[1])

月份转化成数字:

def getmonth(x):if x == "May":return 5if x == "Oct":return 10if x == "Aug":return 8if x == "Jul":return 7if x == "Apr":return 4if x == "Nov":return 11if x == "Dec":return 12if x == "Sep":return 9if x == "Mar":return 3if x == "Jan":return 1if x == "Feb":return 2if x == "Jun":return 6train["last_credit_pull_d_month"] = train.last_credit_pull_d_month.apply(lambda x :getmonth(x))

差值处理:

train["loan_last_start"] = train["last_credit_pull_d_month"] - train["loan_month"] + 12 * (train["last_credit_pull_d_year"]-train["loan_year"])

PS:这里只是示例代码,其他时间字段按照同方法处理即可

再看这个字段:emp_length 它表明了借款人迄今为止工作了多少年,数据分布如下:

这也是一个很有用的维度因为一般来说工作越长的人金钱积累和收入都可能更高,偿还能力夜可能更好,我们将其转化为数值型:

train.emp_length = train.emp_length.fillna("10 years")
def getwork(x):if "+" in x:return 10else:if "<" in x:return 0else:return int(x.split(" ")[0])
train["work_long"] = train.emp_length.apply(lambda x : getwork(x))

然后我们将原有的不需要的字段全部删除,包括右边,职业,原始保存的时间格式等等

train.drop(["issue_d","last_credit_pull_d","last_pymnt_d","loan_status","issue_d"],axis=1,inplace=True)

我们看一下现在的数据情况

train.info()

可以看到目前一共99个特征维度,一个标签列。看上去整整齐齐也没有大规模的数据缺失。那么一下步我们就要进行一些少规模数据缺失的处理

由于在经过以上的处理后,我们所生下包含缺失值的列均为数字型,因此我们分情况将每一列的数据分布和取值都看一看,在决定使用众数,平均数还是0进行填充即可

补全代码都是通用的,类似这种:

train.colname = train.colname.fillna(train.colname.mean())

最后一步,one-hot编码,我们使用pandas.get_dummies()一步到位

train = pd.get_dummies(train)

最后我们的数据情况如下:

接下来就是初步的模型训练啦,模型选用强大的xgboost,参数现场是通用参数:

我们首先把数据集的标签和特征分开,在使用train_test_split随机划分为训练集和测试集:

y  = train.label
x = train.drop(["label"],axis=1,inplace=True)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=666)

构建XGB参数,并使用训练集进行训练,在测试集上测试

clf2 = xgb.XGBClassifier(n_estimators=500, max_depth=3, learning_rate=0.01, subsample=0.8, colsample_bytree=0.3,scale_pos_weight=3.0, silent=True, nthread=-1, seed=0, missing=None,objective='binary:logistic', reg_alpha=1, reg_lambda=1, gamma=0, min_child_weight=1, max_delta_step=0,base_score=0.5)clf2.fit(x_train, y_train)
print (clf2.score(x_test, y_test))

最终结果:

总结

风控其实是一个很有意思的事情。

我认为只有金融,机器学习和安全结合在一起,才能做到更加安全的风控系统和更强的反欺诈能力。

安全方面的IP,Phone,User-Agent,请求频率配合业务方的真实线上数据;

风控和金融人员的专业经验结合机器学习和统计学习甚至深度学习;

才是风控越走越远的法门。

编辑于 2019-03-12

机器学习

大数据风控

业务安全

​赞同 7​​6 条评论

​分享

​收藏

文章被以下专栏收录

机器学习于安全风控领域的应用实践

已关注

6 条评论

​切换为时间排序

写下你的评论...

发布

  • 豆腐脑应该是甜的3 天前

    很不错呀,可以研究研究

    ​赞​回复​踩​举报

  • 吴三岁8 小时前

    代码好多错误之处啊 运行不了 怎么回事

    ​赞​回复​踩​举报

  • ReLuQ (作者) 回复吴三岁6 小时前

    因为是简略版的代码 不是完整版的~

    ​赞​回复​踩​举报

  • 吴三岁回复ReLuQ (作者)1 小时前

    你好 能发我一下完整版的代码吗 我想试一下

    ​赞​回复​踩​举报

  • 吴三岁回复ReLuQ (作者)1 小时前

    谢谢

    ​赞​回复​举报

  • ReLuQ (作者) 回复吴三岁19 分钟前

    代码已经上传https://github.com/0FuzzingQ/fengkong可能有一些问题因为有地方是反复运行的,不过问题应该不大~写的比较丑

    ​赞​回复​举报

使用机器学习构建简单金融风控反欺诈模型(一)EDA+XGBOOST相关推荐

  1. community 计算模块度_【转载】金融风控反欺诈之图算法

    随着量化宽松和经济复苏,商业银行消费金融进一步发展,在移动支付.大数据.人工智能等技术快速发展的背景下,消费金融领域开展了诸多创新,金融借贷业务发展迅速. 先介绍下金融借贷业务流程:用户前来申请借贷, ...

  2. 金融反欺诈模型----项目实战--机器学习

    机器学习:从源数据清洗到特征工程建立谈金融反欺诈模型训练 本文旨在通过一个完整的实战例子,演示从源数据清洗到特征工程建立,再到模型训练,以及模型验证和评估的一个机器学习的完整流程.由于初识机器学习,会 ...

  3. AI:人工智能实践六大场景(金融信用违约、反欺诈模型、客户偏好洞察、智能推荐、精准营销、客户流失管理)及其对应常用机器学习算法经验总结(不断更新)

    AI:人工智能实践六大场景(金融信用违约.反欺诈模型.客户偏好洞察.智能推荐.精准营销.客户流失管理)及其对应常用机器学习算法经验总结(不断更新) 目录

  4. 互联网金融领域反欺诈技术已发展到哪一步?

    http://www.ce.cn/xwzx/gnsz/gdxw/201711/13/t20171113_26835875.shtml 近日,在JDD大会上,京东金融集团副总裁.技术研发部总经理曹鹏介绍 ...

  5. python金融风控评分卡模型和数据分析

    python金融风控评分卡模型和数据分析微专业课(博主录制):http://dwz.date/b9vv 作者Toby:持牌照消费金融模型专家,和中科院,中科大教授保持长期项目合作:和同盾,聚信立等外部 ...

  6. python金融风控评分卡模型

    python金融风控评分卡模型和数据分析微专业课(博主录制): [ http://dwz.date/b9vv ](https://study.163.com/series/1202875601.htm ...

  7. 实操信贷场景中的反欺诈模型

    今天的文章,关于反欺诈模型的实操,之前有跟大家分享过相关内容,部分反欺诈的领域的童鞋感觉内容比较有帮助,今天就该内容进行讲解.本文介绍的产品适合在消费零售信贷及现金场景贷中的中短期产品,其中涉及的变量 ...

  8. 微表情反欺诈模型特征解析及应用

    在整个风险管理全流程中,科技元素应用最多的板块非反欺诈莫属. 一是因为反欺诈风控本身在整个信贷风险全流程拒绝比率中占比较少,导致其"拒绝容错率"可以相应放大,进而可以使用相对激进的 ...

  9. python金融风控评分卡模型和数据分析(加强版)-收藏

    信用评分卡 信用评分是指根据银行客户的各种历史信用资料,利用一定的信用评分模型,得到不同等级的信用分数,根据客户的信用分数,授信者可以通过分析客户按时还款的可能性,据此决定是否给予授信以及授信的额度和 ...

  10. 原理+代码|手把手教你使用Python实战反欺诈模型

    三本点击上方"早起Python",关注并"星标" 每日接收Python干货! 本文含 6192 字,15 图表截屏 建议阅读 20分钟 本文将基于不平衡数据,使 ...

最新文章

  1. Android安卓模拟器的使用
  2. htmlselect保留上次选择内容_中药口服液药液性质与过滤器械选择
  3. 训练日志 2018.8.29
  4. Oracle、Db2、SqlServer、MySQL 数据库插入当前系统时间
  5. Python之网络编程(socketserver模块详解、链接认证)
  6. 动画 - 收藏集 - 掘金
  7. 新浪微博php7升级实践,PHP7线上system time飙高问题
  8. VLAN基础、接口类型和实验
  9. 函数无法识别_Halcon OCR识别
  10. 58、LVS TUN模型实战
  11. html下载链接引入element-ui
  12. 片上总线Wishbone 学习(三)Wishbone互联的类型
  13. 一个关于Linux Bridge配置的吐嘈
  14. matlab实现数据压缩,【Matlab】Huffman编码如何实现数据压缩
  15. 批量创建文件夹并命名
  16. 临近空间环境监测系统
  17. 赋能新零售,Stratifyd亮相Smart Retail智慧零售年度峰会
  18. 首席新媒体黎想教程:直播间流量低?试试这几招!
  19. 共享ADSL违法 中国电信下手封杀真相调查
  20. 我的黑莓8830插CDMA卡成功

热门文章

  1. Ubuntu镜像的下载
  2. 超级好用的网站整站下载工具
  3. 剪贴板查看器clipbrd.exe
  4. 清吧音响怎么选?看看这个黄金搭配,跟着买就对了
  5. Firefox 中文语言包安装方法
  6. 量子计算基础——量子测量
  7. windows优化大师8周年纪念版_P5SPS4体验版上线|青之驱魔师10周年纪念新卷发售【搞趣日报】...
  8. 论文必备:如何用卡片法写论文?
  9. 安卓开发eclipse+adt下载
  10. 2020 智慧城市解决方案(智慧城市系统及相关技术)