小编用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/
联系客服