Kolmogorov-Smirnov 2 样本检验 Java 给出 0 p 值
Kolmogorov-Smirnov 2 Sample Test Java give 0 p-value
我正在使用 Apache Commons Math Kolmogorov-Smirnov 测试来确定我的 RNG 生成的样本是否是均匀分布。
我正在使用 UniformIntegerDistribution
生成均匀分布,我得到了 2000000 个整数的样本。然后我将它们放入 double[]
我也从我的 RNG 2000000 号码中生成并将它们放在 double[]
.
中
我绘制了样本,我发现它是均匀的,但 K-S 检验给出了 0.0 的 p 值,这表明从同一分布(即均匀分布)中抽取的两个零假设无效.这意味着我的 RNG 样本不符合均匀分布。
double alpha = test.kolmogorovSmirnovTest(a, b);
给我alpha = 0.0
方法的 Javadoc 是这样写的:
Computes the p-value, or observed significance level, of a two-sample Kolmogorov-Smirnov test evaluating the null hypothesis that x and y are samples drawn from the same probability distribution.
所以我希望 p 值很高,因为我看到情节明显均匀。
IntegerDistribution uniform = new UniformIntegerDistribution(1, 81);
ArrayList<Integer> lis = new ArrayList<>();
int i = 0;
while (i < 100000) {
//Creates a list of 20 numbers ε [1,80]
List<Integer> l = ls.createRandomNumbersInclusive(80, 20);
lis.addAll(l);
Assertions.assertFalse(l.stream().anyMatch(it -> it > 80));
Assertions.assertFalse(l.stream().anyMatch(it -> it < 1));
i++;
}
KolmogorovSmirnovTest test = new KolmogorovSmirnovTest();
var sample = uniform.sample(2000000);
List<Integer> ll = new ArrayList<>();
double[] a = new double[2000000];
for(var j = 0; j<2000000; j++) {
a[j] = sample[j];
}
double[] b = lis.stream().map(it -> Double.valueOf(it)).mapToDouble(Double::doubleValue).toArray();
var alpha = test.kolmogorovSmirnovTest(a, b);
System.out.println("Alpha "+ alpha); //This gives me 0.0
/** I am doing the below to get the count per numbers [1,80] and plot them.
* I see them being uniform
* 1 ===
* 2 ===
* ...
* 80 ===
*/
Map<Integer, Long> result = lis.stream().collect(Collectors.groupingBy(it -> it, Collectors.counting()));
让我担心的是,如果我创建一个新的 UniformIntegerDistribution
并获得一个 sample2
,然后将其放入 test.kolmogorovSmirnovTest(a, b);
,我确实会得到接近 1 的 p 值这正是我所期望的。
我要么在 Java 上做错了,要么在 RNG 生成的数字中有一些我没有得到的东西。
createRandomNumbersInclusive
的代码是
public List<Integer> fetchNumberList(final int drawNumberMin, final int drawNumberMax, final int drawNumberCount) {
final List<Integer> range = new ArrayList<Integer>();
for (int i = drawNumberMin; i <= drawNumberMax; i++) {
range.add(i);
}
Collections.shuffle(range, rng);
return new ArrayList<Integer>(range.subList(0, drawNumberCount));
}
RNG 为 rng = SecureRandom.getInstance("NativePRNGNonBlocking");
我找到了问题背后的原因。我最初使用的 UniformRealDistribution
与 kolmogorovSmirnovTest(RealDistribution distribution, double[] data)
一起使用
然而,出于某种原因,UniformIntegerDistribution
是包含 - 排他性的。
当我把IntegerDistribution uniform = new UniformIntegerDistribution(1, 81);
改成IntegerDistribution uniform = new UniformIntegerDistribution(1, 80);
的时候
成功了。
我正在使用 Apache Commons Math Kolmogorov-Smirnov 测试来确定我的 RNG 生成的样本是否是均匀分布。
我正在使用 UniformIntegerDistribution
生成均匀分布,我得到了 2000000 个整数的样本。然后我将它们放入 double[]
我也从我的 RNG 2000000 号码中生成并将它们放在 double[]
.
我绘制了样本,我发现它是均匀的,但 K-S 检验给出了 0.0 的 p 值,这表明从同一分布(即均匀分布)中抽取的两个零假设无效.这意味着我的 RNG 样本不符合均匀分布。
double alpha = test.kolmogorovSmirnovTest(a, b);
给我alpha = 0.0
方法的 Javadoc 是这样写的:
Computes the p-value, or observed significance level, of a two-sample Kolmogorov-Smirnov test evaluating the null hypothesis that x and y are samples drawn from the same probability distribution.
所以我希望 p 值很高,因为我看到情节明显均匀。
IntegerDistribution uniform = new UniformIntegerDistribution(1, 81);
ArrayList<Integer> lis = new ArrayList<>();
int i = 0;
while (i < 100000) {
//Creates a list of 20 numbers ε [1,80]
List<Integer> l = ls.createRandomNumbersInclusive(80, 20);
lis.addAll(l);
Assertions.assertFalse(l.stream().anyMatch(it -> it > 80));
Assertions.assertFalse(l.stream().anyMatch(it -> it < 1));
i++;
}
KolmogorovSmirnovTest test = new KolmogorovSmirnovTest();
var sample = uniform.sample(2000000);
List<Integer> ll = new ArrayList<>();
double[] a = new double[2000000];
for(var j = 0; j<2000000; j++) {
a[j] = sample[j];
}
double[] b = lis.stream().map(it -> Double.valueOf(it)).mapToDouble(Double::doubleValue).toArray();
var alpha = test.kolmogorovSmirnovTest(a, b);
System.out.println("Alpha "+ alpha); //This gives me 0.0
/** I am doing the below to get the count per numbers [1,80] and plot them.
* I see them being uniform
* 1 ===
* 2 ===
* ...
* 80 ===
*/
Map<Integer, Long> result = lis.stream().collect(Collectors.groupingBy(it -> it, Collectors.counting()));
让我担心的是,如果我创建一个新的 UniformIntegerDistribution
并获得一个 sample2
,然后将其放入 test.kolmogorovSmirnovTest(a, b);
,我确实会得到接近 1 的 p 值这正是我所期望的。
我要么在 Java 上做错了,要么在 RNG 生成的数字中有一些我没有得到的东西。
createRandomNumbersInclusive
的代码是
public List<Integer> fetchNumberList(final int drawNumberMin, final int drawNumberMax, final int drawNumberCount) {
final List<Integer> range = new ArrayList<Integer>();
for (int i = drawNumberMin; i <= drawNumberMax; i++) {
range.add(i);
}
Collections.shuffle(range, rng);
return new ArrayList<Integer>(range.subList(0, drawNumberCount));
}
RNG 为 rng = SecureRandom.getInstance("NativePRNGNonBlocking");
我找到了问题背后的原因。我最初使用的 UniformRealDistribution
与 kolmogorovSmirnovTest(RealDistribution distribution, double[] data)
然而,出于某种原因,UniformIntegerDistribution
是包含 - 排他性的。
当我把IntegerDistribution uniform = new UniformIntegerDistribution(1, 81);
改成IntegerDistribution uniform = new UniformIntegerDistribution(1, 80);
的时候
成功了。