如何确定两个数据集是否彼此靠近?

数据挖掘 Python 统计数据 可视化 模拟
2021-10-12 10:31:50

我有以下三个数据集。

data_a=[0.21,0.24,0.36,0.56,0.67,0.72,0.74,0.83,0.84,0.87,0.91,0.94,0.97]
data_b=[0.13,0.21,0.27,0.34,0.36,0.45,0.49,0.65,0.66,0.90]
data_c=[0.14,0.18,0.19,0.33,0.45,0.47,0.55,0.75,0.78,0.82]

data_a 是真实数据,另外两个是模拟数据。在这里,我试图检查哪一个(data_b 或 data_c)与 data_a 最接近或非常相似。目前我正在视觉上使用 ks_2samp 测试(python)。

视觉上

我绘制了真实数据的 cdf 与模拟数据的 cdf,并尝试直观地查看哪个最接近。

data_a 与 data_b 的 cdf

以上是 data_a 的 cdf 与 data_b 的 cdf 在此处输入图像描述

以上是 data_a 的 cdf vs data_c 的 cdf

因此,通过直观地看到它,人们可能会说 data_c 更接近 data_a 然后 data_b 但它仍然不准确。

Kolmogorov-Smirnov (KS) 测试

第二种方法是 KS 测试,我用 data_b 测试了 data_a 以及用 data_c 测试了 data_a。

>>> stats.ks_2samp(data_a,data_b)
Ks_2sampResult(statistic=0.5923076923076923, pvalue=0.02134674813035231)
>>> stats.ks_2samp(data_a,data_c)
Ks_2sampResult(statistic=0.4692307692307692, pvalue=0.11575018162481227)

从上面我们可以看到,当我们用 data_c 测试 data_a 时,统计数据较低,因此 data_c 应该比 data_b 更接近 data_a。我没有考虑 p 值,因为将其视为假设检验并使用获得的 p 值是不合适的,因为该检验是根据预先确定的原假设设计的。

所以我的问题是,如果我做得正确,还有其他更好的方法吗?谢谢

3个回答

考虑使用Earth Mover 距离(即Wasserstein-1距离),它(类似于 KL 散度)可用于计算点集之间的“距离”(或者更确切地说是由它们引起的经验分布)。scipy中有一个方法,还有这个库

好处:

  • 您不需要在每组中具有相同数量的点(EMD 允许“拆分”质量)。
  • KL 散度的一个优点是,如果分布没有相同的支持,KLD 可以是未定义的或无限的(尽管使用 Jensen-Shannon 散度可以减轻这种情况)。此外,估计熵通常很困难,而且不是无参数的(通常需要分箱或 KDE),而可以直接在输入数据点上解决 EMD 优化。
  • 相对于简单统计(例如,比较均值和协方差或范数)的优势在于它们往往会丢失信息。例如,匹配前两个矩并不强制匹配第三个矩;或者,两个数据集可以具有相同的范数,尽管它们非常不同(对于n 点,上的每一点 n- 相同半径的超球面具有相同的范数)。相反,EMD 必须考虑一个集合中的每个点与另一个集合中的每个点的关系。

我认为使用 KS 测试完全合理。另见这篇文章一个警告是,它对 supremum 的使用有点极端。例如,一个分布有很大的 CDF 偏差δ在某些时候,其余时间非常接近,而另一时间则偏离δϵ对于一些微小的ϵ很多时候 - KS 统计数据会更喜欢前者。这是否有意义取决于您。

您可以通过找到分布之间的最低Kullback-Leibler 散度来采用信息论方法。SciPy 的熵函数中有一个 KL 散度选项

>>> from scipy.stats import entropy

>>> p = [0.21,0.24,0.36,0.56,0.67,0.72,0.74,0.83,0.84,0.87] # Data removed to make equal sizes: [0.91,0.94,0.97]
>>> q_1 = [0.13,0.21,0.27,0.34,0.36,0.45,0.49,0.65,0.66,0.90]
>>> print(entropy(p, q_1)) 
0.019822015024454846

>>> q_2 =[0.14,0.18,0.19,0.33,0.45,0.47,0.55,0.75,0.78,0.82]
>>> print(entropy(p, q_2))
0.01737229446663193

第二个模拟分布比第一个模拟分布更接近真实分布。

如果您对推理感兴趣,您可以运行许多模拟并计算 p 值。该过程是置换测试的一种变体。

因为我们不应该删除任何数据......我们可以使用来自原点的向量范数(l2 norm),因为 data_a、data_b、data_c 是数组。

 import numpy as np    
 import pandas as pd
 from numpy.linalg import norm
 l2_a=norm(data_a)
 l2_b=norm(data_b)
 l2_c=norm(data_c)
 print(l2_a,l2_b,l2_c)

输出

2.619885493680974 1.5779100101083077 1.6631897065578538.

由于 l2_a、l2_c 的值更接近,data_a 和 data_c 彼此接近。