[英]Kolmogorov-Smirnov 2 Sample Test Java give 0 p-value
我正在使用 Apache Commons Math Kolmogorov-Smirnov 測試來確定我的 RNG 生成的樣本是否是均勻分布。
我正在使用UniformIntegerDistribution
來產生均勻分布,我得到了 2000000 個整數的樣本。 然后我把它們放到一個double[]
我也從我的 RNG 2000000 數字中生成並將它們放在一個double[]
中。
我已經繪制了樣本,我看到它是均勻的,但 KS 檢驗給我的 p 值為 0.0,這表明 null 假設兩者來自同一分布(即均勻)是無效的。 這意味着我的 RNG 樣本不符合均勻分布。
double alpha = test.kolmogorovSmirnovTest(a, b);
給我alpha = 0.0
該方法的 Javadoc 內容如下:
計算兩樣本 Kolmogorov-Smirnov 檢驗的 p 值或觀察到的顯着性水平,該檢驗評估 null 假設,即 x 和 y 是從相同概率分布中抽取的樣本。
所以我預計 p 值會很高,因為我看到 plot 顯然是均勻的。
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);
有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.