はじめに
統計学の教科書の割と最初の方で出てくる「分散」ですが、「標本分散」と「不偏分散」というものが教科書に載っているはずです(最初に見たときはどう使い分けるのか悩んだものです)。
標本分散や不偏分散を母分散の推定量と見たとき、標本分散には不偏性がなく「標本分散の期待値」は母分散よりも小さくなってしまうという性質がある一方で(これはサンプルサイズが小さい場合に顕著です)、不偏分散には「不偏分散の期待値」が母分散に一致するという性質があります。
ですから、何らかの実験でデータを得たときにその結果から背後にある母集団の分散を推定したいような場合には不偏分散を用いることになります。一方、標本分散は得られたデータがどのように散らばっているのかを記述するために使うことになります。
今回は、母集団から適当なサンプルサイズで抽出したサンプルに対して標本分散・不偏分散を計算してサンプルサイズに対する標本分散・不偏分散の動きを可視化してみたいと思います。
※詳しい話は書籍やネットで「一致性」や「不偏性」で調べてください。今回問題になるのは不偏性の方です。
実験と結果
標準正規分布に従うサイズ1000000の母集団を用意します。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
np.random.seed(seed=42)
population = np.random.normal(0, 1, 1000000) # 母集団:平均0, 分散1, サイズ1000000
sns.histplot(population)
plt.title('Population Distribution')
plt.show()
実験1
母集団からサンプルサイズ50で標本抽出を行い不偏分散と標本分散を求める操作を(とりあえず)1000回行いそれぞれの平均を求めます。
unbiased_variances = []
sample_variances = []
for _ in range(1000):
# 母集団から50件の抽出を行い不偏分散と標本分散を求めるのを1000回
sample = np.random.choice(population, 50)
unbiased_variance = np.var(sample, ddof=1) # 不偏分散
sample_variance = np.var(sample, ddof=0) # 標本分散
unbiased_variances.append(unbiased_variance)
sample_variances.append(sample_variance)
np.mean(unbiased_variances)
1.0042536587305344
np.mean(sample_variances)
0.9841685855559237
不偏分散の方がいい感じに母分散=1を推定できています。標本分散は少し小さめになっていることがわかります。
実験2
母集団からサンプルサイズ5~1000で変えながら標本抽出を行い、不偏分散と標本分散を求める操作を(とりあえず)1000回行いそれぞれの平均を求めます。最後にサンプルサイズに対して、標本分散・不偏分散の平均をプロットします。
sample_size_list = []
uv_mean_list = []
sv_mean_list = []
for sample_size in range(5, 1001, 5):
# サンプルサイズを5~1000まで5刻みで変化させる。
unbiased_variances = []
sample_variances = []
for _ in range(1000):
# 母集団から指定サンプルサイズの抽出を行い不偏分散と標本分散を求めるのを1000回
sample = np.random.choice(population, sample_size)
unbiased_variance = np.var(sample, ddof=1) # 不偏分散
sample_variance = np.var(sample, ddof=0) # 標本分散
unbiased_variances.append(unbiased_variance)
sample_variances.append(sample_variance)
# サンプルサイズ、そのサンプルサイズでの不偏分散の平均・標本分散の平均を追加
sample_size_list.append(sample_size)
uv_mean_list.append(np.mean(unbiased_variances))
sv_mean_list.append(np.mean(sample_variances))
df1 = pd.DataFrame({'sample_size': sample_size_list, 'mean_of_variance': uv_mean_list})
df1['variance_type'] = 'unbiased_variance'
df2 = pd.DataFrame({'sample_size': sample_size_list, 'mean_of_variance': sv_mean_list})
df2['variance_type'] = 'sample_variance'
df = pd.concat([df1, df2])
sns.lineplot(data=df, x='sample_size', y='mean_of_variance', hue='variance_type')
plt.show()
サンプルサイズの小さいところでは標本分散が母分散よりかなり小さくなっていますが、サンプルサイズを大きくするにつれて母分散=1とのズレが小さくなっていく様子を確認できます。
最後に
最初に見たとき標本分散と不偏分散の違いが直感的にすぐに頭に入ってこなかったのですが可視化するとそんなに難しくなかったなという感想です。