LoginSignup
2
2

統計検定2級の問題をプログラムで検証してみた

Posted at

背景

統計検定2級の問題で、2枚のコインを天秤で量る場合の誤差を考える問題がありました。
(統計検定2級受験予定で、この問題を解いてない方は、答えを見ないでくださいね。)

天秤の測定誤差が、平均0、分散 $ σ^2 $、となる場合、
1枚ずつ測定すると、測定誤差は、そのまま、平均0、分散$ σ^2 $となるが、
2枚の和と差を測定し、その連立方程式を解いて、それぞれ1枚の重さを計算すると、
平均0、分散 $ \frac{σ^2}{2} $ になるという問題です。

これを、プログラムで検証してみました。

準備

まず、以下の準備。

  • numpy のインポート
  • 正規分布をランダム出力する
  • 平均、標準偏差、分散を出力する関数
  • コインの重さや標準偏差、サンプルサイズ
import numpy as np
rng = np.random.default_rng()

# 平均、標準偏差、分散を出力する関数
def print_mean_std(title,np_list):
  mean = np.nanmean(np_list)
  std  = np.nanstd(np_list)
  var  = np.var(np_list)
  print(f'{title} mean={mean:.2f} std={std:.2f} var={var:.2f}')
  
weitgt_A = 10 # コインAの重さ
weight_B = 11 # コインBの重さ
sigma    = 1  # 天秤で量ったときの標準偏差
n        = 10000

普通に量った場合

np_weight_A_list = rng.normal(weitgt_A,sigma,n)
print_mean_std('普通に量った場合 コインA',np_weight_A_list)
np_weight_B_list = rng.normal(weight_B,sigma,n)
print_mean_std('普通に量った場合 コインB',np_weight_B_list)
普通に量った場合 コインA mean=10.01 std=0.99 var=0.99
普通に量った場合 コインB mean=10.99 std=1.00 var=1.00

測定誤差は、天秤の測定誤差(分散$ σ^2 $)そのままの1となります。

2枚の和と差を測定した場合

2枚のコインの重さの和(X)と差(Y)は、

\begin{align}
X = a + b\\
Y = a - b
\end{align}

となり、

X  = rng.normal(weitgt_A+weight_B,sigma,n)
print_mean_std('コインAとコインBの和',X)
Y = rng.normal(weitgt_A-weight_B,sigma,n)
print_mean_std('コインAとコインBの差',Y)
コインAとコインBの和 mean=20.99 std=1.00 var=0.99
コインAとコインBの差 mean=-1.00 std=1.00 var=1.00

測定誤差は、和でも差でも、天秤の測定誤差(分散$ σ^2 $)そのままの1となります。

和と差から、それぞれ1枚の重さを計算

2枚のコインの重さの和(X)と差(Y)から、それぞれのコインの重さは、

\begin{align}
a = \frac{X + Y}{2} \\
b = \frac{X - Y}{2}
\end{align}

で求まるので、測定誤差は、を求めると、

np_weight_A_list_2 = ( X + Y ) / 2
print_mean_std('和と差から求めた場合 コインA',np_weight_A_list_2)
np_weight_B_list_2 = ( X - Y ) / 2
print_mean_std('和と差から求めた場合 コインB',np_weight_B_list_2)
和と差から求めた場合 コインA mean=10.00 std=0.71 var=0.50
和と差から求めた場合 コインB mean=10.99 std=0.71 var=0.50

理論値の通り、測定誤差(分散)が、1枚ずつ測定するときの、1/2になりました。

3枚を3回量る場合を考えると、、、

2枚の和と1枚の差(引き算)を3回量ることにしました。以下のように、X,Y,Zを定義して、

\begin{align}
X = - a + b + c\\
Y =   a - b + c\\
Z =   a + b - c
\end{align}

で3回量ると、

連立方程式の解答は省略して、答えをズバリ

\begin{align}
a = \frac{Y + Z}{2}\\
b = \frac{Z + X}{2}\\
c = \frac{X + Y}{2}
\end{align}

2枚を2回量ったときと同じになり、このやり方では、うまくいかないことがわかりました。(2枚を2回量ったときと測定誤差が変わらない。)

4枚を4回量る場合を考えると、、、

2枚の和と差の、和と差を量ることにしました。具体的には、(aとbの和と差)と(cとdの和と差)の和と差を考え、以下のように、X,Y,Z,Wを定義します。

\begin{align}
X = ( a + b ) + ( c + d )\\
Y = ( a + b ) - ( c + d )\\
Z = ( a - b ) + ( c - d )\\
W = ( a - b ) - ( c - d )
\end{align}

連立方程式の解答は省略して、答えをズバリ

\begin{align}
a = \frac{X + Y + Z + W}{4}\\
b = \frac{X + Y - Z - W}{4}\\
c = \frac{X + Y + Z - W}{4}\\
d = \frac{X + Y - Z + W}{4}
\end{align}

となり、1枚ずつ測定するときの、1/4になりました。これもプログラムで試してみました。
再度、4枚分のコインの重さや標準偏差、サンプルサイズを定義します。

## 4枚を4回量る
weitgt_A = 10 # コインAの重さ
weight_B = 11 # コインBの重さ
weitgt_C = 12 # コインCの重さ
weight_D = 13 # コインDの重さ
sigma    = 1  # 天秤で量ったときの標準偏差
n        = 10000

普通に量った場合

# 普通に量った場合
np_weight_A_list = rng.normal(weitgt_A,sigma,n)
print_mean_std('普通に量った場合 コインA',np_weight_A_list)
np_weight_B_list = rng.normal(weight_B,sigma,n)
print_mean_std('普通に量った場合 コインB',np_weight_B_list)
np_weight_C_list = rng.normal(weitgt_C,sigma,n)
print_mean_std('普通に量った場合 コインC',np_weight_C_list)
np_weight_D_list = rng.normal(weight_D,sigma,n)
print_mean_std('普通に量った場合 コインD',np_weight_D_list)
普通に量った場合 コインA mean=10.00 std=1.00 var=1.01
普通に量った場合 コインB mean=11.00 std=0.99 var=0.97
普通に量った場合 コインC mean=12.01 std=1.00 var=1.00
普通に量った場合 コインD mean=13.00 std=1.00 var=0.99

測定誤差は、天秤の測定誤差(分散$ σ^2 $)そのままの1となります。

2枚の和と差の、和と差を量った場合

np_weight_X  = rng.normal(weitgt_A+weight_B+weitgt_C+weight_D,sigma,n)
print_mean_std('X',np_weight_X)
np_weight_Y  = rng.normal(weitgt_A+weight_B-weitgt_C-weight_D,sigma,n)
print_mean_std('Y',np_weight_Y)
np_weight_Z  = rng.normal(weitgt_A-weight_B+weitgt_C-weight_D,sigma,n)
print_mean_std('Z',np_weight_Z)
np_weight_W  = rng.normal(weitgt_A-weight_B-weitgt_C+weight_D,sigma,n)
print_mean_std('W',np_weight_W)
X mean=46.01 std=0.99 var=0.98
Y mean=-4.00 std=1.00 var=1.00
Z mean=-1.99 std=1.00 var=1.00
W mean=-0.02 std=1.00 var=1.00

測定誤差は、2枚の和と差の、和と差でも、天秤の測定誤差(分散$ σ^2 $)そのままの1となります。

2枚の和と差の、和と差から、それぞれ1枚の重さを計算

コイン1枚の測定誤差を求めると、

np_weight_A_list_4 = ( np_weight_X + np_weight_Y + np_weight_Z + np_weight_W ) / 4
print_mean_std('2枚の和と差の、和と差から求めた場合 コインA',np_weight_A_list_4)
np_weight_B_list_4 = ( np_weight_X + np_weight_Y - np_weight_Z - np_weight_W ) / 4
print_mean_std('2枚の和と差の、和と差から求めた場合 コインB',np_weight_B_list_4)
np_weight_C_list_4 = ( np_weight_X - np_weight_Y + np_weight_Z - np_weight_W ) / 4
print_mean_std('2枚の和と差の、和と差から求めた場合 コインC',np_weight_C_list_4)
np_weight_D_list_4 = ( np_weight_X - np_weight_Y - np_weight_Z + np_weight_W ) / 4
print_mean_std('2枚の和と差の、和と差から求めた場合 コインD',np_weight_D_list_4)
2枚の和と差の、和と差から求めた場合 コインA mean=10.00 std=0.50 var=0.25
2枚の和と差の、和と差から求めた場合 コインB mean=11.01 std=0.50 var=0.25
2枚の和と差の、和と差から求めた場合 コインC mean=12.01 std=0.50 var=0.25
2枚の和と差の、和と差から求めた場合 コインD mean=13.00 std=0.50 var=0.25

理論値の通り、測定誤差(分散)が、1枚ずつ測定するときの、1/4になりました。

感想

連立方程式を解くのが面倒なので、これ以上は計算しませんが、おそらく、2のN乗のコインの重さを量るときに、測定誤差を低減できるものと思います。(実際はやらないと思いますが、スゴイ技ですね。)

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2