反欺诈与异常点检测

1. 反欺诈检检测

1.1 反欺诈检测的难点

        反诈骗实际是个多分类问题,每种不同的诈骗都当做一种单独的类型。除了欺诈手段多样且持续变化,欺诈检测一般还面临以下问题:

    1. 大部分情况下数据是没有标签的,各种成熟的监督学习没有用武之地;

    2. 区分噪音和异常点时难度很大,甚至需要发挥一点点想象力和直觉;

    3. 当多种诈骗数据混合在一起,区分不同的诈骗类型更难;

         根本原因还是因为我们并不了解每一种诈骗定义。

    4. 即使真的有诈骗的历史数据,在有标签的情况下用监督学习,也存在很大的风险。

         用这样的历史数据学出的模型只能检测曾经出现过与历史诈骗相似的诈骗,而对于变种的诈骗和从未见过的诈骗,模型将无能为力。

        在实际情况中,不建议直接用任何监督学习,至少不能单纯依靠一个监督学习模型来奢求检测到所有的诈骗。一般使用无监督学习,且需要领域专家来验证我们的预测,提供反馈,以便于及时的调整模型。

1.2 解决反欺诈问题的可能手段

1.2.1 迁移学习

        源域样本和目标域样本分布有区别,目标域样本量又不够。通过算法缩小边缘分布之间和条件分布下的差异。

1. 基于实例迁移;

2. 基于特征的迁移;

3. 基于模型的迁移。

缺点:需要拥有与当前目标场景相关的源域数据。

1.2.2 专家模型

        根据专家多年从业经验进行定性判断,它根据主观经验进行打分,而不是根据统计分析或者模型算法来进行客观的计算。操作:

1. 凭经验判断特征重要性;

2. 凭经验为变量加权。

缺点:需要大量的行业经验积累,有时候很难让人信服。

1.2.3 无监督算法

        在风控领域中主要使用的是聚类和无监督异常检测。而聚类是发现样本间的相似性,异常检测则是发现样本间的相异性。这里主要介绍聚类算法:

    (1)K-Means

    (2)DBSCAN

        DBSCAN是数据挖掘中最经典基于密度的聚类算法,其核心是:通过某个点 r 邻域内样本点的数量来衡量该点所在空间的密度。和k-means算法的不同的是:

1. 可以不需要事先指定cluster的个数;

2. 可以找出不规则形状的cluster。

    (3)社区发现

        对负样本聚类,将逾期客群描述成欺诈风险信用风险两部分。社区发现算法也是当前识别团伙欺诈的主要手段之一,主要思想是通过知识图谱将小团体筛选出来。在金融领域,聚集意味着风险

2. 异常点检测(Outlier detection)

        又称为离群点检测,是找出与预期对象的行为差异较大的对象的一个检测过程。这些被检测出的对象被称为异常点或离群点。异常点检测应用非常广泛:

1. 信用卡反欺诈

2. 工业损毁检测

3. 广告点击反作弊

4. 刷好评,刷单检测

5. 羊毛党检测

      异常检测一般是无监督的,往往看似是二分类,但其实是多分类(造成异常的原因各不相同)。

2.1 算法假设

  • 异常数据跟样本中大多数数据不太一样;

  • 异常数据在整体数据样本中占比比较小。

2.2 主要思想

        主流异常检测方法都是基于样本(小群体)间的相似度proximity。

1. 距离

2. 密度

3. 角度

4. 隔离所需的难度

5. 簇

    为什么要用无监督异常检测方法?

1. 样本群体有异构成分,可以对样本做筛选;

2. 很多场景没有标签或者标签很少,不能训练监督模型(比如冷启动项目、欺诈模型);

3. 样本总是在发生变换,只能从一个小群体内部发现异常(比如欺诈检测,手段多变,团伙欺诈通常集中在某段时间内);

4. 异常检测假设异常样本占比很少,并且从某种度量上远离其他样本,这符合我们个体欺诈的先验知识。但是在团体欺诈检测中就不太适用了。

2.3 异常点检验常用算法

2.3.1 z-score异常检测

        假设样本服从正态分布,z-score 用于描述样本偏离正态分布的程度。通过计算 $\mu$ 和 $\sigma$ 得到当前样本所属于的正态分布的表达式,然后分别计算每个样本在这个概率密度函数下被生成的概率,当概率小于某一阈值时,认为这个样本是不属于这个分布的,因此定义为异常值。

计算公式:Z-score = (x -μ) /δ

68% 的数据分布在 +/- 1 倍标准差之间;

95% 的数据分布在 +/- 2 倍标准差之间;

99.7% 的数据分布在 +/- 3 倍标准差之间。

结论:如果一个数据计算出它的z-score >2 甚至>3 说明这个数据和其它数据之间有很大差别。

缺点:需要假设样本满足正态分布,而我们大部分场景都不满足这种假设条件。

2.3.2 Local Outlier Factor

        LOF是基于密度的经典算法,在 LOF 之前的异常检测算法大多是基于统计方法的,或者是借用了一些聚类算法用于异常点的识别(如DBSCAN)。

1. 基于统计的异常检测算法通常需要假设数据服从特定的概率分布,但假设往往不成立;

2. 聚类方法通常只能给出 0/1 的判断(即:是不是异常点),不能量化每个数据点的异常程度;

3. 基于密度的LOF算法要更简单、直观,不需要对数据的分布做太多要求,还能量化每个数据点的异常程度(outlierness)。

        LOF会为每一个数据点计算出一个分数,通过这个分数的大小来判断数据是否异常。

    LOF ≈1 ⇒ 非异常;

    LOF ≫1 ⇒ 异常。

LOF计算过程:

1. 确定近邻点数量K;

2. LOF通过计算最近的K个点的距离来计算密度,然后将其与其它点的密度进行比较;

3. K的选择会对结果产生影响:

    选择比较小的K值,会只计算附近的点,但会受到噪声的影响;

    如果K选的比较大,可能会错过局部离群点。

几种距离简介:  

(1)K-邻近距离(k-distance):

       k-distance即点到第k个邻居的距离,如果k为3,则k-distance将是点到第三最近点的距离。

(2)可达距离(reachability distance): 表示的是两个点的距离和第二个点的k-distance中的最大值。

  reach-dist(a,b) = max{k-distance(b), dist(a,b)}

        如果点a在点b的k个邻居内,则reach-dist(a,b)将是b的k-距离。否则,它将是a和b的实际距离。为了便于理解,可以当做两点之间的距离。

(3)局部可达密度lrd(local reachability densit):

         LRD可以通过reach-dist计算得出,点a的lrd,首先计算a到它的所有k个最近邻居的reach-dist,并取该数字的平均值,lrd是该平均值的倒数。 LRD代表一种密度,因此,到下一个近邻点的距离越长,相应点所在的区域就越稀疏。反之密度越小。

    lrd(a) = 1/(sum(reach-dist(a,n))/k)

    LRD告诉我们,从一点到另一个点或者另一堆点,距离多远。(LRD越小,密度越低,距离越远)。

    (4)LOF 局部异常因子(local outlier factor):

    将每个点的lrd与它们的k个邻居的lrd相比较

1. 某点的LOF: K个邻居的LRD的平均值/该点的LRD;

2. LRD 越小,密度越低,距离越远,离群点的LRD小,它的邻居的LRD会比较大;

3. 离群点的LOF:  较大的邻居的LRD平均值/ 较小的离群点的LRD >>1。

    根据局部异常因子的定义:

1. 如果数据点 p 的 LOF 得分在1附近,表明数据点p的局部密度跟它的邻居们差不多;

2. 如果数据点 p 的 LOF 得分小于1,表明数据点p处在一个相对密集的区域,不像是一个异常点;

3. 如果数据点 p 的 LOF 得分远大于1,表明数据点p跟其他点比较疏远,很有可能是一个异常点。

    LOF算法流程:

(1)首先对样本空间进行去重,分别计算每一个样本到样本空间内其余点的距离;

(2)将步骤1 中的距离升序排列;

(3)指定近邻样本个数k,对于每个样本点,寻找其k近邻样本,然后计算LOF分数,作为异常分数。

        PyOD是一个用于检测数据中异常值的库。它提供对20多种不同算法的访问,以检测异常值。

from pyod.models.lof import LOF
clf = LOF(n_neighbors=20, algorithm='auto') # auto会根据传入的数据自动选择最合适算法
clf.fit(x)
train['out_pred'] = clf.predict_proba(x)[:,1]
key = train['out_pred'].quantile(0.93)
x = train[train.out_pred < key][feature_lst]
y = train[train.out_pred < key]['label']
val_x, val_y = val[feature_lst], val['label']

lr_model = LogisticRegression(C=0.1, class_weight='balanced')
lr_model.fit(x, y)
y_pred = lr_model.predict_proba(x)[:,1]
fpr_lr_train, tpr_lr_train, _ = roc_curve(y, y_pred)
train_ks = abs(fpr_lr_train - tpr_lr_train).max()
print('train_ks : ', train_ks)

   画出相应orc曲线

y_pred = lr_model.predict_proba(val_x)[:,1]
fpr_lr, tpr_lr, _ = roc_curve(val_y, y_pred)
val_ks = abs(fpr_lr - tpr_lr).max()
print('val_ks : ', val_ks)
from matplotlib import pyplot as plt
plt.plot(fpr_lr_train, tpr_lr_train, label = 'train LR')
plt.plot(fpr_lr, tpr_lr, label = 'evl LR')
plt.plot([0,1], [0,1], 'k--')
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC Curve')
plt.legend(loc='best')
plt.show()

    算法应用:

        LOF 算法需要计算数据点两两之间的距离,造成整个算法时间复杂度为 $O(n^2)$

        LOF算法中关于局部可达密度的定义暗含了一个假设,即:不存在>= k 个重复的点。当这样的重复点存在的时候,这些点的平均可达距离为零,局部可达密度就变为无穷大,会给计算带来一些麻烦。在实际应用时,为了避免这样的情况出现,可以把 k-distance 改为 k-distinct-distance,不考虑重复的情况。或者,还可以考虑给可达距离都加一个很小的值,避免可达距离等于零。

        为了提高算法效率,2012年提出了FastLOF 算法:先将整个数据随机的分成多个子集,然后在每个子集里计算 LOF 值。对于那些 LOF 异常得分<=1 的,从数据集里剔除,剩下的在下一轮寻找更合适的 nearest-neighbor,并更新 LOF 值。这种先将数据粗略分成多个部分,然后根据局部计算结果将数据过滤来减少计算量的想法,并不罕见。比如,为了改进 K-means 的计算效率, Canopy Clustering 算法也采用过比较相似的做法。
参考:不均衡学习和异常检测_正负样本不均衡异常检测-CSDN博客

2.3.3 孤立森林(Isolation Forest)

基本想法:

(1)一维数组

1. 假设现在有一组一维数据,我们要对这组数据进行随机切分,希望可以把点 A 和点 B 单独切分出来;

2. 先在最大值和最小值之间随机选择一个值 x,然后按照 <x 和 >=x 可以把数据分成左右两组;

3. 在这两组数据中分别重复这个步骤,直到数据不可再分。点 B 跟其他数据比较疏离,可能用很少的次数就可以把它切分出来;

4. 点 A 跟其他数据点聚在一起,可能需要更多的次数才能把它切分出来。

(2)二维数组

1. 先随机选择一个特征维度,在这个特征的最大值和最小值之间随机选择一个值,按照跟特征值的大小关系将数据进行左右切分;

2. 在左右两组数据中重复上述步骤,随机按某个特征维度的取值把数据细分,直到无法细分(剩下一个数据点,或剩下的数据都相同)。

3. 点B'跟其他数据点比较疏离,可能只需要很少的几次操作就可以将它细分出来;点A'需要的切分次数可能会更多一些。

按照之前提到的关于“异常”的两个假设,一般情况下在上面的例子中:

1. 点B和点B' 由于跟其他数据隔的比较远,会被认为是异常数据,而点A和点A' 会被认为是正常数据

2. 直观上,异常数据由于跟其他数据点较为疏离,可能需要较少几次切分就可以将它们单独划分出来,而正常数据恰恰相反。

3. 这正是Isolation Forest的核心概念。IF采用二叉树去对数据进行切分,数据点在二叉树中所处的深度反应了该条数据的“疏离”程度。

整个算法大致可以分为两步:

    (1)训练:抽取多个样本,构建多棵二叉树iTree;

        构建一棵 iTree 时,先从全量数据中抽取一批样本,然后随机选择一个特征作为起始节点,并在该特征的最大值和最小值之间随机选择一个值,将样本中小于该取值的数据划到左分支,大于等于该取值的划到右分支。然后,在左右两个分支数据中,重复上述步骤,直到满足如下条件:

1. 数据不可再分(只包含一条数据,或者全部数据相同);

2. 二叉树达到限定的最大深度。

    (2)预测:综合多棵二叉树的结果,计算每个数据点的异常分值。

        计算数据 x 的异常分值时,先要估算它在每棵 iTree 中的路径长度(深度)。具体的,先沿着一棵 iTree,从根节点开始按不同特征的取值从上往下,直到到达某叶子节点。假设 iTree 的训练样本中同样落在 x 所在叶子节点的样本数为 T.size,则数据 x 在这棵 iTree 上的路径长度 h(x)。

e 表示数据 x 从 iTree 的根节点到叶节点过程中经过的边的数目;

C(T.size) 可以认为是一个修正值,它表示在一棵用 T.size 条样本数据构建的二叉树的平均路径长度。

        从异常分值的公式看:

1. 如果数据 x 在多棵 iTree 中的平均路径长度越短,得分越接近 1,表明数据 x 越异常;

2. 如果数据 x 在多棵 iTree 中的平均路径长度越长,得分越接近 0,表示数据 x 越正常;

3. 如果数据 x 在多棵 iTree 中的平均路径长度接近整体均值,则打分会在 0.5 附近。

data = pd.read_csv('Bcard.txt')
train = data[data.obs_mth != '2018-11-30'].reset_index().copy()
val = data[data.obs_mth == '2018-11-30'].reset_index().copy()
feature_lst = ['person_info','finance_info']
x, y = train[feature_lst], train['label']
val_x, val_y =  val[feature_lst], val['label']
lr_model = LogisticRegression(C=0.1,class_weight='balanced')
lr_model.fit(x,y)
y_pred = lr_model.predict_proba(x)[:,1]
fpr_lr_train, tpr_lr_train, _ = roc_curve(y, y_pred)
train_ks = abs(fpr_lr_train - tpr_lr_train).max()
print('train_ks : ', train_ks)
y_pred = lr_model.predict_proba(val_x)[:,1]
fpr_lr, tpr_lr, _ = roc_curve(val_y, y_pred)
val_ks = abs(fpr_lr - tpr_lr).max()
print('val_ks : ', val_ks)

        对原有数据进行清洗,将异常样本通过无监督算法进行筛选。

from pyod.models.iforest import IForest
# 'new' 为了兼容后续版本
clf = IForest(behaviour='new', n_estimators=500, n_jobs=-1) 
clf.fit(x)

# 去掉原有数据中异常值可能性较大的进行建模
out_pred = clf.predict_proba(x, method ='linear')[:,1]
train['out_pred'] = out_pred
x = train[train.out_pred< 0.7][feature_lst]
y = train[train.out_pred < 0.7]['label']
val_x, val_y =  val[feature_lst], val['label']
lr_model = LogisticRegression(C=0.1, class_weight='balanced')
lr_model.fit(x,y)
y_pred = lr_model.predict_proba(x)[:,1]
fpr_lr_train,tpr_lr_train,_ = roc_curve(y,y_pred)
train_ks = abs(fpr_lr_train - tpr_lr_train).max()
print('train_ks : ',train_ks)

    通过样本异常程度进行分析:

  train.out_pred.groupby(train.obs_mth).mean()

如果某个月份的平均异常概率较高/方差较大,需要查明原因(渠道问题,运营动作导致...)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/339173.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

反序列化字符串逃逸(下篇)

这里承接上篇文章反序列化字符串逃逸&#xff08;上篇&#xff09;-CSDN博客带大家学习反序列化字符串逃逸减少&#xff0c;没有看过的可以先去看看&#xff0c;不会吃亏。 例题&#xff1a; <?php highlight_file(__FILE__); error_reporting(0); function filter($name…

vectorCast基于分类树设计测试用例

根据代码的条件,以图表的形式为大家展示出各个变量组合的等价类划分。性别分为2类,年龄分为3类,工作年数分为3类。 那么它们最全面的组合结果就是2*3*3=18 也就是说它们最多有18种组合情况的测试用例 2.选中该函数,点击右键 3.自动生成一个map的基于分类树的测试用例 4.此…

commit 历史版本记录修正

commit 历史版本记录修正 当 Bug 发生的时候&#xff0c;我们会需要去追踪特定 bug 的历史记录&#xff0c;以查出该 bug 真正发生的原因&#xff0c;这个时候就是版本控制带来最大价值的时候。 因此&#xff0c;要怎样维持一个好的版本记录是非常重要的&#xff0c;下面是一…

机器学习--Matplotlib

机器学习–Matplotlib Matplotlib 是专门用于开发2D图表(包括3D图表)以渐进、交互式方式实现数据可视化 简单的Matplotlib画图 — 以折线图为例 matplotlib.pyplot模块 matplotlib.pytplot包含了一系列类似于matlab的画图函数。 import matplotlib.pyplot as plt图形绘制流…

7.【CPP】String类

一.汉字的编码 我们知道计算机存储英文字母&#xff0c;标点&#xff0c;数字用的是ascall码&#xff0c;128种用一个字节表示绰绰有余。而汉字远远不止128种&#xff0c;因此汉字需要两个字节表示。 1.gbk编码中汉字占两个字节。 2.utf-8中&#xff0c;一个汉字占三个字节。…

Java - 深入四大限流算法:原理、实现与应用

文章目录 Pre概述简单计数器原理实现测试优缺点 滑动窗口算法原理实现测试优缺点 漏桶算法原理实现测试优缺点 令牌桶算法原理实现测试优缺点 小结 Pre 深入理解分布式技术 - 限流 并发编程-25 高并发处理手段之消息队列思路 应用拆分思路 应用限流思路 SpringBoot - 优雅…

(上) C语言中的语句分类及分支语句:if语句、switch语句介绍

目录 前言 一、语句的分类 1. 空语句 2. 表达式语句 3. 函数调用语句 4. 复合语句 5. 控制语句 二、分支语句 1. if语句 (1) if的使用 (2) else的使用 (3) 分支中包含多条语句 (4) 嵌套if (5) 悬空else问题 2. switch语句 (1) if语句和switch语句的对比 (2) s…

摇臂MG995舵机模块实战教程

简介 舵机也叫伺服电机&#xff0c;最早用于船舶上实现其转向功能&#xff0c;由于可以通过程序连续控制其转角&#xff0c;因而被广泛应用智能小车以实现转向以及机器人各类关节运动中。舵机&#xff08;英文叫Servo&#xff09;&#xff1a;它由直流电机、减速齿轮组、传感器…

计算机网络——面试问题

1 从输⼊ URL 到⻚⾯展示到底发⽣了什么&#xff1f; 1. 先检查浏览器缓存⾥是否有缓存该资源&#xff0c;如果有直接返回&#xff1b;如果没有进⼊下⼀ 步⽹络请求。 2. ⽹络请求前&#xff0c;进⾏ DNS 解析 &#xff0c;以获取请求域名的 IP地址 。 3. 浏览器与服务器…

Sqoop与Kafka的集成:实时数据导入

将Sqoop与Kafka集成是实现实时数据导入和流处理的关键步骤之一。Sqoop用于将数据从关系型数据库导入到Hadoop生态系统中&#xff0c;而Kafka则用于数据流的传输和处理。本文将深入探讨如何使用Sqoop与Kafka集成&#xff0c;提供详细的步骤、示例代码和最佳实践&#xff0c;以确…

Git与GitHub零基础教学

大家好&#xff0c;我是星恒&#xff0c;这个帖子给大家分享的是git和github的全套教程&#xff0c;包含github初始&#xff0c;git常用命令以及基本使用&#xff0c;git的ssh链接github&#xff0c;github使用token登录&#xff0c;github和idea的配合&#xff0c;一些平时常用…

适合初学者的 机器学习 资料合集(可快速下载)

AI时代已经来临&#xff0c;机器学习成为了当今的热潮。但是&#xff0c;很多人在面对机器学习时却不知道如何开始学习。 今天&#xff0c;我为大家推荐几个适合初学者的机器学习开源项目&#xff0c;帮助大家更好地了解和掌握机器学习的知识。这些项目都是开源的&#xff0c;…

EtherNet/IP开发:C++开发CIP源代码

① 介绍一下CIP CIP是一种考虑到自动化行业而设计的通用协议。然而&#xff0c;由于其开放性&#xff0c;它可以并且已经应用于更多的领域。CIP网络库包含若干卷&#xff1a; 第1卷介绍了适用于所有网络自适应的CIP的常见方面。本卷包含通用对象库和设备配置文件库&#xff0…

信息安全的脆弱性及常见安全攻击

目录 信息安全概述信息安全现状及挑战传统安全防护逐步失效 安全风险能见度不足看不清资产看不见新型威胁看不见内网潜藏风险 常见的网络安全术语信息安全的脆弱性及常见安全攻击网络环境的开放性协议栈的脆弱性及常见攻击常见安全风险 协议栈自身的脆弱性网络的基本攻击模式 链…

Dubbo的几个序列化方式

欢迎订阅专栏&#xff0c;会分享Dubbo里面相关的技术实现 这篇文章就不详细的介绍每种序列化方式的实现细节&#xff0c;大家可以自行去问度娘&#xff0c;我也会找一些资料。需要注意的是&#xff0c;这个先后顺序不表示性能优越 ObjectInput、ObjectOutput 这两是Dubbo序列…

Linux_清理docker磁盘占用

文章目录 前言一、docker system 命令1. docker system df&#xff08;本文重点使用&#xff09;2. docker system prune&#xff08;本文重点使用&#xff09;3. docker system info4. docker system events 二、开始清理三、单独清理Build Cache四、单独清理未被使用的网络 前…

如何理解 GO 语言的接口 - 鸭子模型

个人认为&#xff0c;要理解 Go 的接口&#xff0c;一定先了解下鸭子模型。 鸭子模型 那什么鸭子模型&#xff1f; 鸭子模型的解释&#xff0c;通常会用了一个非常有趣的例子&#xff0c;一个东西究竟是不是鸭子&#xff0c;取决于它的能力。游泳起来像鸭子、叫起来也像鸭子…

【Emgu CV教程】5.6、几何变换之LinearPolar()极坐标变换

LinearPolar()线性极坐标转换函数用于将图像从笛卡尔坐标系转换为极坐标系&#xff0c;太难懂了&#xff0c;还是简单的说吧 笛卡尔坐标系就是平面直角坐标系&#xff0c;用X轴、Y轴表示的图像&#xff0c;最常用的表示方式&#xff0c;比如灰度图Point(360,100) 230&#xff…

数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)四

第五部分、数组和广义表详解 数组和广义表&#xff0c;都用于存储逻辑关系为“一对一”的数据。 数组存储结构&#xff0c;99% 的编程语言都包含的存储结构&#xff0c;用于存储不可再分的单一数据&#xff1b;而广义表不同&#xff0c;它还可以存储子广义表。 本章重点从矩阵…

【工具使用】Keil5软件使用-基础使用篇

一、概述 本文面向未接触过Keil的新手&#xff0c;如果是职场老手可跳过此篇。为了快速上手&#xff0c;本文会跳过很多细节及解释&#xff0c;如需要了解原理&#xff0c;请移步进阶篇。 二、 软件介绍 Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调…