背景
統計検定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乗のコインの重さを量るときに、測定誤差を低減できるものと思います。(実際はやらないと思いますが、スゴイ技ですね。)