是否有衡量传播“均匀度”的标准?

机器算法验证 方差 标准差 描述性统计 测量
2022-01-29 14:49:24

我在网上查了一下,但找不到任何有用的东西。

我基本上是在寻找一种方法来衡量一个值如何“均匀”分布。例如,像X这样的“均匀”分布分布在此处输入图像描述

以及大致相同的均值和标准差 的“不均匀”分布Y :在此处输入图像描述

但是是否有任何均匀度度量 m,例如 m(X) > m(Y)?如果没有,创建这样的度量的最佳方法是什么?

(图片来自可汗学院)

4个回答

Ripley K 函数及其近亲 L 函数是一种标准的、强大的、易于理解的、理论上完善的和经常实施的“均匀度”度量。 尽管这些通常用于评估二维空间点配置,但将它们调整为一维所需的分析(通常在参考文献中未给出)很简单。


理论

K 函数估计距离内点的平均比例d的一个典型点。对于区间上的均匀分布[0,1],可以计算真实比例并且(在样本量中渐近)等于1(1d)2. L 函数的适当一维版本从 K 中减去该值以显示与均匀性的偏差。 因此,我们可能会考虑将任何一批数据归一化以具有单位范围,并检查其 L 函数是否存在零附近的偏差。


工作示例

为了说明,我模拟了999大小独立样本64从均匀分布中绘制它们的(归一化的)L 函数以获得较短的距离(从01/3),从而创建一个包络来估计 L 函数的采样分布。(在这个包络内绘制的点不能与均匀性显着区分开来。)在此之上,我已经绘制了来自 U 形分布、具有四个明显分量的混合分布和标准正态分布的相同大小样本的 L 函数。显示这些样本(及其父分布)的直方图以供参考,使用线符号来匹配 L 函数的直方图。

数字

U 形分布的尖锐分离尖峰(红色虚线,最左边的直方图)创建了紧密间隔值的集群。这反映在 L 函数中的一个非常大的斜率上0. 然后 L 函数减小,最终变为负值以反映中间距离处的间隙。

来自正态分布的样本(蓝色实线,最右边的直方图)非常接近均匀分布。因此,它的 L 函数不偏离0迅速地。然而,由于距离0.10左右,它已经上升到足够高于包络线,表明有轻微的聚集趋势。中间距离的持续上升表明聚类是分散的和广泛的(不限于一些孤立的峰)。

混合分布(中间直方图)中样本的初始大斜率揭示了小距离(小于0.15)。通过下降到负值,它表示中间距离的分离。将其与 U 形分布的 L 函数进行比较可以发现:斜率位于0, 这些曲线上升的量0,以及它们最终下降到的速率0所有这些都提供了有关数据中存在的聚类性质的信息。可以选择这些特征中的任何一个作为“均匀度”的单一度量以适应特定应用。

这些示例显示了如何检查 L 函数以评估数据与均匀性(“均匀性”)的偏差,以及如何从中提取有关偏差的规模和性质的定量信息。

(确实可以绘制整个 L 函数,延伸到完全归一化的距离1,以评估大规模偏离均匀性。不过,通常情况下,评估数据在较小距离内的行为更为重要。)


软件

R生成此图的代码如下。它首先定义计算 K 和 L 的函数。它创建了从混合分布进行模拟的能力。然后它生成模拟数据并绘制图表。

Ripley.K <- function(x, scale) {
  # Arguments:
  # x is an array of data.
  # scale (not actually used) is an option to rescale the data.
  #
  # Return value:
  # A function that calculates Ripley's K for any value between 0 and 1 (or `scale`).
  #
  x.pairs <- outer(x, x, function(a,b) abs(a-b))  # All pairwise distances
  x.pairs <- x.pairs[lower.tri(x.pairs)]          # Distances between distinct pairs
  if(missing(scale)) scale <- diff(range(x.pairs))# Rescale distances to [0,1]
  x.pairs <- x.pairs / scale
  #
  # The built-in `ecdf` function returns the proportion of values in `x.pairs` that
  # are less than or equal to its argument.
  #
  return (ecdf(x.pairs))
}
#
# The one-dimensional L function.
# It merely subtracts 1 - (1-y)^2 from `Ripley.K(x)(y)`.  
# Its argument `x` is an array of data values.
#
Ripley.L <- function(x) {function(y) Ripley.K(x)(y) - 1 + (1-y)^2}
#-------------------------------------------------------------------------------#
set.seed(17)
#
# Create mixtures of random variables.
#
rmixture <- function(n, p=1, f=list(runif), factor=10) {
  q <- ceiling(factor * abs(p) * n / sum(abs(p)))
  x <- as.vector(unlist(mapply(function(y,f) f(y), q, f)))
  sample(x, n)
}
dmixture <- function(x, p=1, f=list(dunif)) {
  z <- matrix(unlist(sapply(f, function(g) g(x))), ncol=length(f))
  z %*% (abs(p) / sum(abs(p)))
}
p <- rep(1, 4)
fg <- lapply(p, function(q) {
  v <- runif(1,0,30)
  list(function(n) rnorm(n,v), function(x) dnorm(x,v), v)
  })
f <- lapply(fg, function(u) u[[1]]) # For random sampling
g <- lapply(fg, function(u) u[[2]]) # The distribution functions
v <- sapply(fg, function(u) u[[3]]) # The parameters (for reference)
#-------------------------------------------------------------------------------#
#
# Study the L function.
#
n <- 64                # Sample size
alpha <- beta <- 0.2   # Beta distribution parameters

layout(matrix(c(rep(1,3), 3, 4, 2), 2, 3, byrow=TRUE), heights=c(0.6, 0.4))
#
# Display the L functions over an envelope for the uniform distribution.
#
plot(c(0,1/3), c(-1/8,1/6), type="n", 
     xlab="Normalized Distance", ylab="Total Proportion",
     main="Ripley L Functions")
invisible(replicate(999, {
  plot(Ripley.L(x.unif <- runif(n)), col="#00000010", add=TRUE)
}))
abline(h=0, lwd=2, col="White")
#
# Each of these lines generates a random set of `n` data according to a specified
# distribution, calls `Ripley.L`, and plots its values.
#
plot(Ripley.L(x.norm <- rnorm(n)), col="Blue", lwd=2, add=TRUE)
plot(Ripley.L(x.beta <- rbeta(n, alpha, beta)), col="Red", lwd=2, lty=2, add=TRUE)
plot(Ripley.L(x.mixture <- rmixture(n, p, f)), col="Green", lwd=2, lty=3, add=TRUE)
#
# Display the histograms.
#
n.breaks <- 24
h <- hist(x.norm, main="Normal Sample", breaks=n.breaks, xlab="Value")
curve(dnorm(x)*n*mean(diff(h$breaks)), add=TRUE, lwd=2, col="Blue")
h <- hist(x.beta, main=paste0("Beta(", alpha, ",", beta, ") Sample"), 
          breaks=n.breaks, xlab="Value")
curve(dbeta(x, alpha, beta)*n*mean(diff(h$breaks)), add=TRUE, lwd=2, lty=2, col="Red")
h <- hist(x.mixture, main="Mixture Sample", breaks=n.breaks, xlab="Value")
curve(dmixture(x, p, g)*n*mean(diff(h$breaks)), add=TRUE, lwd=2, lty=3, col="Green")

我假设您想测量分布与制服的接近程度。

您可以查看均匀分布的累积分布函数与样本的经验累积分布函数之间的距离。

假设变量是在集合上定义的{1,2,3,4,5}. 然后均匀分布有 cdfFu(x)

Fu(x)=i=1[x]1/5.

现在,假设您的样本X1,3,5. 然后经验分布X

FX(1)=1/3,FX(2)=1/3,FX(3)=2/3,FX(4)=2/3,FX(5)=1

让样品Y1,1,5. 然后经验分布Y

FY(1)=2/3,FY(2)=2/3,FY(3)=2/3,FY(4)=2/3,FY(5)=1

现在,作为分布之间距离的度量,让我们取每个点的距离之和,即

d(F,G)=i=15|F(x)G(x)|.

你可以很容易地发现d(Fu,FX)<d(Fu,FY).

在更复杂的情况下,您需要修改上面使用的规范,但主要思想保持不变。如果您需要测试程序,最好使用为其开发测试的规范(@TomMinka 指出的规范)。

如果我正确理解了您的问题,那么对您来说“最均匀”的分布将是随机变量将每个观察值取一次的分布——在某种意义上是均匀的。如果存在相同值的观察“集群”,那将是不均匀的。假设我们正在谈论离散的观察,也许您可​​以同时查看概率质量点之间的平均差异、最大差异或可能有多少观察与某个阈值上的“平均值”有差异。

如果观测值真正均匀,则所有 PM 点的值应该相等,并且 max 和 min 之间的差值为 0。平均差值越接近 0,则大部分观测值越“均匀”,越低最大差异和更少的“峰值”也表明经验观察是多么“均匀”。

更新 当然,您可以使用卡方检验来检验均匀性或将经验分布函数与均匀分布函数进行比较,但在这些情况下,即使观察值的分布仍然存在,您也会因观测值中的任何大“差距”而受到惩罚“甚至”。

您正在寻找的度量正式称为discrepancy

一维版本如下:

I=[a,b)表示半开区间并考虑一个有限序列x1,,xNI.

对于一个子集JI, 让A(J,N)表示这个序列里面的元素个数J.

那是,

A(J,N)=|{x1,,xN}J|,
然后让 V(J)表示体积J.

顺序差异x1,,xN定义为

>DN=supJ|A(J,N)V(J)N|,
其中上确界被接管所有半开子区间,其中J=j=1[0,tj)0tj1

中均匀分布,则差异将给定体积中的实际点数与该体积中的预期点数进行比较x1,,xNI

低差异序列通常称为准随机序列

可以在此处找到低差异序列的基本概述,我的博客文章“准随机序列的不合理有效性”比较了应用于数值积分、将点映射到球体表面和准周期平铺的各种方法。