ぬーみんの日記

某大医大生の短期留学と膝のリハビリと医学メモ

German Tank Problerm

どーも、昨日の練習試合で死んでるぬーみんです。

臨床実習が始まってるばばあにはもう若い子の相手なんて務まりませんよ・・・練習不足なのは認めますが・・・

 

さて、今日の表題は英語で書きましたが、医療ネタとは関係がありません。統計学の話題です。どうでもいいんだけど、大きな声では言えないですがぬーみんは一般教養の統計学で落単したことがあります。それ以来統計には憎しみと好奇心のような感情を抱いています。

 

第二次世界大戦中、連合国軍はドイツ軍戦車の数を把握したいと思いました。現在捕虜となった同じタイプの戦車が数個あるようで、それぞれシリアル番号が付けられています。さて少数のサンプルから全体の数を予測することは可能でしょうか?

結論から言うと、非常に高精度で予測できる計算式が開発されました。

サンプルの中の最大のシリアル番号に(最大番号 / サンプル数)を足して1を引いたものです。なんでこうなるのかはよくわかりません。ですが、「標本の最大値に標本の平均間隔を足したのが、母集団の最大値(N)」というのが簡単な解釈のようです。

シリアル番号のように1から最大値Nまでどれか1つがついている時にある数字が選ばれる確率というのは、公正なサイコロでどの数字も同じ確率で出るという考え方が応用できます。これは離散一様分布といいます。詳しくはwikiに載ってます(丸投げ)

離散一様分布 - Wikipedia

このm / kというのは母集団の標準偏差に非常に似た値のようです。

出典は不明ですが、pythonでシミュレートするコードを見つけました。コードを実行してみてもかなりの精度であることがわかると思います。

import random

def german_tank(n, k):
tanks = list(range(n))
random.shuffle(tanks)
m = max(tanks[:k])
return (k+1.0)*m/k - 1

if __name__ == '__main__':
patterns = [
(100, 5), (100, 10), (100, 20), (100, 50),
(10000, 10), (10000, 100), (10000, 1000),
(100000, 100), (100000, 1000), (100000, 10000)
]
for pattern in patterns:
results = []
for i in list(range(5)):
results.append(german_tank(*pattern))
print ('N:%6d k:%5d estimated:' % pattern, ''.join('%10.2f' % x for x in results))

 

また、ベイズ推定を使えば、次のような式でも推定することができるそうです。(これもよくわからんかった)

(m-1)**1

 

統計の力は計り知れないものですね。将来的にうまく利用できるようになりたいものですが・・・難しい・・・

*1:k-1) / (k-2