第1回の練習問題の解答例¶

問題19¶

実際のテストの得点(S)は、真の能力が表されている点数(T)と測定における誤差(E)から構成するという以下のような考え方があります。

$$S = T + E$$

測定における誤差(E)は、測定誤差(Standard Error of Measurement: SEM)という統計量を指標として用いて表現します。測定誤差(SEM)は以下の式で求められます。

$$SEM = \sigma \sqrt{1-r}$$

ここで、$\sigma$はテストの分散 標準偏差、$r$はテストの信頼性係数です。SEMは信頼区間(Confidence Interval: CI)という考え方に基づいて以下のように用います。

  • 68%CI = Score ± SEM
  • 95%CI = Score ± 1.96 * SEM

測定誤差の信頼区間が95%の場合、100回テストを行なった場合、95回はその信頼区間内にスコアが入ると考えます。たとえば、測定誤差が3.5のテストで50点をとった受験者が同じテストを100回受験した場合、95回は43.1と56.9(50 ±1.96 × 3.5)の間のスコアをとるというように解釈します。

問題18で読み込んだデータのTEST_Aの測定誤差を計算し、このテストで100点を取った場合の98%信頼区間を出力しなさい。TEST_Aの信頼性係数は0.8とします。

In [1]:
# 問題19の解答欄
import pandas as pd
import numpy as np

df = pd.read_csv("../test01/test01_03.csv",index_col=0)

sigma = df["TEST_A"].std()

SEM = sigma * np.sqrt(1 - 0.8)

z = 2.23

upper = 100 + z * SEM
lower = 100 - z * SEM

print(lower,upper)
78.6278139284378 121.3721860715622

練習問題¶

  • ../DATA01/IEDA2_02.csvを読み込み、TEST_AとTEST_Bの散布図を描きましょう。
  • ここまで授業で扱った3つの方法を用いて、TEST_AからTEST_Bを予測する回帰式を求めましょう。
  • TEST_AはTEST_Bの事前テスト(模試)だとします。TEST_Bの合格点が180点だとすると、TEST_Aで何点とっていれば、TEST_Bで合格すると言えるでしょう。
  • Pandasで読み込んだデータをリストにするにはX = list(data["TEST_A"])のように書きます。
In [2]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
In [3]:
# データの読み込み
data = pd.read_csv("../DATA01/IEDA2_02.csv",index_col = 0)

# 散布図の描画
data.plot(kind = "scatter",x="TEST_A",y="TEST_B")
Out[3]:
<Axes: xlabel='TEST_A', ylabel='TEST_B'>
No description has been provided for this image

回帰式の求め方(その1)

  • この方法の場合、傾きと切片がおおよそどれぐらいなのか見当をつけなければならない。
In [4]:
X = data["TEST_A"].values
Y = data["TEST_B"].values

x = np.arange(70,250,0.1) 

a = 0.5
b = 90
y = a*x + b

plt.scatter(x=data["TEST_A"],y=data["TEST_B"])
plt.plot(x,y,color="red")
Out[4]:
[<matplotlib.lines.Line2D at 0x10924b3d0>]
No description has been provided for this image
In [5]:
# 傾き(a)の候補として0.1から1未満0.1ずつ変化させたリストを作成
A = np.arange(0.1,1,0.1)
# 切片(b)の候補として1から90未満まで1ずつ変化させたリストを作成
B = np.arange(1,90,1)

# 傾きの候補が0.10のとき、切片の候補が1から100未満まで、
# 傾きの候補が0.11のとき、切片の候補が1から100未満まで、
# のように全通りのリストDを作成
D = []

for a in A:
    for b in B:
        D.append([a,b])

# 傾きが0.1で切片が1、傾きが0.1で切片が2のように
# 全通りの誤差(実際の値と予測値の差)を計算したリストEを作成
E = []

for a,b in D:
    diff = 0
    for x,y in zip(X,Y):
        d = (y - (a*x+b))**2
        diff += d
    E.append(diff)
In [6]:
# Eの最小値を算出
np.min(E)
Out[6]:
np.float64(143885.0)
In [7]:
# Eの最小値の要素番号を取得
E.index(np.min(E))
Out[7]:
440
In [8]:
# 誤差が最小となる傾きと切片の組み合わせ
D[440]
Out[8]:
[np.float64(0.5), np.int64(85)]

回帰式の求め方(その2)

$$ a = \frac{Cov(x,y)}{\sigma_x^2} $$

$$ b = \mu_y - a\mu_x $$

  • $ Cov(x,y) $ : xとyの共分散
  • $ \sigma_x^2 $ : xの分散
  • $ \mu_y $ : yの平均
  • $ \mu_x $ : xの平均
In [9]:
mu_x = np.average(X)
s2_x = np.var(X,ddof=1)
mu_y = np.average(Y)
cov_xy = np.cov(X,Y)[0][1]
a = cov_xy / s2_x
b = mu_y - a * mu_x
print(a,b)
0.48492450764523504 87.14887255082185

回帰式の求め方(その3)

In [10]:
a,b = np.polyfit(X,Y,1)
print(a,b)
0.4849245076452346 87.14887255082185

TEST_Bの合格点が180点だった場合、TEST_Aで何点取っていれば良いか。

$$ \hat y = 0.48x + 87.14$$

なので、$x$に値を入れて$\hat y$が180をこえる$x$を探す。

In [11]:
X = np.arange(75,250,1)

for i in X:
    y_hat = 0.48 * i + 87.14
    if y_hat > 180:
        print(i)
        break
194

練習問題 その2¶

../DATA01/IEDA2_03.csvを読み込んで、

  1. pretestの点数をX軸、posttestの点数をY軸とした散布図を描きなさい。
  2. 以下の式を用いて、平均への回帰を考慮しても点数が上がった受験者の数を求めなさい。 $$ Score = \mu_2 + r_{12}(\frac{\sigma_2}{\sigma_1})(X-\mu_1) $$
  3. 以下の式を用いてSEDを求め、SEDを用いた場合に点数が上がったと判断できる受験者の数を求めなさい。pretest、posttestともに信頼性係数は0.8とする。 $$ SED = \sigma_A \sqrt{2 - r_A - r_B} $$
In [12]:
# データの読み込みと確認
import pandas as pd

data = pd.read_csv("../DATA01/IEDA2_03.csv",index_col=0)
data.head()
Out[12]:
pretest posttest
S001 510 585
S002 722 800
S003 513 607
S004 730 800
S005 483 445
In [13]:
# 散布図
data.plot(kind="scatter",x="pretest",y="posttest")
Out[13]:
<Axes: xlabel='pretest', ylabel='posttest'>
No description has been provided for this image
  1. 以下の式を用いて、平均への回帰を考慮しても点数が上がった受験者の数を求めなさい。 $$ Score = \mu_2 + r_{12}(\frac{\sigma_2}{\sigma_1})(X-\mu_1) $$
In [14]:
# 必要な統計量を求める
mu_2 = data["posttest"].mean()
r_12 = data.corr()["pretest"][1]
sigma_1 = data["pretest"].std()
sigma_2 = data["posttest"].std()
mu_1 = data["pretest"].mean()
/var/folders/nz/_yfjsvk16fbcf6x8w1wcsf1w0000gn/T/ipykernel_17008/3702593153.py:3: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  r_12 = data.corr()["pretest"][1]
In [15]:
# 表計算
data["expected"] = mu_2 + r_12*(sigma_2/sigma_1)*(data["pretest"] - mu_1)
In [16]:
# データの確認
data.head()
Out[16]:
pretest posttest expected
S001 510 585 569.237508
S002 722 800 796.900825
S003 513 607 572.459159
S004 730 800 805.491893
S005 483 445 540.242652
In [17]:
# 差の計算
data["diff_1"] = data["posttest"] - data["expected"]
In [18]:
# データの確認
data.head()
Out[18]:
pretest posttest expected diff_1
S001 510 585 569.237508 15.762492
S002 722 800 796.900825 3.099175
S003 513 607 572.459159 34.540841
S004 730 800 805.491893 -5.491893
S005 483 445 540.242652 -95.242652
In [19]:
# 上がった人数の確認
len(data[data["diff_1"] > 0])
Out[19]:
108
  1. 以下の式を用いてSEDを求め、SEDを用いた場合に点数が上がったと判断できる受験者の数を求めなさい。pretest、posttestともに信頼性係数は0.8とする。 $$ SED = \sigma_A \sqrt{2 - r_A - r_B} $$
In [20]:
# SEDの計算
SED = data["pretest"].std() * np.sqrt(2 - 0.8 - 0.8)

# SEDを考慮したスコアの計算
data["diff_2"] = data["posttest"] - (data["pretest"] + SED)
data.head()
Out[20]:
pretest posttest expected diff_1 diff_2
S001 510 585 569.237508 15.762492 18.234132
S002 722 800 796.900825 3.099175 21.234132
S003 513 607 572.459159 34.540841 37.234132
S004 730 800 805.491893 -5.491893 13.234132
S005 483 445 540.242652 -95.242652 -94.765868
In [21]:
# 上がった人数の確認
len(data[data["diff_2"] > 0])
Out[21]:
118