SynchroTrap欺诈检测算法代码实操示例

有了这篇社交网络恶意账户检测利器对SynchroTrap的理解基础,打算跟着小伍哥的文章基于同步行为的反欺诈算法SynchroTrap实现细节来实践一下了。其实在第一次看到SynchroTrap这个概念时,哪怕给了实操案例还是懵懵的,后面找到了SynchroTrap介绍的12页原始论文来看,顺便翻译成万字长文分享出来,再回看这些介绍文章会清晰很多。

1. 场景描述通过SynchroTrap思想检测某电商平台的商户评价是否异常,比如是否存在刷评现象,可用数据为买家ID、卖家ID和评价日期。

2. 构造示例样本

import pandas as pddata = pd.DataFrame({    'Buy':['BUY_03','BUY_02','BUY_01','BUY_04','BUY_03','BUY_02','BUY_01','BUY_04','BUY_02','BUY_01'],    'Times':['2021-11-16 00:03:32','2021-11-16 00:12:23','2021-11-16 00:22:07','2021-11-16 21:10:24','2021-11-16 21:18:05','2021-11-16 21:22:02','2021-11-16 21:42:57','2021-11-16 23:51:39','2021-11-17 07:01:01','2021-11-17 07:01:03'],    'Seller':['Y','Y','Y','E','E','E','E','Y','Y','Y']    })
图片

如第一行代表买家BUY_03在2021-11-16 00:03:32时对卖家Y的产品作出评价。

3. User-pair comparison

  • 时间切片处理

滑动窗口选择2小时(tsim=1h)

import datetimedef Time2Str(tsm):    t1 = datetime.datetime.fromisoformat(tsm)    t0 = t1-datetime.timedelta(days=0, hours=1)    t2 = t1+datetime.timedelta(days=0, hours=1)    str1 = t0.strftime("%Y%m%d")+'(' +str(t0.hour).rjust(2,'0')+'#'+str(t1.hour).rjust(2,'0')+')'    str2 = t1.strftime("%Y%m%d")+'(' +str(t1.hour).rjust(2,'0')+'#'+str(t2.hour).rjust(2,'0')+')'    return str1+';'+str2
print(Time2Str('2021-11-16 15:51:39'))#测试下df=data.copy()df['tsm'] = df['Times'].apply(Time2Str) # 时间离散
图片
  • 对数据进行裂变

一行变两行,为了实现同一个小时内的两个操作对象能够匹配

df = df.set_index(["Buy", "Times",'Seller'])["tsm"].str.split(";", expand=True)    .stack().reset_index(drop=True, level=-1).reset_index().rename(columns={0: "tsm"})print(df)
图片
  • 加上约束条件匹配数据

以时间约束和商家约束对裂变数据自匹配,删除自己和自己匹配到的无效数据,且限制时间间隔在tsim=1h以内,以便删除重复统计的部分

df_0 = pd.merge(df,df,on =['Seller','tsm'],how='inner')df_1 = df_0[df_0['Buy_x']!=df_0['Buy_y']]df_1=df_1.copy()df_1.loc[:,'diff/d'] = (pd.to_datetime(df_0['Times_x'])-pd.to_datetime(df_0['Times_y'])).dt.seconds/3600/24df_1.loc[:,'diff/h'] = (pd.to_datetime(df_0['Times_x'])-pd.to_datetime(df_0['Times_y'])).dt.seconds/3600df_2=df_1[df_1['diff/h']<=1]df_2 = df_2.sort_values(by=['Buy_x','Times_x','Buy_y'],ascending=True) df_2.head(10)
图片
  • user-pair comparison结果

本次案例中配对成功是指在1小时内买家A和B对同一卖家作出评论,才会计数一次,x∩y列即代表匹配成功次数。需要注意的是,如果在1小时内A和B对同一卖家同时作出多次评论,这里仅计数一次。(思考:是否可以调整权重系数进行优化?)

group=df_2.groupby(['Buy_x','Buy_y']).agg({'Seller': pd.Series.nunique}).reset_index()group.rename(columns={'Seller': "x∩y"},inplace=True)cnt=data.groupby(['Buy']).Times.count().reset_index()tmp_dict = dict(zip(cnt['Buy'],cnt['Times']))group['x_cnt']=group.Buy_x.map(tmp_dict)group['y_cnt']=group.Buy_y.map(tmp_dict)group
图片

4. 聚合多天的数据

假设上面是一天的结果,我们需要对多天的结果进行直接相加汇总,用来近似代表全局的匹配情况。汇总后的数据就不造了,我就把前面生成的group作为多天聚合后的结果来看了。

使用https://flourish.studio/对结果可视化如下,边框越粗代表配对成功的次数越高。

图片

5. User-pair过滤功能直接基于配对成功次数进行过滤,比如阈值设置为2,则圈红数据将会被剔除
图片
基于全局相似度过滤,使用Jaccard相似度,比如对相似度低于30%的进行删除

group['x∪y']=group['x_cnt']+group['y_cnt']-group['x∩y']group['SIM']=group['x∩y']/group['x∪y']group
图片

为什么要计算相似度呢?

举一个极端的例子,假如用户A自己出现了一万次,与B共同出现了5次,那这可能是巧合,但是如果A总共出现了5次,且5次都和B出现,那他俩是团伙的概率要大很多。
到这里同步行为的构图结束,下一步是如何对这些行为进行分群,继续学起来,下一个阶段再见吧!

题图来源:网站Pexels

阅读原文

简介:FRM持证人|传播分享反欺诈风控知识。欢迎关注微信公众号:反欺诈攻防战
(1)
打赏 喜欢就点个赞支持下吧 喜欢就点个赞支持下吧

声明:本文来自“反欺诈攻防战”,分享链接:https://www.zyxiao.com/p/302184    侵权投诉

网站客服
网站客服
内容投稿 侵权处理
分享本页
返回顶部