diff --git a/AnomalyDetection/img/5k1sASfi9gVpcrt6bCpE8ac-7XGQlEhRydpM7L2EHZM.original.fullsize.png b/AnomalyDetection/img/5k1sASfi9gVpcrt6bCpE8ac-7XGQlEhRydpM7L2EHZM.original.fullsize.png new file mode 100644 index 0000000..de87b27 Binary files /dev/null and b/AnomalyDetection/img/5k1sASfi9gVpcrt6bCpE8ac-7XGQlEhRydpM7L2EHZM.original.fullsize.png differ diff --git a/AnomalyDetection/img/APsWDfG-1NDc-z--7wVPsBICFs7Vvwt0v3T7VZwGvxg.original.fullsize.png b/AnomalyDetection/img/APsWDfG-1NDc-z--7wVPsBICFs7Vvwt0v3T7VZwGvxg.original.fullsize.png new file mode 100644 index 0000000..91bfa2e Binary files /dev/null and b/AnomalyDetection/img/APsWDfG-1NDc-z--7wVPsBICFs7Vvwt0v3T7VZwGvxg.original.fullsize.png differ diff --git a/AnomalyDetection/img/EVHASE85aZeCS43XNaCfsDK6DOJk-WOhXv7KHwo0EoA.original.fullsize.png b/AnomalyDetection/img/EVHASE85aZeCS43XNaCfsDK6DOJk-WOhXv7KHwo0EoA.original.fullsize.png new file mode 100644 index 0000000..9b223e8 Binary files /dev/null and b/AnomalyDetection/img/EVHASE85aZeCS43XNaCfsDK6DOJk-WOhXv7KHwo0EoA.original.fullsize.png differ diff --git a/AnomalyDetection/img/He6GRseNHy5vCD28xNr5O4wIMSBYC_CMmpmjmWTocg8.original.fullsize.png b/AnomalyDetection/img/He6GRseNHy5vCD28xNr5O4wIMSBYC_CMmpmjmWTocg8.original.fullsize.png new file mode 100644 index 0000000..62acda9 Binary files /dev/null and b/AnomalyDetection/img/He6GRseNHy5vCD28xNr5O4wIMSBYC_CMmpmjmWTocg8.original.fullsize.png differ diff --git a/AnomalyDetection/img/N47Ra3UY3ONpe6opMQoM-LjiauCBqRHf9jISb2yk2As.original.fullsize.png b/AnomalyDetection/img/N47Ra3UY3ONpe6opMQoM-LjiauCBqRHf9jISb2yk2As.original.fullsize.png new file mode 100644 index 0000000..df66d95 Binary files /dev/null and b/AnomalyDetection/img/N47Ra3UY3ONpe6opMQoM-LjiauCBqRHf9jISb2yk2As.original.fullsize.png differ diff --git a/AnomalyDetection/img/UWiX5C7kCHx5yX7O9yQm9F1ndg-QgMqS3BAwIWPB40k.original.fullsize-1609839833441.png b/AnomalyDetection/img/UWiX5C7kCHx5yX7O9yQm9F1ndg-QgMqS3BAwIWPB40k.original.fullsize-1609839833441.png new file mode 100644 index 0000000..395bb46 Binary files /dev/null and b/AnomalyDetection/img/UWiX5C7kCHx5yX7O9yQm9F1ndg-QgMqS3BAwIWPB40k.original.fullsize-1609839833441.png differ diff --git a/AnomalyDetection/img/UWiX5C7kCHx5yX7O9yQm9F1ndg-QgMqS3BAwIWPB40k.original.fullsize.png b/AnomalyDetection/img/UWiX5C7kCHx5yX7O9yQm9F1ndg-QgMqS3BAwIWPB40k.original.fullsize.png new file mode 100644 index 0000000..395bb46 Binary files /dev/null and b/AnomalyDetection/img/UWiX5C7kCHx5yX7O9yQm9F1ndg-QgMqS3BAwIWPB40k.original.fullsize.png differ diff --git a/AnomalyDetection/img/cTjP7hnGGCB-h8sfZLCJio9oqUYvs-sdoxpSRtoGCjE.original.fullsize.png b/AnomalyDetection/img/cTjP7hnGGCB-h8sfZLCJio9oqUYvs-sdoxpSRtoGCjE.original.fullsize.png new file mode 100644 index 0000000..a639b15 Binary files /dev/null and b/AnomalyDetection/img/cTjP7hnGGCB-h8sfZLCJio9oqUYvs-sdoxpSRtoGCjE.original.fullsize.png differ diff --git a/AnomalyDetection/img/fOfAz4nhVr7COjlNqCN_AxWiZgVElfaJq6SS8uSjBR4.original.fullsize.png b/AnomalyDetection/img/fOfAz4nhVr7COjlNqCN_AxWiZgVElfaJq6SS8uSjBR4.original.fullsize.png new file mode 100644 index 0000000..12105c7 Binary files /dev/null and b/AnomalyDetection/img/fOfAz4nhVr7COjlNqCN_AxWiZgVElfaJq6SS8uSjBR4.original.fullsize.png differ diff --git a/AnomalyDetection/img/image-20210103174850565.png b/AnomalyDetection/img/image-20210103174850565.png new file mode 100644 index 0000000..a7de317 Binary files /dev/null and b/AnomalyDetection/img/image-20210103174850565.png differ diff --git a/AnomalyDetection/img/image-20210103174904734.png b/AnomalyDetection/img/image-20210103174904734.png new file mode 100644 index 0000000..34ebc98 Binary files /dev/null and b/AnomalyDetection/img/image-20210103174904734.png differ diff --git a/AnomalyDetection/img/image-20210103182254793.png b/AnomalyDetection/img/image-20210103182254793.png new file mode 100644 index 0000000..8344ff7 Binary files /dev/null and b/AnomalyDetection/img/image-20210103182254793.png differ diff --git a/AnomalyDetection/img/image-20210103183909407.png b/AnomalyDetection/img/image-20210103183909407.png new file mode 100644 index 0000000..3da07c3 Binary files /dev/null and b/AnomalyDetection/img/image-20210103183909407.png differ diff --git a/AnomalyDetection/img/image-20210104144520790.png b/AnomalyDetection/img/image-20210104144520790.png new file mode 100644 index 0000000..fe1afbf Binary files /dev/null and b/AnomalyDetection/img/image-20210104144520790.png differ diff --git a/AnomalyDetection/img/image-20210104144603849.png b/AnomalyDetection/img/image-20210104144603849.png new file mode 100644 index 0000000..7e9a54a Binary files /dev/null and b/AnomalyDetection/img/image-20210104144603849.png differ diff --git a/AnomalyDetection/img/image-20210104150718935.png b/AnomalyDetection/img/image-20210104150718935.png new file mode 100644 index 0000000..1a2f7b4 Binary files /dev/null and b/AnomalyDetection/img/image-20210104150718935.png differ diff --git a/AnomalyDetection/img/image-20210105140222697-1609839336763.png b/AnomalyDetection/img/image-20210105140222697-1609839336763.png new file mode 100644 index 0000000..5b2c472 Binary files /dev/null and b/AnomalyDetection/img/image-20210105140222697-1609839336763.png differ diff --git a/AnomalyDetection/img/image-20210105140222697.png b/AnomalyDetection/img/image-20210105140222697.png new file mode 100644 index 0000000..5b2c472 Binary files /dev/null and b/AnomalyDetection/img/image-20210105140222697.png differ diff --git a/AnomalyDetection/img/image-20210105140242611-1609839375267.png b/AnomalyDetection/img/image-20210105140242611-1609839375267.png new file mode 100644 index 0000000..e6af3f9 Binary files /dev/null and b/AnomalyDetection/img/image-20210105140242611-1609839375267.png differ diff --git a/AnomalyDetection/img/image-20210105140242611.png b/AnomalyDetection/img/image-20210105140242611.png new file mode 100644 index 0000000..e6af3f9 Binary files /dev/null and b/AnomalyDetection/img/image-20210105140242611.png differ diff --git a/AnomalyDetection/img/output_28_0-1609839842623.png b/AnomalyDetection/img/output_28_0-1609839842623.png new file mode 100644 index 0000000..239ba47 Binary files /dev/null and b/AnomalyDetection/img/output_28_0-1609839842623.png differ diff --git a/AnomalyDetection/img/output_28_0.png b/AnomalyDetection/img/output_28_0.png new file mode 100644 index 0000000..239ba47 Binary files /dev/null and b/AnomalyDetection/img/output_28_0.png differ diff --git a/AnomalyDetection/img/output_32_0-1609839844832.png b/AnomalyDetection/img/output_32_0-1609839844832.png new file mode 100644 index 0000000..45cf4ef Binary files /dev/null and b/AnomalyDetection/img/output_32_0-1609839844832.png differ diff --git a/AnomalyDetection/img/output_32_0.png b/AnomalyDetection/img/output_32_0.png new file mode 100644 index 0000000..45cf4ef Binary files /dev/null and b/AnomalyDetection/img/output_32_0.png differ diff --git a/AnomalyDetection/img/v2-bb94bcf07ced88315d0a5de47677200e_720w.png b/AnomalyDetection/img/v2-bb94bcf07ced88315d0a5de47677200e_720w.png new file mode 100644 index 0000000..d6794c2 Binary files /dev/null and b/AnomalyDetection/img/v2-bb94bcf07ced88315d0a5de47677200e_720w.png differ diff --git a/AnomalyDetection/img/xQz5G5vBRHR6PIT6oUEnnPZ1hV5ccszHuX_Fya9R6sQ.original.fullsize.png b/AnomalyDetection/img/xQz5G5vBRHR6PIT6oUEnnPZ1hV5ccszHuX_Fya9R6sQ.original.fullsize.png new file mode 100644 index 0000000..b50afe5 Binary files /dev/null and b/AnomalyDetection/img/xQz5G5vBRHR6PIT6oUEnnPZ1hV5ccszHuX_Fya9R6sQ.original.fullsize.png differ diff --git a/AnomalyDetection/img/图4.1距离检测的困境-离群点A-1609839836032.png b/AnomalyDetection/img/图4.1距离检测的困境-离群点A-1609839836032.png new file mode 100644 index 0000000..3c0bea5 Binary files /dev/null and b/AnomalyDetection/img/图4.1距离检测的困境-离群点A-1609839836032.png differ diff --git a/AnomalyDetection/img/图4.1距离检测的困境-离群点A.png b/AnomalyDetection/img/图4.1距离检测的困境-离群点A.png new file mode 100644 index 0000000..3c0bea5 Binary files /dev/null and b/AnomalyDetection/img/图4.1距离检测的困境-离群点A.png differ diff --git a/AnomalyDetection/img/定义3-邻域半径-1609839837759.png b/AnomalyDetection/img/定义3-邻域半径-1609839837759.png new file mode 100644 index 0000000..393671c Binary files /dev/null and b/AnomalyDetection/img/定义3-邻域半径-1609839837759.png differ diff --git a/AnomalyDetection/img/定义3-邻域半径.png b/AnomalyDetection/img/定义3-邻域半径.png new file mode 100644 index 0000000..393671c Binary files /dev/null and b/AnomalyDetection/img/定义3-邻域半径.png differ diff --git a/AnomalyDetection/img/局部异常因子公式-1609839840015.png b/AnomalyDetection/img/局部异常因子公式-1609839840015.png new file mode 100644 index 0000000..3544910 Binary files /dev/null and b/AnomalyDetection/img/局部异常因子公式-1609839840015.png differ diff --git a/AnomalyDetection/img/局部异常因子公式.png b/AnomalyDetection/img/局部异常因子公式.png new file mode 100644 index 0000000..3544910 Binary files /dev/null and b/AnomalyDetection/img/局部异常因子公式.png differ diff --git a/AnomalyDetection/一、概述.md b/AnomalyDetection/一、概述.md new file mode 100644 index 0000000..396ae0e --- /dev/null +++ b/AnomalyDetection/一、概述.md @@ -0,0 +1,172 @@ +## 1、什么是异常检测 + +**异常检测(Outlier Detection)**,顾名思义,是识别与正常数据不同的数据,与预期行为差异大的数据。 + +识别如信用卡欺诈,工业生产异常,网络流里的异常(网络侵入)等问题,针对的是少数的事件。 + + + +### 1.1 异常的类别 + +**点异常**:指的是少数个体实例是异常的,大多数个体实例是正常的,例如正常人与病人的健康指标; + +**上下文异常**:又称上下文异常,指的是在特定情境下个体实例是异常的,在其他情境下都是正常的,例如在特定时间下的温度突然上升或下降,在特定场景中的快速信用卡交易; + +**群体异常**:指的是在群体集合中的个体实例出现异常的情况,而该个体实例自身可能不是异常,例如社交网络中虚假账号形成的集合作为群体异常子集,但子集中的个体节点可能与真实账号一样正常。 + + + +### 1.2 异常检测任务分类 + +**有监督**:训练集的正例和反例均有标签 + +**无监督**:训练集无标签 + +**半监督**:在训练集中只有单一类别(正常实例)的实例,没有异常实例参与训练 + + + +### 1.3 异常检测场景 + +* **故障检测** + +* **物联网异常检测** + +* **欺诈检测** + +* **工业异常检测** + +* **时间序列异常检测** + +* **视频异常检测** + +* **日志异常检测** + +* **医疗日常检测** + +* **网络入侵检测** + + + +## 2、异常检测常用方法 + +### 2.1 传统方法 + +#### 2.1.1 基于统计学的方法 + +统计学方法对数据的正常性做出假定。**它们假定正常的数据对象由一个统计模型产生,而不遵守该模型的数据是异常点。**统计学方法的有效性高度依赖于对给定数据所做的统计模型假定是否成立。 + +异常检测的统计学方法的一般思想是:学习一个拟合给定数据集的生成模型,然后识别该模型低概率区域中的对象,把它们作为异常点。 + +即利用统计学方法建立一个模型,然后考虑对象有多大可能符合该模型。 + +假定输入数据集为$\{x^{(1)}, x^{(2)}, ..., x^{(m)}\}$,数据集中的样本服从正态分布,即$x^{(i)}\sim N(\mu, \sigma^2)$,我们可以根据样本求出参数$\mu$和$\sigma$。 + +$\mu=\frac 1m\sum_{i=1}^m x^{(i)}$ + +$\sigma^2=\frac 1m\sum_{i=1}^m (x^{(i)}-\mu)^2$ + +#### 2.1.2 线性模型 + +典型的如PCA方法,Principle Component Analysis是主成分分析,简称PCA。它的应用场景是对数据集进行降维。降维后的数据能够最大程度地保留原始数据的特征(以数据协方差为衡量标准)。 +PCA的原理是通过构造一个新的特征空间,把原数据映射到这个新的低维空间里。PCA可以提高数据的计算性能,并且缓解"高维灾难"。 + +#### 2.1.3 基于相似度的方法 + +  这类算法适用于数据点的聚集程度高、离群点较少的情况。同时,因为相似度算法通常需要对每一个数据分别进行相应计算,所以这类算法通常计算量大,不太适用于数据量大、维度高的数据。 +  基于相似度的检测方法大致可以分为三类: + ++ 基于集群(簇)的检测,如DBSCAN等聚类算法。 +   聚类算法是将数据点划分为一个个相对密集的“簇”,而那些不能被归为某个簇的点,则被视作离群点。这类算法对簇个数的选择高度敏感,数量选择不当可能造成较多正常值被划为离群点或成小簇的离群点被归为正常。因此对于每一个数据集需要设置特定的参数,才可以保证聚类的效果,在数据集之间的通用性较差。聚类的主要目的通常是为了寻找成簇的数据,而将异常值和噪声一同作为无价值的数据而忽略或丢弃,在专门的异常点检测中使用较少。 +   聚类算法的优缺点: + (1)能够较好发现小簇的异常; + (2)通常用于簇的发现,而对异常值采取丢弃处理,对异常值的处理不够友好; + (3)产生的离群点集和它们的得分可能非常依赖所用的簇的个数和数据中离群点的存在性; + (4)聚类算法产生的簇的质量对该算法产生的离群点的质量影响非常大。 ++ 基于距离的度量,如k近邻算法。 +   k近邻算法的基本思路是对每一个点,计算其与最近k个相邻点的距离,通过距离的大小来判断它是否为离群点。在这里,离群距离大小对k的取值高度敏感。如果k太小(例如1),则少量的邻近离群点可能导致较低的离群点得分;如果k太大,则点数少于k的簇中所有的对象可能都成了离群点。为了使模型更加稳定,距离值的计算通常使用k个最近邻的平均距离。 +   k近邻算法的优缺点: + (1)简单; + (2)基于邻近度的方法需要O(m2)时间,大数据集不适用; + (3)对参数的选择敏感; + (4)不能处理具有不同密度区域的数据集,因为它使用全局阈值,不能考虑这种密度的变化。 ++ 基于密度的度量,如LOF(局部离群因子)算法。 +   局部离群因子(LOF)算法与k近邻类似,不同的是它以相对于其邻居的局部密度偏差而不是距离来进行度量。它将相邻点之间的距离进一步转化为“邻域”,从而得到邻域中点的数量(即密度),认为密度远低于其邻居的样本为异常值。 + LOF(局部离群因子)算法的优缺点: + (1)给出了对离群度的定量度量; + (2)能够很好地处理不同密度区域的数据; + (3)对参数的选择敏感。 + + + +### 2.2 集成方法 + +集成是提高数据挖掘算法精度的常用方法。集成方法将多个算法或多个基检测器的输出结合起来。其基本思想是一些算法在某些子集上表现很好,一些算法在其他子集上表现很好,然后集成起来使得输出更加鲁棒。集成方法与基于子空间方法有着天然的相似性,子空间与不同的点集相关,而集成方法使用基检测器来探索不同维度的子集,将这些基学习器集合起来。 + +常用的集成方法有Feature bagging,孤立森林等。 + +**feature bagging **: + +与bagging法类似,只是对象是feature。 + + + +**孤立森林**: + +孤立森林假设我们用一个随机超平面来切割数据空间,切一次可以生成两个子空间。然后我们继续用随机超平面来切割每个子空间并循环,直到每个子空间只有一个数据点为止。直观上来讲,那些具有高密度的簇需要被切很多次才会将其分离,而那些低密度的点很快就被单独分配到一个子空间了。孤立森林认为这些很快被孤立的点就是异常点。 + +用四个样本做简单直观的理解,d是最早被孤立出来的,所以d最有可能是异常。 + + + +![img](https://pic3.zhimg.com/80/v2-bb94bcf07ced88315d0a5de47677200e_720w.png) + +### 2.3 机器学习 + +在有标签的情况下,可以使用树模型(gbdt,xgboost等)进行分类,缺点是异常检测场景下数据标签是不均衡的,但是利用机器学习算法的好处是可以构造不同特征。 + + + +## 3、异常检测常用开源库 + +**Scikit-learn:** + +**Scikit-learn**是一个Python语言的开源机器学习库。它具有各种分类,回归和聚类算法。也包含了一些异常检测算法,例如LOF和孤立森林。 + +官网:https://scikit-learn.org/stable/ + + + +**PyOD:** + +> **[Python Outlier Detection(PyOD)](https://link.zhihu.com/?target=https%3A//github.com/yzhao062/pyod)**是当下最流行的Python异常检测工具库,其主要亮点包括: +> +> - 包括近20种常见的异常检测算法,比如经典的LOF/LOCI/ABOD以及最新的**深度学习**如对抗生成模型(GAN)和**集成异常检测**(outlier ensemble) +> - **支持不同版本的Python**:包括2.7和3.5+;**支持多种操作系统**:windows,macOS和Linux +> - **简单易用且一致的API**,**只需要几行代码就可以完成异常检测**,方便评估大量算法 +> - 使用JIT和并行化(parallelization)进行优化,加速算法运行及扩展性(scalability),可以处理大量数据 +> +> ​ ——https://zhuanlan.zhihu.com/p/58313521 + + + +## 4、练习 + +**1、学习pyod库基本操作** + +(如何生成toy example,了解训练以及预测的api) + +参考资料: + +* https://zhuanlan.zhihu.com/p/58313521(pyod库作者对pyod库的介绍) + +* https://pyod.readthedocs.io/en/latest/ (Pyod库官网) + + + + + +**关于Datawhale**: + +>Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。同时Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。 + diff --git a/AnomalyDetection/三、线性模型.md b/AnomalyDetection/三、线性模型.md new file mode 100644 index 0000000..63654d1 --- /dev/null +++ b/AnomalyDetection/三、线性模型.md @@ -0,0 +1,300 @@ +#异常检测——线性相关方法 + +@(Aaron) [异常检测, 线性方法] + +**主要内容包括:** + +- **线性回归** +- **主成分分析** + +------------------- + +[TOC] + +## 1、引言 + +  真实数据集中不同维度的数据通常具有高度的相关性,这是因为不同的属性往往是由相同的基础过程以密切相关的方式产生的。在古典统计学中,这被称为——**回归建模**,一种参数化的相关性分析。 +  一类相关性分析试图通过其他变量预测单独的属性值,另一类方法用一些潜在变量来代表整个数据。前者的代表是 **线性回归**,后者一个典型的例子是 **主成分分析**。本文将会用这两种典型的线性相关分析方法进行异常检测。 + +  需要明确的是,这里有两个重要的假设: + +  **假设一:近似线性相关假设。线性相关假设是使用两种模型进行异常检测的重要理论基础。** + +  **假设二:子空间假设。子空间假设认为数据是镶嵌在低维子空间中的,线性方法的目的是找到合适的低维子空间使得异常点(o)在其中区别于正常点(n)。** + +  基于这两点假设,在异常检测的第一阶段,为了确定特定的模型是否适合特定的数据集,对数据进行探索性和可视化分析是非常关键的。 +## 2、数据可视化 +  以**breast-cancer-unsupervised-ad**数据集为例做一些简单的数据可视化。 + +```python +#coding:utf-8 +#导入warnings包,利用过滤器来实现忽略警告语句。 +import warnings +warnings.filterwarnings('ignore') + +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import seaborn as sns +import missingno as msno +``` + +```python +## 1) 载入训练集和测试集; +path = 'dataverse_files/' +f=open(path+'breast-cancer-unsupervised-ad.csv') +Train_data = pd.read_csv(f) +``` +```python +## 2) 简略观察数据(head()+shape) +Train_data.head() +``` +![](img/He6GRseNHy5vCD28xNr5O4wIMSBYC_CMmpmjmWTocg8.original.fullsize.png) + +```python +## 2) 简略观察数据(tail()+shape) +Train_data.tail() +``` +![](img/EVHASE85aZeCS43XNaCfsDK6DOJk-WOhXv7KHwo0EoA.original.fullsize.png) + +```python +## 1) 通过describe()来熟悉数据的相关统计量 +Train_data.describe() +``` +![](img/APsWDfG-1NDc-z--7wVPsBICFs7Vvwt0v3T7VZwGvxg.original.fullsize.png) + +```python +## 2) 通过info()来熟悉数据类型 +Train_data.info() +``` +![](img/fOfAz4nhVr7COjlNqCN_AxWiZgVElfaJq6SS8uSjBR4.original.fullsize.png) + +```python +numeric_features = ['f' + str(i) for i in range(30)] + +## 1) 相关性分析 +numeric = Train_data[numeric_features] +correlation = numeric.corr() + +f , ax = plt.subplots(figsize = (14, 14)) + +sns.heatmap(correlation,square = True) +plt.title('Correlation of Numeric Features with Price',y=1,size=16) +plt.show()) +``` +![](img/N47Ra3UY3ONpe6opMQoM-LjiauCBqRHf9jISb2yk2As.original.fullsize.png) +```python +## 3) 每个数字特征得分布可视化 +f = pd.melt(Train_data, value_vars=numeric_features) +g = sns.FacetGrid(f, col="variable", col_wrap=6, sharex=False, sharey=False) +g = g.map(sns.distplot, "value", hist=False, rug=True) +``` +![](img/5k1sASfi9gVpcrt6bCpE8ac-7XGQlEhRydpM7L2EHZM.original.fullsize.png) + +```python +#变量两两之间的相关性 +sns.set() +sns.pairplot(Train_data[numeric_features],size = 2 ,kind ='scatter',diag_kind='kde') +plt.savefig('correlation.png') +plt.show() +``` +![](img/cTjP7hnGGCB-h8sfZLCJio9oqUYvs-sdoxpSRtoGCjE.original.fullsize.png) + +```python +#数据降维可视化 +from sklearn.manifold import TSNE +tsne = TSNE(n_components=2, init='pca', random_state=0) +result = tsne.fit_transform(numeric) +x_min, x_max = np.min(result, 0), np.max(result, 0) +result = (result - x_min) / (x_max - x_min) +label = Train_data['label'] +fig = plt.figure(figsize = (7, 7)) +#f , ax = plt.subplots() +color = {'o':0, 'n':7} +for i in range(result.shape[0]): + plt.text(result[i, 0], result[i, 1], str(label[i]), + color=plt.cm.Set1(color[label[i]] / 10.), + fontdict={'weight': 'bold', 'size': 9}) +plt.xticks([]) +plt.yticks([]) +plt.title('Visualization of data dimension reduction') +``` +![](img/xQz5G5vBRHR6PIT6oUEnnPZ1hV5ccszHuX_Fya9R6sQ.original.fullsize.png) + +## 3、线性回归 + +  在线性回归中,我们假设不同维度的变量具有一定的相关性,并可以通过一个相关系数矩阵进行衡量。因此对于特定的观测值,可以通过线性方程组来建模。在实际应用中,观测值的数量往往远大于数据的维度,导致线性方程组是一个超定方程,不能直接求解。因此需要通过优化的方法,最小化模型预测值与真实数据点的误差。 + +  线性回归是统计学中一个重要的应用,这个重要的应用往往是指通过一系列自变量去预测一个特殊因变量的值。在这种情况下,异常值是根据其他自变量对因变量的影响来定义的,而自变量之间相互关系中的异常则不那么重要。这里的异常点检测主要用于数据降噪,避免异常点的出现对模型性能的影响,因而这里关注的兴趣点主要是正常值(n)。 + +  而我们通常所说的异常检测中并不会对任何变量给与特殊对待,异常值的定义是基于基础数据点的整体分布,这里我们关注的兴趣点主要是异常值(o)。 + +> **广义的回归建模只是一种工具,这种工具既可以用来进行数据降噪也可以进行异常点检测。** + +### 3.1 基于自变量与因变量的线性回归 +#### 3.1.1 最小二乘法 + +  为了简单起见,这里我们一元线性回归为例: + +$$Y=\sum_{i=1}^{d} a_{i} \cdot X_{i}+a_{d+1}$$ + + +  变量Y为因变量,也就是我们要预测的值;$X_{1}...X_{d}$为一系列因变量,也就是输入值。系数$a_{1}...a_{d+1}$为要学习的参数。假设数据共包含$N$个样本,第$j$个样本包含的数据为$x_{j1}...x_{jd}$和$y_{j}$,带入式(1)如下式所示: + +$$y_{j}=\sum_{i=1}^{d} a_{i} \cdot x_{j i}+a_{d+1}+\epsilon_{j}$$ + +  这里$\epsilon_{j}$为第$j$个样本的误差。以$Y$ 代表 $N \times 1$ 的因变量矩阵${(y_{1}...y_{N})}^{T}$,即样本中的真实值;以$U$代表$N \times (d+1)$的自变量矩阵,其中第$j$行为$(x_{j1}...x_{jd}, 1)$;以$A$ 代表 $(d+1) \times 1$ 的系数矩阵$(a_{1}...a_{d+1})^{T}$。则模型可表示为: +$$f(U, A) = U \cdot A$$ + +  定义目标函数为: + +$$L(A) = \frac{1}{2}{\left\| {Y - U \cdot A} \right\|^2} $$ + +  目标函数是关于$A$的凸函数,其对$A$求偏导为: + +$$\frac{{\partial L(A)}}{{\partial A}} = \frac{1}{2}\frac{{\partial {{\left\| {Y - U \cdot A} \right\|}^2}}}{{\partial A}} = - {U^T}(Y - U \cdot A)$$ + +  令$\frac{{\partial L(A)}}{{\partial A}}=0$,得到最优参数为: + +$$A=\left(U^{T} \cdot U\right)^{-1} \cdot\left(U^{T} \cdot Y\right)$$ + +  这种求解线性回归参数的方法也叫**最小二乘法**。 + +  最小二乘法要求矩阵 $U^{T} \cdot U$ 可逆,即$U^{T} \cdot U$是满秩的。当$U^{T} \cdot U$不可逆时可以通过两种方法进行参数估计,一种先使用主成分分析等方法来预处理数据,消除不同特征之间的相关性,然后再使用最小二乘法。第二种方法是使用**梯度下降法**。 + +#### 3.1.2 梯度下降法 +**数据集** + +  监督学习一般靠数据驱动。我们通常收集一系列的真实数据,例如多栋房屋的真实售出价格和它们对应的面积和房龄。我们希望在这个数据上面寻找模型参数来使模型的预测价格与真实价格的误差最小。在机器学习术语里,该数据集被称为训练数据集(training data set)或训练集(training set),通常还应该有一个用于防止过拟合的交叉验证集和一个用于评估模型性能的测试集(test set)。一栋房屋被称为一个样本(sample),其真实售出价格叫作标签(label),用来预测标签的两个因素叫作特征(feature)。 + +**损失函数** + +  如果把线性回归看作是一个优化问题,那么我们要优化的目标就是损失函数。损失函数是用来衡量样本误差的函数,我们的优化目标是要求得在误差最小的情况下模型参数的值。这里强调一下损失函数和代价函数的区别: +> **注意:** +**Loss Function(损失函数):**the error for single training example; +**Cost Function(代价函数):**the average of the loss functions of the entire training set; + +  线性回归常用的损失函数是均方误差,表达式为: + +$$l^{(i)}(\mathbf{w}, b)=\frac{1}{2}\left(\hat{y}^{(i)}-y^{(i)}\right)^{2}$$ + +$$ +L(\mathbf{w}, b)=\frac{1}{n} \sum_{i=1}^{n} l^{(i)}(\mathbf{w}, b)=\frac{1}{n} \sum_{i=1}^{n} \frac{1}{2}\left(\mathbf{w}^{\top} \mathbf{x}^{(i)}+b-y^{(i)}\right)^{2} +$$ +  其中 $\hat{y}$ 为预测值,$y$ 为真实值。 +**优化算法 - 随机梯度下降** + +  当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解叫作解析解(analytical solution)。本节使用的线性回归和平方误差刚好属于这个范畴。然而,大多数深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解(numerical solution)。 + +  在求数值解的优化算法中,小批量随机梯度下降(mini-batch stochastic gradient descent)被广泛使用。它的算法很简单:先选取一组模型参数的初始值,如随机选取;接下来对参数进行多次迭代,使每次迭代都可能降低损失函数的值。在每次迭代中,先随机均匀采样一个由固定数目训练数据样本所组成的小批量(mini-batch),然后求小批量中数据样本的平均损失和有关模型参数的导数(梯度),最后用此结果与预先设定的学习率的乘积作为模型参数在本次迭代的减小量。如下式所示: + +$$ +(\mathbf{w}, b) \leftarrow(\mathbf{w}, b)-\frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{(\mathbf{w}, b)} l^{(i)}(\mathbf{w}, b) +$$ + +**学习率($\eta$):** 代表在每次优化中,能够学习的步长的大小 +**批量大小($B$):** 是小批量计算中的批量大小batch size + +### 3.2 基于异常检测的线性回归 + +  前一节讨论了这样一种情况:即一个特定的变量被认为是特殊的,最优平面是通过最小化该特殊变量的均方误差而确定的。而我们通常所说的异常检测中并不会对任何变量给与特殊对待,异常值的定义是基于基础数据点的整体分布,因此需要采用一种更一般的回归建模:即以相似的方式对待所有变量,通过最小化数据对该平面的**投影误差**确定最佳回归平面。在这种情况下,假设我们有一组变量 $X_{1}… X_{d}$, 对应的回归平面如下: + +$$a_{1} \cdot X_{1}+\ldots+a_{d} \cdot X_{d}+a_{d+1}=0$$ + +  为了后续计算的方便,对参数进行如下约束: +$$\sum\limits_{i = 1}^d {a_i^2 = 1} $$ +  以$L_{2}$范数作为目标函数: +$$L = {\left\| {U \cdot A} \right\|_2}$$ + +  这样的一个问题可以通过主成分分析方法得到有效解决,我们会单独用一个部分进行讨论。 + +## 4、主成分分析 + +  上一节的最小二乘法试图找到一个与数据具有最佳匹配 $(d−1)$ 维超平面。主成分分析方法可用于解决这一问题的广义版本。具体来说,它可以找到任意 $k( kDatawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。同时Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。 + + + + + diff --git a/AnomalyDetection/二、基于统计学的方法.md b/AnomalyDetection/二、基于统计学的方法.md new file mode 100644 index 0000000..1d30279 --- /dev/null +++ b/AnomalyDetection/二、基于统计学的方法.md @@ -0,0 +1,199 @@ +#异常检测——基于统计学的方法 + +**主要内容包括:** + +- **高斯分布** +- **箱线图** + +[TOC] + + + +## 1、概述 + + + +统计学方法对数据的正常性做出假定。**它们假定正常的数据对象由一个统计模型产生,而不遵守该模型的数据是异常点。**统计学方法的有效性高度依赖于对给定数据所做的统计模型假定是否成立。 + +异常检测的统计学方法的一般思想是:学习一个拟合给定数据集的生成模型,然后识别该模型低概率区域中的对象,把它们作为异常点。 + +即利用统计学方法建立一个模型,然后考虑对象有多大可能符合该模型。 + +根据如何指定和学习模型,异常检测的统计学方法可以划分为两个主要类型:参数方法和非参数方法。 + +**参数方法**假定正常的数据对象被一个以$\Theta$为参数的参数分布产生。该参数分布的概率密度函数$f(x,\Theta)$给出对象$x$被该分布产生的概率。该值越小,$x$越可能是异常点。 + +**非参数方法**并不假定先验统计模型,而是试图从输入数据确定模型。非参数方法通常假定参数的个数和性质都是灵活的,不预先确定(所以非参数方法并不是说模型是完全无参的,完全无参的情况下从数据学习模型是不可能的)。 + +## 2、参数方法 + +**2.1 基于正态分布的一元异常点检测** + +仅涉及一个属性或变量的数据称为一元数据。我们假定数据由正态分布产生,然后可以由输入数据学习正态分布的参数,并把低概率的点识别为异常点。 + +假定输入数据集为$\{x^{(1)}, x^{(2)}, ..., x^{(m)}\}$,数据集中的样本服从正态分布,即$x^{(i)}\sim N(\mu, \sigma^2)$,我们可以根据样本求出参数$\mu$和$\sigma$。 + +$\mu=\frac 1m\sum_{i=1}^m x^{(i)}$ + +$\sigma^2=\frac 1m\sum_{i=1}^m (x^{(i)}-\mu)^2$ + +求出参数之后,我们就可以根据概率密度函数计算数据点服从该分布的概率。正态分布的概率密度函数为 + +$p(x)=\frac 1{\sqrt{2\pi}\sigma}exp(-\frac{(x-\mu)^2}{2\sigma^2})$ + +如果计算出来的概率低于阈值,就可以认为该数据点为异常点。 + +阈值是个经验值,可以选择在验证集上使得评估指标值最大(也就是效果最好)的阈值取值作为最终阈值。 + +例如常用的3sigma原则中,如果数据点超过范围$(\mu-3\sigma, \mu+3\sigma)$,那么这些点很有可能是异常点。 + +这个方法还可以用于可视化。箱线图对数据分布做了一个简单的统计可视化,利用数据集的上下四分位数(Q1和Q3)、中点等形成。异常点常被定义为小于Q1-1.5IQR或大于Q3+1.5IQR的那些数据。 + +用Python画一个简单的箱线图: + +```python +import numpy as np +import seaborn as sns +import matplotlib.pyplot as plt + +data = np.random.randn(50000) * 20 + 20 +sns.boxplot(data=data) +``` + + + +**2.2 多元异常点检测** + +涉及两个或多个属性或变量的数据称为多元数据。许多一元异常点检测方法都可以扩充,用来处理多元数据。其核心思想是把多元异常点检测任务转换成一元异常点检测问题。例如基于正态分布的一元异常点检测扩充到多元情形时,可以求出每一维度的均值和标准差。对于第$j$维: + +$\mu_j=\frac 1m\sum_{i=1}^m x_j^{(i)}$ + +$\sigma_j^2=\frac 1m\sum_{i=1}^m (x_j^{(i)}-\mu_j)^2$ + +计算概率时的概率密度函数为 + +$p(x)=\prod_{j=1}^n p(x_j;\mu_j,\sigma_j^2)=\prod_{j=1}^n\frac 1{\sqrt{2\pi}\sigma_j}exp(-\frac{(x_j-\mu_j)^2}{2\sigma_j^2})$ + +这是在各个维度的特征之间相互独立的情况下。如果特征之间有相关性,就要用到多元高斯分布了。 + + + +**1.3 多个特征相关,且符合多元高斯分布** + +$\mu=\frac{1}{m}\sum^m_{i=1}x^{(i)}$ + +$\sum=\frac{1}{m}\sum^m_{i=1}(x^{(i)}-\mu)(x^{(i)}-\mu)^T$ + +$p(x)=\frac{1}{(2 \pi)^{\frac{n}{2}}|\Sigma|^{\frac{1}{2}}} \exp \left(-\frac{1}{2}(x-\mu)^{T} \Sigma^{-1}(x-\mu)\right)$ + + + +**3.使用混合参数分布** + +在许多情况下假定数据是由正态分布产生的。当实际数据很复杂时,这种假定过于简单,可以假定数据是被混合参数分布产生的。 + +## 3、非参数方法 + +在异常检测的非参数方法中,“正常数据”的模型从输入数据学习,而不是假定一个先验。通常,非参数方法对数据做较少假定,因而在更多情况下都可以使用。 + +**例子:使用直方图检测异常点。** + +直方图是一种频繁使用的非参数统计模型,可以用来检测异常点。该过程包括如下两步: + +步骤1:构造直方图。使用输入数据(训练数据)构造一个直方图。该直方图可以是一元的,或者多元的(如果输入数据是多维的)。 + +尽管非参数方法并不假定任何先验统计模型,但是通常确实要求用户提供参数,以便由数据学习。例如,用户必须指定直方图的类型(等宽的或等深的)和其他参数(直方图中的箱数或每个箱的大小等)。与参数方法不同,这些参数并不指定数据分布的类型。 + +步骤2:检测异常点。为了确定一个对象是否是异常点,可以对照直方图检查它。在最简单的方法中,如果该对象落入直方图的一个箱中,则该对象被看作正常的,否则被认为是异常点。 + +对于更复杂的方法,可以使用直方图赋予每个对象一个异常点得分。例如令对象的异常点得分为该对象落入的箱的容积的倒数。 + +使用直方图作为异常点检测的非参数模型的一个缺点是,很难选择一个合适的箱尺寸。一方面,如果箱尺寸太小,则许多正常对象都会落入空的或稀疏的箱中,因而被误识别为异常点。另一方面,如果箱尺寸太大,则异常点对象可能渗入某些频繁的箱中,因而“假扮”成正常的。 + +## 4、HBOS + +HBOS全名为:Histogram-based Outlier Score。它是一种单变量方法的组合,不能对特征之间的依赖关系进行建模,但是计算速度较快,对大数据集友好。其基本假设是数据集的每个维度相互独立。然后对每个维度进行区间(bin)划分,区间的密度越高,异常评分越低。 + + + +HBOS算法流程: + +1.为每个数据维度做出数据直方图。对分类数据统计每个值的频数并计算相对频率。对数值数据根据分布的不同采用以下两种方法: + +> 1.静态宽度直方图:标准的直方图构建方法,在值范围内使用k个等宽箱。样本落入每个桶的频率(相对数量)作为密度(箱子高度)的估计。 +> +> 时间复杂度:$O(n)$ +> +> + +> 2.动态宽度直方图:首先对所有值进行排序,然后固定数量的$\frac{N}{k}$个连续值装进一个箱里,其 中N是总实例数,k是箱个数;直方图中的箱面积表示实例数。因为箱的宽度是由箱中第一个值和最后一个值决定的,所有箱的面积都一样,因此每一个箱的高度都是可计算的。这意味着跨度大的箱的高度低,即密度小,只有一种情况例外,超过k个数相等,此时允许在同一个箱里超过$\frac{N}{k}$值。 +> +> 时间复杂度:$O(n\times log(n))$ + + + +2.对每个维度都计算了一个独立的直方图,其中每个箱子的高度表示密度的估计。然后为了使得最大高度为1(确保了每个特征与异常值得分的权重相等),对直方图进行归一化处理。最后,每一个实例的HBOS值由以下公式计算: + + + +$$ +H B O S(p)=\sum_{i=0}^{d} \log \left(\frac{1}{\text {hist}_{i}(p)}\right) +$$ + +**推导过程**: + +假设样本*p*第 *i* 个特征的概率密度为$p_i(p)$ ,则*p*的概率密度可以计算为: +$$ +P(p)=P_{1}(p) P_{2}(p) \cdots P_{d}(p) +$$ +两边取对数: +$$ +\begin{aligned} +\log (P(p)) &=\log \left(P_{1}(p) P_{2}(p) \cdots P_{d}(p)\right) =\sum_{i=1}^{d} \log \left(P_{i}(p)\right) +\end{aligned} +$$ +概率密度越大,异常评分越小,为了方便评分,两边乘以“-1”: +$$ +-\log (P(p))=-1 \sum_{i=1}^{d} \log \left(P_{t}(p)\right)=\sum_{i=1}^{d} \frac{1}{\log \left(P_{i}(p)\right)} +$$ +最后可得: +$$ +H B O S(p)=-\log (P(p))=\sum_{i=1}^{d} \frac{1}{\log \left(P_{i}(p)\right)} +$$ + + + +## 5、总结 + +1.异常检测的统计学方法由数据学习模型,以区别正常的数据对象和异常点。使用统计学方法的一个优点是,异常检测可以是统计上无可非议的。当然,仅当对数据所做的统计假定满足实际约束时才为真。 + +2.HBOS在全局异常检测问题上表现良好,但不能检测局部异常值。但是HBOS比标准算法快得多,尤其是在大数据集上。 + + + +## 6、练习 + +**1.学习使用PyOD库生成toy example并调用HBOS** + + + +## 参考资料 + +[1]Goldstein, M. and Dengel, A., 2012. Histogram-based outlier score (hbos):A fast unsupervised anomaly detection algorithm . In*KI-2012: Poster and Demo Track*, pp.59-63. + +[2]http://speech.ee.ntu.edu.tw/~tlkagk/courses.html + +[3]http://cs229.stanford.edu/ + + + + + +**关于Datawhale**: + +>Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。同时Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。 + + + + + diff --git a/AnomalyDetection/五、高维异常.md b/AnomalyDetection/五、高维异常.md new file mode 100644 index 0000000..fb497ea --- /dev/null +++ b/AnomalyDetection/五、高维异常.md @@ -0,0 +1,134 @@ +#异常检测——高维数据异常检测 + +**主要内容包括:** + +* **Feature Bagging** + +- **孤立森林** + + + +[TOC] + +## 1、引言 + +在实际场景中,很多数据集都是多维度的。随着维度的增加,数据空间的大小(体积)会以指数级别增长,使数据变得稀疏,这便是维度诅咒的难题。维度诅咒不止给异常检测带来了挑战,对距离的计算,聚类都带来了难题。例如基于邻近度的方法是在所有维度使用距离函数来定义局部性,但是,在高维空间中,所有点对的距离几乎都是相等的(距离集中),这使得一些基于距离的方法失效。在高维场景下,一个常用的方法是子空间方法。 + +集成是子空间思想中常用的方法之一,可以有效提高数据挖掘算法精度。集成方法将多个算法或多个基检测器的输出结合起来。其基本思想是一些算法在某些子集上表现很好,一些算法在其他子集上表现很好,然后集成起来使得输出更加鲁棒。集成方法与基于子空间方法有着天然的相似性,子空间与不同的点集相关,而集成方法使用基检测器来探索不同维度的子集,将这些基学习器集合起来。 + + + +下面来介绍两种常见的集成方法: + +## 2、Feature Bagging + +Feature Bagging,基本思想与bagging相似,只是对象是feature。feature bagging属于集成方法的一种。集成方法的设计有以下两个主要步骤: + +**1.选择基检测器**。这些基本检测器可以彼此完全不同,或不同的参数设置,或使用不同采样的子数据集。Feature bagging常用lof算法为基算法。下图是feature bagging的通用算法: + +![image-20210104144520790](./img/image-20210104144520790.png) + +**2.分数标准化和组合方法**:不同检测器可能会在不同的尺度上产生分数。例如,平均k近邻检测器会输出原始距离分数,而LOF算法会输出归一化值。另外,尽管一般情况是输出较大的异常值分数,但有些检测器会输出较小的异常值分数。因此,需要将来自各种检测器的分数转换成可以有意义的组合的归一化值。分数标准化之后,还要选择一个组合函数将不同基本检测器的得分进行组合,最常见的选择包括平均和最大化组合函数。 + +下图是两个feature bagging两个不同的组合分数方法: + +![image-20210105140222697-1609839336763](img/image-20210105140222697-1609839336763.png) + +​ (广度优先) + +![image-20210105140242611](./img/image-20210105140242611.png) + +​ (累积求和) + +​ + +基探测器的设计及其组合方法都取决于特定集成方法的特定目标。很多时候,我们无法得知数据的原始分布,只能通过部分数据去学习。除此以外,算法本身也可能存在一定问题使得其无法学习到数据完整的信息。这些问题造成的误差通常分为偏差和方差两种。 + +**方差**:是指算法输出结果与算法输出期望之间的误差,描述模型的离散程度,数据波动性。 + +**偏差**:是指预测值与真实值之间的差距。即使在离群点检测问题中没有可用的基本真值 + + + +## 3、Isolation Forests + +孤立森林(Isolation Forest)算法是周志华教授等人于2008年提出的异常检测算法,是机器学习中少见的专门针对异常检测设计的算法之一,方法因为该算法时间效率高,能有效处理高维数据和海量数据,无须标注样本,在工业界应用广泛。 + +孤立森林属于非参数和无监督的算法,既不需要定义数学模型也不需要训练数据有标签。孤立森林查找孤立点的策略非常高效。假设我们用一个随机超平面来切割数据空间,切一次可以生成两个子空间。然后我们继续用随机超平面来切割每个子空间并循环,直到每个子空间只有一个数据点为止。直观上来讲,那些具有高密度的簇需要被切很多次才会将其分离,而那些低密度的点很快就被单独分配到一个子空间了。孤立森林认为这些很快被孤立的点就是异常点。 + +用四个样本做简单直观的理解,d是最早被孤立出来的,所以d最有可能是异常。 + +![img](./img/v2-bb94bcf07ced88315d0a5de47677200e_720w.png) + + + +怎么来切这个数据空间是孤立森林的核心思想。因为切割是随机的,为了结果的可靠性,要用集成(ensemble)的方法来得到一个收敛值,即反复从头开始切,平均每次切的结果。孤立森林由t棵孤立的数组成,每棵树都是一个随机二叉树,也就是说对于树中的每个节点,要么有两个孩子节点,要么一个孩子节点都没有。树的构造方法和随机森林(random forests)中树的构造方法有些类似。流程如下: + +1) 从训练数据中随机选择一个样本子集,放入树的根节点; + +2) 随机指定一个属性,随机产生一个切割点V,即属性A的最大值和最小值之间的某个数; + +3) 根据属性A对每个样本分类,把A小于V的样本放在当前节点的左孩子中,大于等于V的样本放在右孩子中,这样就形成了2个子空间; + +4) 在孩子节点中递归步骤2和3,不断地构造左孩子和右孩子,直到孩子节点中只有一个数据,或树的高度达到了限定高度。 + +获得t棵树之后,孤立森林的训练就结束,就可以用生成的孤立森林来评估测试数据。 + + + +孤立森林检测异常的假设是:异常点一般都是非常稀有的,在树中会很快被划分到叶子节点,因此可以用叶子节点到根节点的路径长度来判断一条记录是否是异常的。和随机森林类似,孤立森林也是采用构造好的所有树的平均结果形成最终结果的。在训练时,每棵树的训练样本是随机抽样的。从孤立森林的树的构造过程看,它不需要知道样本的标签,而是通过阈值来判断样本是否异常。因为异常点的路径比较短,正常点的路径比较长,孤立森林根据路径长度来估计每个样本点的异常程度。 + +路径长度计算方法: + +![image-20210103183909407](./img//image-20210103183909407.png) + + + +孤立森林也是一种基于子空间的方法,不同的分支对应于数据的不同局部子空间区域,较小的路径对应于孤立子空间的低维 + +## 4、总结 + +1.feature bagging可以降低方差 + +2.孤立森林的优势在于: + +- 计算成本相比基于距离或基于密度的算法更小。 +- 具有线性的时间复杂度。 +- 在处理大数据集上有优势。 + +孤立森林不适用于超高维数据,因为鼓励森林每次都是随机选取维度,如果维度过高,则会存在过多噪音。 + + + +## 5、练习 + +**1.使用PyOD库生成toy example并调用feature bagging** + + + +**2.使用PyOD库生成toy example并调用Isolation Forests** + + + +**3.(思考题:feature bagging为什么可以降低方差?)** + + + +**4.(思考题:feature bagging存在哪些缺陷,有什么可以优化的idea?)** + + + +## 6、参考文献 + +[1]Goldstein, M. and Dengel, A., 2012. Histogram-based outlier score (hbos):A fast unsupervised anomaly detection algorithm . In*KI-2012: Poster and Demo Track*, pp.59-63. + +[2]https://cs.nju.edu.cn/zhouzh/zhouzh.files/publication/icdm08b.pdf + +[3]《Outlier Analysis》——Charu C. Aggarwal + + + +**关于Datawhale**: + +>Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。同时Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。 + diff --git a/AnomalyDetection/四、基于相似度的方法.md b/AnomalyDetection/四、基于相似度的方法.md new file mode 100644 index 0000000..56ff720 --- /dev/null +++ b/AnomalyDetection/四、基于相似度的方法.md @@ -0,0 +1,241 @@ +#异常检测——基于相似度的方法 + +**主要内容包括:** + +- 基于距离的度量 +- 基于密度的度量 + +[TOC] + + + +## 1、概述 + +  “异常”通常是一个主观的判断,什么样的数据被认为是“异常”的,需要结合业务背景和环境来具体分析确定。 +  实际上,数据通常嵌入在大量的噪声中,而我们所说的“异常值”通常指具有特定业务意义的那一类特殊的异常值。噪声可以视作特性较弱的异常值,没有被分析的价值。噪声和异常之间、正常数据和噪声之间的边界都是模糊的。异常值通常具有更高的离群程度分数值,同时也更具有可解释性。 +  在普通的数据处理中,我们常常需要保留正常数据,而对噪声和异常值的特性则基本忽略。但在异常检测中,我们弱化了“噪声”和“正常数据”之间的区别,专注于那些具有有价值特性的异常值。在基于相似度的方法中,主要思想是异常点的表示与正常点不同 + + + +## 2、基于距离的度量 + +  基于距离的方法是一种常见的适用于各种数据域的异常检测算法,它基于最近邻距离来定义异常值。 此类方法不仅适用于多维数值数据,在其他许多领域,例如分类数据,文本数据,时间序列数据和序列数据等方面也有广泛的应用。 +  基于距离的异常检测有这样一个前提假设,即异常点的 $k$ 近邻距离要远大于正常点。解决问题的最简单方法是使用嵌套循环。 第一层循环遍历每个数据,第二层循环进行异常判断,需要计算当前点与其他点的距离,一旦已识别出多于 $k$ 个数据点与当前点的距离在 $D$ 之内,则将该点自动标记为非异常值。 这样计算的时间复杂度为$O(N^{2})$,当数据量比较大时,这样计算是及不划算的。 因此,需要修剪方法以加快距离计算。 + +### 2.1 基于单元的方法 + +  在基于单元格的技术中,数据空间被划分为单元格,单元格的宽度是阈值D和数据维数的函数。具体地说,每个维度被划分成宽度最多为 $\frac{D}{{2 \cdot \sqrt d }}$ 单元格。在给定的单元以及相邻的单元中存在的数据点满足某些特性,这些特性可以让数据被更有效的处理。 + +![@图 1 基于单元的数据空间分区 | center| 500x0](img/UWiX5C7kCHx5yX7O9yQm9F1ndg-QgMqS3BAwIWPB40k.original.fullsize-1609839833441.png) + +  以二维情况为例,此时网格间的距离为 $\frac{D}{{2 \cdot \sqrt d }}$ ,需要记住的一点是,网格单元的数量基于数据空间的分区,并且与数据点的数量无关。这是决定该方法在低维数据上的效率的重要因素,在这种情况下,网格单元的数量可能不多。 另一方面,此方法不适用于更高维度的数据。对于给定的单元格,其 $L_{1}$ 邻居被定义为通过最多1个单元间的边界可从该单元到达的单元格的集合。请注意,在一个角上接触的两个单元格也是 $L_{1}$ 邻居。 $L_{2}$ 邻居是通过跨越2个或3个边界而获得的那些单元格。 上图中显示了标记为 $X$的特定单元格及其 $L_{1}$ 和 $L_{2}$ 邻居集。 显然,内部单元具有8个 $L_{1}$ 邻居和40个 $L_{2}$ 邻居。 然后,可以立即观察到以下性质: + +- 单元格中两点之间的距离最多为 $D/2$。 +- 一个点与 $L_{1}$ 邻接点之间的距离最大为 $D$。 +- 一个点与它的 $Lr$ 邻居(其中$r$ > 2)中的一个点之间的距离至少为$D$。 + +  唯一无法直接得出结论的是 $L_{2}$ 中的单元格。 这表示特定单元中数据点的不确定性区域。 对于这些情况,需要明确执行距离计算。 同时,可以定义许多规则,以便立即将部分数据点确定为异常值或非异常值。 规则如下: + +- 如果一个单元格中包含超过 $k$ 个数据点及其 $L_{1}$ 邻居,那么这些数据点都不是异常值。 +- 如果单元 $A$ 及其相邻 $L_{1}$ 和 $L_{2}$ 中包含少于 $k$ 个数据点,则单元A中的所有点都是异常值。 + +  此过程的第一步是将部分数据点直接标记为非异常值(如果由于第一个规则而导致它们的单元格包含 $k$ 个点以上)。 此外,此类单元格的所有相邻单元格仅包含非异常值。 为了充分利用第一条规则的修剪能力,确定每个单元格及其 $L_{1}$ 邻居中点的总和。 如果总数大于 $k$ ,则所有这些点也都标记为非离群值。 + +  接下来,利用第二条规则的修剪能力。 对于包含至少一个数据点的每个单元格 $A$,计算其中的点数及其 $L_{1}$ 和 $L_{2}$ 邻居的总和。 如果该数字不超过 $k$,则将单元格$A$ 中的所有点标记为离群值。 此时,许多单元可能被标记为异常值或非异常值。 + +  对于此时仍未标记为异常值或非异常值的单元格中的数据点需要明确计算其 $k$ 最近邻距离。即使对于这样的数据点,通过使用单元格结构也可以更快地计算出 $k$ 个最近邻的距离。考虑到目前为止尚未被标记为异常值或非异常值的单元格$A$。这样的单元可能同时包含异常值和非异常值。单元格 $A$ 中数据点的不确定性主要存在于该单元格的 $L_{2}$ 邻居中的点集。无法通过规则知道 $A$ 的 $L_{2}$ 邻居中的点是否在阈值距离 $D$ 内,为了确定单元 $A$ 中数据点与其$L_{2}$ 邻居中的点集在阈值距离 $D$ 内的点数,需要进行显式距离计算。对于那些在 $L_{1}$ 和 $L_{2}$ 中不超过 $k$ 个且距离小于 $D$ 的数据点,则声明为异常值。需要注意,仅需要对单元 $A$ 中的点到单元$A$的$L_{2}$邻居中的点执行显式距离计算。这是因为已知 $L_{1}$ 邻居中的所有点到 $A$ 中任何点的距离都小于 $D$,并且已知 $Lr$ 中 $(r> 2)$ 的所有点与 $A$上任何点的距离至少为 $D$。因此,可以在距离计算中实现额外的节省。 + +### 2.2 基于索引的方法 + +  对于一个给定数据集,基于索引的方法利用多维索引结构(如 $\mathrm{R}$ 树、$k-d$ 树)来搜索每个数据对象 $A$ 在半径 $D$ 范围 内的相邻点。设 $M$ 是一个异常值在其 $D$ -邻域内允许含有对象的最多个数,若发现某个数据对象 $A$ 的 $D$ -邻域内出现 $M+1$ 甚至更多个相邻点, 则判定对象 $A$ 不是异常值。该算法时间复杂度在最坏情况下为 $O\left(k N^{2}\right),$ 其中 $k$ 是数据集维数, $N$ 是数据集包含对象的个数。该算法在数据集的维数增加时具有较好的扩展性,但是时间复杂度的估算仅考虑了搜索时间,而构造索引的任务本身就需要密集复杂的计算量。 + +## 3、基于密度的度量 + +  基于密度的算法主要有局部离群因子(LocalOutlierFactor,LOF),以及LOCI、CLOF等基于LOF的改进算法。下面我们以LOF为例来进行详细的介绍和实践。 + +  基于距离的检测适用于各个集群的密度较为均匀的情况。在下图中,离群点B容易被检出,而若要检测出较为接近集群的离群点A,则可能会将一些集群边缘的点当作离群点丢弃。而LOF等基于密度的算法则可以较好地适应密度不同的集群情况。 + +![图4.1距离检测的困境-离群点A.png](img/图4.1距离检测的困境-离群点A-1609839836032.png) + +   那么,这个基于密度的度量值是怎么得来的呢?还是要从距离的计算开始。类似k近邻的思路,首先我们也需要来定义一个“k-距离”。 + +### 3.1 k-距离(k-distance(p)): + +  对于数据集D中的某一个对象o,与其距离最近的k个相邻点的最远距离表示为k-distance(p),定义为给定点p和数据集D中对象o之间的距离d(p,o),满足: ++ 在集合D中至少有k个点 o',其中$o'∈D\{p\}$,满足$d(p,o')≤d(p,o)$ ++ 在集合D中最多有k-1个点o',其中$o'∈D\{p\}$,满足$d(p,o;)Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。同时Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。 +