統計ソフトウェアのテストに役立つテクニック/アプローチは何ですか?私は特に、最尤法を使用してパラメトリック推定を行うプログラムに興味があります。
他のプログラムや公開されたソースからの結果と比較することは常に可能であるとは限りません。なぜなら、私が自分のプログラムを書くときのほとんどは、必要な計算が既存のシステムにまだ実装されていないためです。
私は正確さを保証できる方法を主張していません。エラーの一部をキャッチできるテクニックに満足しています。
統計ソフトウェアのテストに役立つテクニック/アプローチは何ですか?私は特に、最尤法を使用してパラメトリック推定を行うプログラムに興味があります。
他のプログラムや公開されたソースからの結果と比較することは常に可能であるとは限りません。なぜなら、私が自分のプログラムを書くときのほとんどは、必要な計算が既存のシステムにまだ実装されていないためです。
私は正確さを保証できる方法を主張していません。エラーの一部をキャッチできるテクニックに満足しています。
回答:
有用なテクニックの1つは、モンテカルロテストです。同じことを行う2つのアルゴリズムがある場合は、両方を実装し、ランダムなデータをフィードし、(数値のファズの小さな許容範囲内で)同じ答えを生成することを確認します。私はこれを以前に数回行ったことがあります:
KendallのTau Bの効率的で実装が難しい実装を作成しました。それをテストするために、で実行される非常に単純な50行の実装を作成しました。 O (N 2)
リッジ回帰を行うためのコードを書きました。これを行うための最適なアルゴリズムは、かどちらのケースにいるかに依存するため、とにかく2つのアルゴリズムが必要でした。 p > n
これらのどちらの場合でも、Dプログラミング言語で比較的よく知られた手法(実装が存在しない)を実装していたため、Rに対していくつかの結果を確認しました。それでも、モンテカルロテストでは、他の方法では見つけられなかったであろうバグが見つかりました。 。
別の良いテストはアサートです。計算の正しい結果が正確に何であるかは正確にはわからない場合がありますが、それは、計算のさまざまな段階で健全性チェックを実行できないことを意味するものではありません。実際には、コードにこれらの多くがあり、それらすべてが合格した場合、コードは通常正しいです。
編集:3番目の方法は、正確にわからない場合でも、正しいおおよその回答が少なくともおおよそわかっているアルゴリズムデータ(合成または実数)をフィードし、回答が妥当かどうかを検査で確認することです。たとえば、パラメータの推定値は正確にはわからないかもしれませんが、どのパラメータが「大きい」か、どのパラメータが「小さい」かはわかります。
これが本当にあなたの質問に対する答えであるかどうかはわかりませんが、少なくとも接線的に関連しています。
MapleでStatisticsパッケージを管理しています。テストが難しいコードの興味深い例は、さまざまな分布によるランダムなサンプル生成です。エラーが生成されていないことをテストするのは簡単ですが、生成されたサンプルが要求された分布に「十分に」適合しているかどうかを判断するのは難しいです。Mapleにはシンボリック機能と数値機能の両方があるため、シンボリック機能の一部を使用して(純粋に数値の)サンプル生成をテストできます。
いくつかのタイプの統計的仮説検定を実装しました。そのうちの1つは、カイ二乗適切なモデル検定 -所定の確率分布の逆CDFから決定されたビン内のサンプル数のカイ二乗検定です。したがって、たとえば、コーシー分布のサンプル生成をテストするには、次のようなものを実行します
with(Statistics):
infolevel[Statistics] := 1:
distribution := CauchyDistribution(2, 3):
sample := Sample(distribution, 10^6):
ChiSquareSuitableModelTest(sample, distribution, 'bins' = 100, 'level' = 0.001);
好きなだけ大きなサンプルを生成できるため、かなり小さくすることができます。
有限モーメントの分布の場合、私は一方で多数のサンプルモーメントを計算し、他方で対応する分布モーメントとそれらの標準誤差を記号的に計算します。たとえば、ベータ版の場合:
with(Statistics):
distribution := BetaDistribution(2, 3):
distributionMoments := Moment~(distribution, [seq(1 .. 10)]);
standardErrors := StandardError[10^6]~(Moment, distribution, [seq(1..10)]);
evalf(distributionMoments /~ standardErrors);
これは数の減少するリストを示しており、最後のリストは255.1085766です。したがって、10番目のモーメントの場合でも、モーメントの値は、サイズサンプルのサンプルモーメントの標準誤差の値の250倍を超えています。つまり、次のように多かれ少なかれ実行するテストを実装できます。
with(Statistics):
sample := Sample(BetaDistribution(2, 3), 10^6):
sampleMoments := map2(Moment, sample, [seq(1 .. 10)]);
distributionMoments := [2/5, 1/5, 4/35, 1/14, 1/21, 1/30, 4/165, 1/55, 2/143, 1/91];
standardErrors :=
[1/5000, 1/70000*154^(1/2), 1/210000*894^(1/2), 1/770000*7755^(1/2),
1/54600*26^(1/2), 1/210000*266^(1/2), 7/5610000*2771^(1/2),
1/1567500*7809^(1/2), 3/5005000*6685^(1/2), 1/9209200*157366^(1/2)];
deviations := abs~(sampleMoments - distributionMoments) /~ standardErrors;
上記の最初の実行からの数値distributionMoments
とその数値standardErrors
。これで、サンプルの生成が正しい場合、偏差の数値は比較的小さくなります。私はそれらがほぼ正規分布していると仮定します(実際にはそうではありませんが、十分に近いです-これらはサンプル自体ではなくサンプルモーメントのスケーリングされたバージョンであることを思い出してください)。したがって、たとえば、偏差がある場合にフラグを立てることができます4より大きい-分布モーメントから標準誤差の4倍以上逸脱するサンプルモーメントに対応します。サンプル生成が適切な場合、これがランダムに発生することはほとんどありません。一方、最初の10個のサンプルモーメントが分布モーメントと0.5%未満の範囲で一致している場合、分布の近似はかなり良好です。
これらの両方の方法が機能する理由は、サンプル生成コードとシンボリックコードがほぼ完全にばらばらであることです。2つの間にオーバーラップがある場合、そのオーバーラップのエラーは、サンプル生成とその検証の両方で明らかになり、キャッチされません。