分享

数据挖掘 | 异常值检测实例

 kieojk 2016-08-27

小编用R语言结合实例,介绍异常检测的方法:


单变量异常检测

       本部分展示了一个单变量异常检测的例子,并且演示了如何将这种方法应用在多元数据上。在该例中,单变量异常检测通过boxplot.stats()函数实现,并且返回产生箱线图的统计量。在返回的结果中,有一个部分是out,它给出了异常值的列表,即它列出了位于极值之外的胡须。参数coef可以控制胡须延伸到箱线图外的远近。在R中,运行?boxplot.stats可获取更详细的信息。例子如下:

> set.seed(521)

> x = rnorm(100)

> x[10] = 5

> x[20] = 6

> summary(x)

> outliers = boxplot.stats(x)$out

> outliers

[1] 5.000000  6.000000 -3.338937

> boxplot(x)

> for(i in outliers) points(i,col='red', pch='+', cex=2.5)


如上的单变量异常检测,通过简单搭配的方式可以用来发现多元数据中的异常值。在下例中,我们首先产生一个数据框df,它有两列x和y。之后,异常值分别从x和y检测出来。然后,我们获取两列都是异常值的数据作为异常数据。

> y = rnorm(100)

> df = data.frame(x, y)

> a = which(df$x %in%boxplot.stats(df$x)$out)

> a

> b = which(df$y %in%boxplot.stats(df$y)$out)

> b

> outliers = intersect(a, b)

> plot(df)

> points(df[outliers,], col='red',pch='+', cex=2.5)


类似的,我们也可以将x或y为异常值的数据标记为异常值。

> outliers = union(a, b)

> plot(df)

> points(df[outliers,], col='blue',pch='+', cex=2.5)


当有三个以上的变量时,最终的异常值需要考虑单变量异常检测结果的多数表决。当选择最佳方式在真实应用中进行搭配时,需要涉及领域知识。

 

LOF异常检测

      LOF(local outlier factor,局部异常因子)是用于识别基于密度的局部异常值的算法。使用LOF,一个点的局部密度会与它的邻居进行比较。如果前者明显低于后者(有一个大于1 的LOF值),该点位于一个稀疏区域,对于它的邻居而言,这就表明,该点是一个异常值。LOF的缺点就是它只对数值数据有效。

      lofactor()函数使用LOF算法计算局部异常因子,并且它在DMwR和dprep包中是可用的。下面将介绍一个使用LOF进行异常检测的例子,k是用于计算局部异常因子的邻居数量。下图呈现了一个异常值得分的密度图。

> library(DMwR)

> iris2 = iris[, 1:4]

> outlier_scores = lofactor(iris2, k=5)

> plot(density(outlier_scores))

# 将前5个作为异常值

> outliers = order(outlier_scores,decreasing=T)[1:5]

> outliers

> iris2[outliers,]

   Sepal.Length Sepal.Width Petal.Length Petal.Width

42          4.5         2.3          1.3         0.3

107         4.9         2.5          4.5         1.7

23          4.6         3.6          1.0         0.2

110         7.2         3.6          6.1         2.5

63          6.0         2.2          4.0         1.0

接着,我们结合前两个主成份的双标图呈现异常值。

> n = nrow(iris2)

> labels = 1:n

> labels[-outliers] = '.'

> biplot(prcomp(iris2), cex=0.8,xlabs=labels)



在如上代码中,prcomp()执行了一个主成分分析,并且biplot()使用前两个主成分画出了这些数据。在上图中,x和y轴分别代表第一和第二个主成份,箭头表示了变量,5个异常值用它们的行号标记出来了。

 

聚类异常检测

      通过把数据聚成类,将那些不属于任务一类的数据作为异常值。比如,使用基于密度的聚类DBSCAN,如果对象在稠密区域紧密相连,它们将被分组到一类。因此,那些不会被分到任何一类的对象就是异常值。

      我们也可以使用k-means算法来检测异常。使用k-means算法,数据被分成k组,通过把它们分配到最近的聚类中心。然后,我们能够计算每个对象到聚类中心的距离(或相似性),并且选择最大的距离作为异常值。

如下是一个基于k-means算法在iris数据上实现在异常检测。

# 去掉species列

> iris2 = iris[, 1:4]

> kmeans_result = kmeans(iris2,centers=3)

> kmeans_result$centers

> kmeans_result$cluster

> centers =kmeans_result$centers[kmeans_result$cluster,]

> distances =sqrt(rowSums((iris2-centers)^2))

# 取前5个作为异常值

> outliers = order(distances,decreasing=T)[1:5]

> outliers

> iris2[outliers,]

> plot(iris2[,c('Sepal.Length', 'Sepal.Width')], pch='o',col=kmeans_result$cluster, cex=0.5)

> points(kmeans_result$centers[,c('Sepal.Length','Sepal.Width')], col=1:3, pch=8, cex=1.5)

> points(iris2[outliers,c('Sepal.Length','Sepal.Width')], col=4, pch='+', cex=1.5)

 

在上图中,聚类中心被标记为星号,异常值标记为'+'

 

其他一些用于异常检测的R包包括:

extremevalues、outliers包:单变量异常检测

mvoutlier包:基于稳定方法的多元变量异常检测

(封面图片就是用此包做出来的,uni.plot函数检测每个维度上的异常值)




参考文章:

[1] http://blog.163.com/zzz216@yeah/blog/static/162554684201472303218605/



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多