
こんにちは!データサイエンティストの青木和也(https://twitter.com/kaizen_oni)です!
今回の記事では、統計学の青本「自然科学の統計学」の第5章-演習問題1「
問題文
<
適合度検定統計量の分布: 近似問題> 多項分布の
適合度検定統計量の分布は、セルの期待度数が小さい時 分布で必ずしもよく近似できない。 そのような例として、
の三項分布
で、
が観測された場合を考えよう。この場合、
であり、
だから、 近似によれば、4.67以上の値が得られる確率は約10%となる。 近似の良不良を見るためにこの確率を正確に求めてみよう。
いま、
を3つに分割する型は全部で12通りあるが、このうち が 以上になるのは下記の7つの型である。 たとえば一番上の9,0,0の確率は
から であり、そのような型を与える観測値は の3個だから、型9,0,0の確率は となる。 他の型についての空欄を埋めて完成し、
となる確率が となることを確かめよ。 東京大学教養学部統計学教室『自然科学の統計学』(東京大学出版社/2001) 第5章 演習問題 P173
適合度検定を行う際に、分母が3で分子でも3を引き算しているのはなぜ?
実際に観測された値を観測度数
今回の問題の場合は、
上記の計算をし、
「この理論値はいったいどれだけ信用できるのか」
を確かめることができるのです。
実装コード
今回の問題を解く際の実装コードは以下の通りです。
import numpy as np
import math
import pandas as pd
def calc_chi_and_prob(arr):
sum_chi = 0
# 確率のうち、分母にある階乗以外の部分を先に計算
sum_prob = math.factorial(9) / (3**9)
for val in arr:
# カイ二乗値を計算
sum_chi += (val - 3) ** 2/3
# 分母にある階乗部分を計算
sum_prob /= math.factorial(val)
# 数字のペアのうち、一意な数字の個数を求める
pair = set(arr)
unique_n = len(pair)
# 全ての数字が異なる場合は3!がペアのパターン数
if unique_n == 3:
pair_num = math.factorial(3)
# 1つ被りがある場合は3!/2!がペアのパターン数
else:
pair_num = math.factorial(3) / math.factorial(2)
return sum_chi, sum_prob, pair_num
arrs = [
[9,0,0],
[8,1,0],
[7,2,0],
[7,1,1],
[6,3,0],
[6,2,1],
[5,4,0],
]
arrs = [ calc_chi_and_prob(arr) for arr in arrs]
df = pd.DataFrame(arrs, columns = ['chi_square', 'prob', 'pair_num'])
# ペアごとの期待値を計算
df['E'] = df.prob * df.pair_num
display(df)
# 期待値の合計を計算
print(df.E.sum())
実装コード解説
実装では、以下の4ステップで問題を解いています。
- 当該ペアの確率分布を計算する
- 当該ペアの並び順の個数を計算する
- 当該ペアの
を計算する - 各ペアの期待値を計算して、最後に総和を求める
順に解説をしていきます。
当該ペアの確率分布を計算する
当該ペアの確率分布を計算している実装部分は以下のコードです。
def calc_chi_and_prob(arr):
# ...
# 確率のうち、分母にある階乗以外の部分を先に計算 ... (1)
sum_prob = math.factorial(9) / (3**9)
for val in arr:
# ...
# ...
# 分母にある階乗部分を計算 ... (2)
sum_prob /= math.factorial(val)
確率分布の計算には以下の式
なお、math.factorial(n)は
当該ペアの並び順の個数を計算する
重複を許す3個の数字の並び順を考える場合は、以下の3パターンを考える必要があります。
- 3つとも数字が異なるパターン
- 3つの数字のうち、2つが重複しているパターン(例: 1,1,7)
- 3つの数字の全てが重複しているパターン
本問題の場合はパターン3は登場しないので、パターン1とパターン2について考えましょう。
パターン1の場合はシンプルに3つの数字の並び順を考えれば良いので、以下のように求めることができます。
一方で、パターン2の場合は、ペアの数字が
すると、3つの数字を並べた
このような場合わけをした上で、並び方のパターン数を計算しているのが以下実装部分になります。
def calc_chi_and_prob(arr):
# ...
# 数字のペアのうち、一意な数字の個数を求める
pair = set(arr)
unique_n = len(pair)
# 全ての数字が異なる場合は3!がペアのパターン数
if unique_n == 3:
pair_num = math.factorial(3)
# 1つ被りがある場合は3!/2!がペアのパターン数
else:
pair_num = math.factorial(3) / math.factorial(2)
当該ペアの を計算する
今回のケースでは、
def calc_chi_and_prob(arr):
sum_chi = 0
# ...
# ...
for val in arr:
# カイ二乗値を計算
sum_chi += (val - 3) ** 2/3
各ペアの期待値を計算して、最後に総和を求める
最後に、計算した確率、並びのパターン数、
df = pd.DataFrame(arrs, columns = ['chi_square', 'prob', 'pair_num'])
# ペアごとの期待値を計算 ... (1)
df['E'] = df.prob * df.pair_num
display(df)
# 期待値の合計を計算 ... (2)
print(df.E.sum())

期待値の総和は0.16567…となっており、四捨五入すれば問題文で示唆されている0.166と合致していることがわかります。
まとめ
今回の記事では、統計学の青本「自然科学の統計学」の第5章-演習問題1「
確率と並び順の計算自体は高校数学レベル、
皆さんも、
コメント