有了这篇
社交网络恶意账户检测利器
对
SynchroTrap
的理解基础,打算跟着小伍哥的文章
基于同步行为的反欺诈算法SynchroTrap实现细节
来实践一下了。其实在第一次看到
SynchroTrap
这个概念时,哪怕给了实操案例还是懵懵的,后面找到了
SynchroTrap
介绍的12页原始论文来看,顺便翻译成万字长文分享出来,再回看这
些介绍文章会清晰很多。
通过
SynchroTrap
思想检测某电商平台的商户评价是否异常,比如是否存在刷评现象,可用数据为买家ID、卖家ID和评价日期。
import pandas as pd
data = 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']
})
滑动窗口选择2小时(tsim=1h)
import datetime
def 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')+'
str2 = t1.strftime("%Y%m%d")+'(' +str(t1.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/24
df_1.loc[:,'diff/h'] = (pd.to_datetime(df_0['Times_x'])-pd.to_datetime(df_0['Times_y'])).dt.seconds/3600
df_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)
本次案例中配对成功是指在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/对结果可视化如下,边框越粗代表配对成功的次数越高。
-
基于全局相似度过滤,使用Jaccard相似度,比如对相似度低于30%的进行删除
基于全局相似度过滤,使用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
THE END
声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/239522.html