こんにちは、サーバエンジニアの池脇と申します。
みなさんはランダムに実行される処理を実装した際に、その処理が設定した確率通りに振る舞っているかテストしたいと思ったことはないでしょうか?
今回は適合度検定を利用して、そのテストを行う方法をご紹介したいと思います。
適合度検定
適合度検定とは、観察されたデータが特定の理論的な分布(期待値)にどの程度適合しているかを検定する方法です。主に以下のような状況で使用されます。
- ある標本が特定の分布に従っているか確認したい場合
- 観察データが理論的な期待値に一致しているか評価したい場合
例えば、サイコロを十分な回数1振って各面が出た回数を数え、それが公平なサイコロ(各面が1/6の確率で出現する)に従っているかどうかを確認する場合に適合度検定を使用します。
適合度検定は期待値がわかっている場合に利用できます。つまり、出力される値の出現率がわかっている場合にこれを利用してテストが可能です。
カイ二乗検定
適合度検定の主要な手法の1つがカイ二乗検定です。カイ二乗検定は、カテゴリーデータに対して期待された頻度と観察された頻度の間の差を評価するために使用されます。
以下の式を用いてカイ二乗統計量を計算します。
χ² = Σ ((Observed[i] - Expected[i])² / Expected[i])
ここで、$Observed[i]$は観察された値、$Expected[i]$は期待値です。この統計量がカイ二乗分布に従うことを利用して検定を行います。
Javaでの実装方法
Apache Commons Math
のChiSquareTest
を利用することでカイ二乗適合度検定を行うことができます。
以下のコードは、観察データが公平なサイコロの期待値に従っているかをカイ二乗適合度検定で評価する例です。
import org.apache.commons.math3.stat.inference.TestUtils;
public class ChiSquareTestExample {
public static void main(String[] args) {
// 観察データ(サイコロの各面が出た回数)
long[] observed = {18, 12, 15, 14, 22, 19};
// 期待値データ(公平なサイコロの場合、各面の出現率)
double[] expected = {16.67, 16.67, 16.67, 16.67, 16.67, 16.67};
// カイ二乗適合度検定の実行
double pValue = TestUtils.chiSquareTest(expected, observed);
// ここで結果を判定
if (pValue < 0.05) {
System.out.println("有意差があります。p-value: " + pValue);
} else {
System.out.println("有意差はありません。p-value: " + pValue);
}
}
}
ここでは「5%水準2」を満たしているかで結果の判定を行なっています。
今回の場合はp値(p-value)が0.05以上であれば有意差3がない、すなわち期待値に適合しているとみなせるということになります。
有意差があるとみなすかどうかは求める精度によって変わります。決まった水準というものはなく、主観的に決められる値です。
実装した処理がどの程度の精度を求めているのかを考えた上で水準を設定しましょう。
まとめ
適合度検定を利用することで、ランダム処理が確率通りに実行されているかを統計学的にテストすることが可能です。
ランダム処理のテストをこのような手法を利用して自動テストに組み込むことで、これまで以上の品質を担保できるようになるかと思います。
「ランダム処理を実装したはいいものの、確率通りに動いているか不安だな…」と思った時には試してみてはいかがでしょうか?
以上、池脇でした。