数据化审计:问题导向、应用至上、解决痛点
内容摘要
- 交易者账户和其控制的“影子账户”往往在时、空上有一定频率的交集。
- 从交易数据中,找到这些频繁出现的交易集合,也就能找到相应的“影子账户”。
- 数据挖掘中的关联规则挖掘就是这样一种挖掘频繁集的算法,可以让“影子账户”无所遁形。
好久不发技术贴,晚上被问到,就整理了下发出来。
代码很粗糙,专业人士请忽略!
重要声明
本文中的所有信息和数据都是虚拟的,仅为说明数据化审计的思路和过程,不代表真实的交易情况。
所有的数据都是使用Python的faker库生成,非真实数据,并根据分析需要进行了调整,不涉及个人信息。
风控业务背景
在内部审计、风险预警、反欺诈等风险控制过程中,很多可疑交易往往不是使用交易者自己的账户进行,而是通过其控制的“影子账户”进行。
大量的业务实践也表明,交易者自己的账户和“影子账户”往往在时、空上有一定频率的交集。从大量的交易数据中,找到这些频繁出现的交易集合,也就能找到相应的“影子账户”。
数据挖掘中的关联规则挖掘就是这样一种挖掘频繁集的算法,可以让“影子账户”无所遁形。
关于数据挖掘的一些基本信息,可参见《审计思考 | 大数据分析技术在内部审计循环中的应用》一文。
什么是关联规则挖掘
1.学术定义
数据挖掘中的关联规则定义如下:
2.通俗表述
学术定义看上去比较复杂,简单一点,关联规则可以表述为“如果发生这种情况,则可能发生以下情况。”也就是在项目A发生的情况下,项目B有多大的概率可能发生。
在《审计思考 | 和数据化审计相关的几个“吓人”名词》一文中,也举个一个应用关联规则挖掘的例子:
拿到费用支出数据,整理出支付对象,分析单据交易对手之间的关系…… 嗯?甲客户怎么总是和表面没啥关系的乙客户出现在同一批次的单据中?确认一下这条关联规则的支持度(Support)和置信度(Confidence),聚焦力量检查。
3.重要参数
描述关联规则算法有三个参数:支持度、置信度与提升度。
数据分析环境
Python是一种解释型、面向对象、动态数据类型的高级程序设计语言,具有丰富、强大的库,功能全。基于Python环境引入Orange库,将交易时间接近的账号交易作为一个会话,并在此基础上,设置一定的置信度、支持度,提取关联规则,找到总是同时出现的账户。
本文分析所使用的环境具体如下:
软件或环境 | 说明 |
Win10 64位 | 系统环境 |
Python 2.7 | 数据分析语言平台 |
pandas 0.20.3 | Excel数据读取和处理 |
Orange | 数据挖掘包 |
数据分析过程
代码可以按住屏幕,左右滑动查看
1.环境初始化和公共函数定义
1# coding: utf-8
2
3# 引入库
4import pandas as pd
5import Orange
6import codecs
7
8# 函数logInfo
9# 写信息到指定的文本文件中,用于存放中间数据
10def logInfo(info,logfile=''):
11 if logfile == '':
12 logfile = 'result.basket'
13 logfp = codecs.open(logfile,mode='a',encoding='utf-8')
14 try:
15 logfp.write(info+'\r\n')
16 finally:
17 logfp.close()
2.数据预处理
提取交易数据,包括如下字段:交易地点、交易日期、交易时间、账户。原始的交易数据是一条条记录,关联规则算法需要处理的是一个个会话,也就是所谓的购物篮数据。
所谓购物篮数据,就是类似于超市场的购物篮,每次购买的东西放在一个篮子里,每个篮子都是一组,基于此数据才能挖掘哪些商品是存在购买中的关联行为的。
所以,需要根据行式的交易记录,构建购物篮形式的数据。从业务实践看,在同一个地点交易,如果是同一个人持两个账户,交易间隔比较接近。
基于此,假设5分钟之内的所有账户交易为一个“购物篮”。(更优的算法是,两个没有交易的较大间隔中的交易为一个“购物篮”)
1##
2## 将相近的交易(如5分钟)视为一个会话
3## 从交易记录文件生成购物篮数据
4##
5def Record2Basket(filename=''):
6 data = pd.read_csv(u'交易数据.txt',sep=',',header=0,usecols=[u'交易地点',u'交易日期',u'交易时间',u'账户'],dtype={u'交易地点':str,u'交易日期':str,u'交易时间':str,u'账户':str})
7 data = data.dropna(how='any')
8 datagrp = data.groupby([u'交易地点',u'交易日期'],sort=True)
9 for name,subgrp in datagrp:
10 subgrprowsnum = subgrp.count(0)[0]
11 if subgrprowsnum > 1:
12 subgrp = subgrp.sort_values(by=u'交易时间',ascending=True) #根据时间排序
13 begintime = subgrp.iloc[0,2]
14 Titems = subgrp.iloc[0,3]
15 for i in range(1,subgrprowsnum):
16 endtime = subgrp.iloc[i,2]
17 timegap = (pd.to_datetime(endtime) - pd.to_datetime(begintime)).total_seconds()
18 if abs(timegap) <=5*60:
19 Titems = Titems + ',' + subgrp.iloc[i,3]
20 else:
21 if len(Titems.split(','))>1 :
22 print Titems
23 logInfo(info=Titems,logfile = 'result.basket')
24 Titems = subgrp.iloc[i,3]
25 begintime = endtime
26 if len(Titems.split(','))>1 :
27 print Titems
28 logInfo(info=Titems,logfile = 'result.basket')
3.提取关联规则
基于处理后的交易数据result.basket,提取关联规则。输出到屏幕,同时存入到规则文件rules.txt。
1# 调用函数 生成购物篮数据
2Record2Basket(u'交易数据.txt')
3# 读入生成的购物篮数据
4data = Orange.data.Table('result.basket')
5# 三个参数可以根据实际数据进行调整
6rules = Orange.associate.AssociationRulesSparseInducer(data, support = 0.000166, confidence=0.8,maxItemSets=1500000)
7print "%4s %6s %5s %6s %s" % ("Index","Supp", "Conf", "Lift", "Rule")
8for index, r in enumerate(rules):
9 print "%03d %6.6f %5.3f %6.6f %s %s %s" % (index+1, r.support, r.confidence, r.lift, r, r.left.get_metas(str).items()[0][0], r.right.get_metas(str).items()[0][0])
10 logInfo(info="%03d %6.6f %5.3f %6.6f %s %s %s" % (index+1, r.support, r.confidence, r.lift, r, r.left.get_metas(str).items()[0][0], r.right.get_metas(str).items()[0][0]),logfile='rules.txt')