我们可以使用遗漏均值和标准差来揭示异常值吗?

机器算法验证 交叉验证 标准差 意思是 异常值
2022-01-19 19:45:53

假设我有正态分布的数据。对于数据的每个元素,我想检查它与平均值相差多少 SD。数据中可能存在异常值(可能只有一个,但也可能是两个或三个),但这个异常值基本上是我正在寻找的。从平均值和 SD 的计算中暂时排除我当前正在查看的元素是否有意义?我的想法是,如果它接近平均值,它不会有任何影响。如果它是一个异常值,它可能会使均值和 SD 的计算产生偏差,并降低它被检测到的概率。我不是统计学家,所以任何帮助表示赞赏!

1个回答

这可能看起来违反直觉,但使用您描述的方法没有意义(用您的措辞,我宁愿写“可能导致与预期的结果大不相同”)并且永远不应该这样做:它不起作用是必然的,此外,还有一种更简单、更安全、更成熟的替代方案,无需额外费用。

首先,确实,如果存在单个异常值,那么您最终会使用您建议的过程找到它。但是,一般来说(当数据中可能有多个异常值时),您建议的算法会完全失效,这可能会导致您拒绝将好的数据点作为异常值或将异常值保留为好的数据点具有潜在的灾难性后果。

下面,我给出了一个简单的数字示例,其中您提出的规则被打破,然后我提出了一个更安全和更成熟的替代方案,但在此之前,我将解释 a)您提出的方法有什么问题和 b)通常首选的方法替代它是。

从本质上讲,您不能使用观测值与数据的遗漏均值和标准差的距离来可靠地检测异常值,因为您使用的估计值(遗漏均值和标准差)仍然容易被拉向剩余的异常值:这称为掩蔽效应。

简而言之,可靠检测异常值的一种简单方法是使用您建议的一般想法(与位置和规模估计的距离),但用稳健的估计量替换您使用的估计量(保留一个均值,sd) - 即估计设计得更不容易受到异常值的影响。

考虑这个例子,我将 3 个异常值添加到从 Normal 0,1 中提取的 47 个真实观察值中:

n    <- 50
set.seed(123)  # for reproducibility
x    <- round(rnorm(n,0,1), 1)
x[1] <- x[1]+1000
x[2] <- x[2]+10
x[3] <- x[3]+10

下面的代码根据遗漏平均值和标准差(例如您建议的方法)计算异常指数。

out_1 <- rep(NA,n)
for(i in 1:n){  out_1[i] <- abs( x[i]-mean(x[-i]) )/sd(x[-i])  }

此代码生成您在下面看到的图。

plot(x, out_1, ylim=c(0,1), xlim=c(-3,20))
points(x[1:3], out_1[1:3], col="red", pch=16)

图 1 描绘了作为观察值函数的离群指数值(离群值最远的值超出了该图的范围,但其他两个显示为红点)。如您所见,除了最极端的以外,按照您的建议构建的离群指数将无法揭示离群值:实际上,第二个和第三个(较温和的)离群值现在甚至(在离群指数上)的值都小于所有离群值真正的观察!...根据您建议的方法,将这两个极端异常值保留在一组真正的观察中,导致您使用剩余的 49 个观察,就好像它们来自同一个同质过程一样,给您一个最终的根据这 49 个 0.45 和 2.32 的数据点估计平均值和标准差,这对样本的任何一部分都进行了非常糟糕的描述!

图2

将此结果与您使用基于中值的异常值检测规则获得的结果进行对比xi写入数据向量X

O(xi,X)=|ximed(X)|mad(X)

在哪里med(X)是条目的中位数X(所有这些,不排除)和mad(X)是它们的中值绝对偏差乘以 1.4826(我参考链接的 wiki 文章来解释这个数字的来源,因为它与这里的主要问题正交)。

在 R 中,第二个异常指数可以计算为:

out_2 <- abs( x-median(x) )/mad(x)

并使用以下方法绘制(如前所述):

plot(x, out_2, ylim=c(0,15), xlim=c(-3,20))
points(x[1:3], out_2[1:3], col="red", pch=16)

图2

图 2 绘制了同一数据集的这种替代偏远指数的值。如您所见,现在所有三个异常值都清楚地显示出来了。此外,这种异常值检测规则具有一些既定的统计特性。除其他外,这导致了可用的截止规则。例如,如果可以假设数据的真实部分是从具有有限二阶矩的对称分布中提取的,则可以拒绝所有满足以下条件的数据点

|ximed(X)|mad(X)>3.5

作为异常值。在上面的示例中,应用此规则将导致您正确标记观测值 1,2 和 3。拒绝这些,剩余观测值的均值和标准差分别为 0.021 和 0.93,更好地描述了样本的真实部分!