こんにちは私は、Apache Mathsライブラリ(バージョン2.2)で、特にorg.apache.commons.math.distribution.GammaDistributionImpl
クラスで奇妙な動作に気づきましたが、これはおそらく他のディストリビューションにも当てはまると思います。
次のように、さまざまなガンマ分布からサンプルを取得したかったのです。
public static final double[] gammaSamples(final double[] shapeParameters)
{
double[] samples = new double[shapeParameters.length];
for (int i = 0; i < shapeParameters.length; i++)
{
GammaDistributionImpl gd = new GammaDistributionImpl(shapeParameters[i], 1.0d);
try
{
samples[i] = gd.sample();
}
catch (MathException e)
{
e.printStackTrace();
}
}
return samples;
}
しかし、コードを実行すると、サンプルはすべて疑わしいほど類似している、つまり与えられていることがわかります
public static void main(String[] args)
{
System.out.println(Arrays.toString(gammaSamples(new double[] { 2.0d, 2.0d, 2.0d})));
}
出力例は次のとおりです。
[0.8732612631078758, 0.860967116242789, 0.8676088095186796]
[0.6099133517568643, 0.5960661621756747, 0.5960661621756747]
[2.1266766239021364, 2.209383544840242, 2.209383544840242]
[0.4292184700011395, 0.42083613304362544, 0.42083613304362544]
問題は、各分布に同じ/類似のシードを使用するデフォルトの乱数ジェネレーターが原因だと思います。これを次のようにテストしました。
public static final double[] gammaSamples(final double[] shapeParameters, final Random random)
{
double[] samples = new double[shapeParameters.length];
for (int i = 0; i < shapeParameters.length; i++)
{
GammaDistributionImpl gd = new GammaDistributionImpl(shapeParameters[i], 1.0d);
gd.reseedRandomGenerator(random.nextLong());
try
{
samples[i] = gd.sample();
}
catch (MathException e)
{
e.printStackTrace();
}
}
return samples;
}
これは問題を解決するようです、すなわち与えられた
public static void main(String[] args)
{
System.out.println(Arrays.toString(gammaSamples(new double[] { 2.0d, 2.0d, 2.0d }, new Random())));
}
出力例は次のとおりです。
[2.7506981228470084, 0.49600951917542335, 6.841476090550152]
[1.7571444623500108, 1.941865982739116, 0.2611420777612158]
[6.043421570871683, 0.8852269293415297, 0.6921033738466775]
[1.3859078943455487, 0.8515111736461752, 3.690127105402944]
私の質問は:
どうしたの?これはバグですか、それともApache Mathsディストリビューションがこのように機能することを目的としていましたか?
別々の配布オブジェクトを作成する場合、それらがどのシードを与えられているかを心配し、それらが十分に異なることを確認する必要があるのは、私には奇妙に思えます。
もう1つの少し厄介な点は、これらのディストリビューションを自分のRandomオブジェクトに渡すことができないように見えることです。むしろ、resedRandomGenerator(long seed)メソッドを介してのみシードを変更できます。それらを自分のランダムオブジェクトに渡すことができると、結果を再現しようとするときに非常に役立ちます。
助けてくれてありがとう。