数据化审计:问题导向、应用至上、解决痛点

内容摘要


  • 交易者账户和其控制的“影子账户”往往在时、空上有一定频率的交集。
  • 从交易数据中,找到这些频繁出现的交易集合,也就能找到相应的“影子账户”。
  • 数据挖掘中的关联规则挖掘就是这样一种挖掘频繁集的算法,可以让“影子账户”无所遁形。

好久不发技术贴,晚上被问到,就整理了下发出来。

代码很粗糙,专业人士请忽略!

重要声明

本文中的所有信息和数据都是虚拟的,仅为说明数据化审计的思路和过程,不代表真实的交易情况。

所有的数据都是使用Python的faker库生成,非真实数据,并根据分析需要进行了调整,不涉及个人信息。

风控业务背景

在内部审计、风险预警、反欺诈等风险控制过程中,很多可疑交易往往不是使用交易者自己的账户进行,而是通过其控制的“影子账户”进行。

大量的业务实践也表明,交易者自己的账户和“影子账户”往往在时、空上有一定频率的交集。从大量的交易数据中,找到这些频繁出现的交易集合,也就能找到相应的“影子账户”。

数据挖掘中的关联规则挖掘就是这样一种挖掘频繁集的算法,可以让“影子账户”无所遁形。

关于数据挖掘的一些基本信息,可参见《审计思考 | 大数据分析技术在内部审计循环中的应用》一文。

什么是关联规则挖掘

1.学术定义

数据挖掘中的关联规则定义如下:

关联规则数据挖掘方法 关联规则挖掘应用_关联规则

2.通俗表述

学术定义看上去比较复杂,简单一点,关联规则可以表述为“如果发生这种情况,则可能发生以下情况。”也就是在项目A发生的情况下,项目B有多大的概率可能发生。

在《审计思考 | 和数据化审计相关的几个“吓人”名词》一文中,也举个一个应用关联规则挖掘的例子:

拿到费用支出数据,整理出支付对象,分析单据交易对手之间的关系…… 嗯?甲客户怎么总是和表面没啥关系的乙客户出现在同一批次的单据中?确认一下这条关联规则的支持度(Support)和置信度(Confidence),聚焦力量检查。

3.重要参数

描述关联规则算法有三个参数:支持度、置信度与提升度

关联规则数据挖掘方法 关联规则挖掘应用_关联规则数据挖掘方法_02

数据分析环境

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')