【问题标题】:Neighborhood calculations for outlier detection异常值检测的邻域计算
【发布时间】:2021-05-25 02:32:49
【问题描述】:

我正在使用 R 编程语言,我正在尝试了解以下用于异常值检测的函数的详细信息:https://rdrr.io/cran/dbscan/src/R/LOF.R

此函数(来自“dbscan”库)使用局部异常值因子 (LOF) 算法计算异常值:https://en.wikipedia.org/wiki/Local_outlier_factor

LOF 算法是一种无监督的基于距离的算法,它定义数据集中相对于观测值的“可达性和邻域”的异常值。通常,相对于其附近的其他观测值而言,不是“非常可达”的观测值被认为是“异常值”。基于这些属性(用户指定这些属性,例如邻域(用“k”表示)可以是“3”),该算法为数据集中的每个点分配一个 LOF“分数”。给定观测值的 LOF 分数越大,该观测值被认为是异常值。

现在,我试图更好地理解 dbscan::lof() 函数中发生的一些计算。

1)基本的LOF算法可以在一些人工创建的数据上运行,如下所示:

```#load library(dbscan)
par(mfrow = c(1,2))
#generate data
n <- 100
x <- cbind(
  x=runif(10, 0, 5) + rnorm(n, sd=0.4),
  y=runif(10, 0, 5) + rnorm(n, sd=0.4)
  )

### calculate LOF score
lof <- lof(x, k=3)

### distribution of outlier factors
summary(lof)
hist(lof, breaks=10)

### point size is proportional to LOF
plot(x, pch = ".", main = "LOF (k=3)")
points(x, cex = (lof-1)*3, pch = 1, col="red") ```

我的问题是:“k”值越大,识别出的异常值越少(直方图左偏),但识别出的异常值越“极端”(即 LOF 分数越大)?

我观察到了这种一般模式,但我不确定这种趋势是否反映在 LOF 算法代码中。例如

#plot LOF results for different values of k

par(mfrow = c(2,2))



### calculate LOF score
lof <- lof(x, k=3)

### distribution of outlier factors
summary(lof)
hist(lof, main = "k = 3",breaks=10)

### calculate LOF score
lof <- lof(x, k=10)

### distribution of outlier factors
summary(lof)
hist(lof, main = "k = 10", breaks=10)

### calculate LOF score
lof <- lof(x, k=20)

### distribution of outlier factors
summary(lof)
hist(lof, main = "k = 20", breaks=10)


### calculate LOF score
lof <- lof(x, k=40)

### distribution of outlier factors
summary(lof)
hist(lof, main = "k = 10", breaks=40)

在上图中,您可以看到随着“k”值的增加,识别出的异常值越少。这是正确的吗?

2) 是否有一种“最佳”方式为 LOF 算法选择“k”值?看到 LOF 算法如何,在我看来并没有一种“最佳”方式来选择“k”的值。看来你必须参考1)中描述的逻辑:

  1. “k”值越大,识别出的异常值越少,但 识别出的异常值更“极端”

  2. 较小的“k”值会导致识别出更多的异常值,但 识别出的异常值不那么“极端”

这是正确的吗?

【问题讨论】:

标签: r algorithm data-science histogram outliers


【解决方案1】:

关于 2) ,我在这里找到了这个 stackoverflow 帖子:https://stats.stackexchange.com/questions/138675/choosing-a-k-value-for-local-outlier-factor-lof-detection-analysis

“论文的作者建议选择一个最小 k 和一个最大 k,并且对于每个点,在该范围内的每个 k 上取最大 LOF 值。他们提供了一些选择边界的指南。”

这是我将上述实现到 R 代码中的逻辑:

library(dbscan)

#generate data
n <- 100
x <- cbind(
  x=runif(10, 0, 5) + rnorm(n, sd=0.4),
  y=runif(10, 0, 5) + rnorm(n, sd=0.4)
  )

x = data.frame(x)

### calculate LOF score for a range of different "k" values:

lof_10 <- lof(x, k=10)
lof_15 <- lof(x, k=15)
lof_20 <- lof(x, k=20)

#append these lof calculations the original data set:

x$lof_10 = lof_10
x$lof_15 = lof_15
x$lof_20 = lof_20

#as the previous stackoverflow post suggests: for each row, choose the highest LOF value 

x$max_lof = pmax(x$lof_10, x$lof_15, x$lof_20)

#view results:

 head(x)

         x          y    lof_10    lof_15    lof_20   max_lof
1 2.443382  4.2611753 0.9803894 0.9866732 0.9841705 0.9866732
2 2.397454 -0.3732838 1.0527592 1.4638348 1.6008284 1.6008284
3 2.617348  3.0435179 0.9952212 0.9945580 0.9715819 0.9952212
4 3.731156  4.1668976 1.0339001 1.0802826 1.0921033 1.0921033
5 1.103123  1.6642337 1.1260092 1.0773444 1.0650159 1.1260092
6 2.735938  4.3737450 0.9939896 0.9573139 0.9700123 0.9939896

因此,每一行的 LOF 分数就是“max_lof”列的值。

有人可以告诉我是否正确解释了之前的 stackoverflow 帖子?我是否也正确编写了 R 代码?

谢谢

注意:从我最初的问题来看,我仍然不确定 1)

即较大的“k”值是否会导致识别的异常值更少(直方图左偏),但识别出的异常值更“极端”?

【讨论】:

    猜你喜欢
    • 2017-02-17
    • 2014-10-06
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    • 2014-06-24
    • 2016-03-17
    相关资源
    最近更新 更多