原文: https://machinelearningmastery.com/how-to-code-the-students-t-test-from-scratch-in-python/
也许最广泛使用的统计假设检验之一是 T 检验。
因为有一天你可能会自己使用这个测试,所以深入了解测试的工作原理非常重要。作为开发人员,通过从零开始实现假设检验,可以最好地实现这种理解。
在本教程中,您将了解如何在 Python 中从零开始实现 Student's t 检验统计假设检验。
完成本教程后,您将了解:
- 学生的 t 检验将评论是否可能观察到两个样本,因为样本来自同一人群。
- 如何从零开始实现 T 检验两个独立样本。
- 如何从零开始对两个相关样本实现配对 T 检验。
让我们开始吧。
如何在 Python 中从零开始编写 T 检验 照片由 n1d ,保留一些权利。
本教程分为三个部分;他们是:
- 学生的 t-测试
- 学生对独立样本的 t 检验
- 学生对依赖样本的 t 检验
T 检验是一项统计假设检验,用于检验是否预期两个样本来自同一人群。
它以 William Gosset 使用的化名“Student
”命名,他开发了该测试。
测试通过检查来自两个样品的平均值来确定它们是否彼此显着不同。它通过计算均值之间差异的标准误差来做到这一点,如果两个样本具有相同的均值(零假设),可以解释为差异的可能性。
通过将其与来自 t 分布的临界值进行比较,可以解释通过测试计算的 t 统计量。可以使用自由度和百分点函数(PPF)的显着性水平来计算临界值。
我们可以在双尾检验中解释统计值,这意味着如果我们拒绝零假设,那可能是因为第一个均值小于或大于第二个均值。为此,我们可以计算检验统计量的绝对值,并将其与正(右尾)临界值进行比较,如下所示:
- 如果 abs(t-statistic)< =临界值:接受平均值相等的零假设。
- 如果 abs(t-statistic)>临界值:拒绝平均值相等的零假设。
我们还可以使用 t 分布的累积分布函数(CDF)来检索观察 t 统计量的绝对值的累积概率,以便计算 p 值。然后可以将 p 值与选择的显着性水平(α)(例如 0.05)进行比较,以确定是否可以拒绝原假设:
- 如果 p> alpha :接受平均值相等的零假设。
- 如果 p <= alpha :拒绝零假设,即平均值相等。
在处理样本的平均值时,测试假设两个样本都是从高斯分布中提取的。该测试还假设样本具有相同的方差和相同的大小,尽管如果这些假设不成立,则对测试进行校正。例如,参见 Welch 的 t 检验。
Student's t-test 有两个主要版本:
- 独立样本。两个样本不相关的情况。
- 相关样本。样本相关的情况,例如对同一群体的重复测量。也称为配对测试。
独立和依赖学生的 t 检验分别通过 ttest_ind()和 ttest_rel() SciPy 函数在 Python 中提供。
注意:我建议使用这些 SciPy 函数计算应用程序的 Student t 检验,如果它们合适的话。库实现将更快,更不容易出错。我只建议您出于学习目的自行实现测试,或者在需要修改测试版本的情况下。
我们将使用 SciPy 函数来确认我们自己的测试版本的结果。
请注意,作为参考,本教程中提供的所有计算都直接取自“ [t _T 测试 _”中的“ T Tests”,第三版,2010 年。我提到这一点是因为您可能会看到具有不同形式的方程式,具体取决于您使用的参考文本。
我们将从最常见的 T 检验形式开始:我们比较两个独立样本的平均值的情况。
两个独立样本的 t 统计量的计算如下:
t = observed difference between sample means / standard error of the difference between the means
要么
t = (mean(X1) - mean(X2)) / sed
其中X1
和X2
是第一和第二数据样本而sed
是平均值之差的标准误差。
平均值之间差异的标准误差可以计算如下:
sed = sqrt(se1^2 + se2^2)
其中se1
和se2
是第一和第二数据集的标准误差。
样本的标准误差可以计算为:
se = std / sqrt(n)
当se
是样品的标准误差时,std
是样品标准偏差,n
是样品中的观察数。
这些计算做出以下假设:
- 样本是从高斯分布中提取的。
- 每个样本的大小大致相等。
- 样本具有相同的方差。
我们可以使用 Python 标准库,NumPy 和 SciPy 中的函数轻松实现这些方程。
假设我们的两个数据样本存储在变量data1
和data2
中。
我们可以从计算这些样本的平均值开始,如下所示:
# calculate means
mean1, mean2 = mean(data1), mean(data2)
我们在那里一半。
现在我们需要计算标准误差。
我们可以手动完成,首先计算样本标准偏差:
# calculate sample standard deviations
std1, std2 = std(data1, ddof=1), std(data2, ddof=1)
然后是标准错误:
# calculate standard errors
n1, n2 = len(data1), len(data2)
se1, se2 = std1/sqrt(n1), std2/sqrt(n2)
或者,我们可以使用sem()
SciPy 函数直接计算标准误差。
# calculate standard errors
se1, se2 = sem(data1), sem(data2)
我们可以使用样本的标准误差来计算样本之间差异的“_ 标准误差”:_
# standard error on the difference between the samples
sed = sqrt(se1**2.0 + se2**2.0)
我们现在可以计算 t 统计量:
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
我们还可以计算一些其他值来帮助解释和呈现统计量。
测试的自由度数计算为两个样本中观察值的总和减去 2。
# degrees of freedom
df = n1 + n2 - 2
对于给定的显着性水平,可以使用百分点函数(PPF)计算临界值,例如 0.05(95%置信度)。
此功能可用于 SciPy 中的 t 分发,如下所示:
# calculate the critical value
alpha = 0.05
cv = t.ppf(1.0 - alpha, df)
可以使用 t 分布上的累积分布函数来计算 p 值,再次在 SciPy 中。
# calculate the p-value
p = (1 - t.cdf(abs(t_stat), df)) * 2
在这里,我们假设一个双尾分布,其中零假设的拒绝可以解释为第一个均值小于或大于第二个均值。
我们可以将所有这些部分组合成一个简单的函数来计算两个独立样本的 t 检验:
# function for calculating the t-test for two independent samples
def independent_ttest(data1, data2, alpha):
# calculate means
mean1, mean2 = mean(data1), mean(data2)
# calculate standard errors
se1, se2 = sem(data1), sem(data2)
# standard error on the difference between the samples
sed = sqrt(se1**2.0 + se2**2.0)
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
# degrees of freedom
df = len(data1) + len(data2) - 2
# calculate the critical value
cv = t.ppf(1.0 - alpha, df)
# calculate the p-value
p = (1.0 - t.cdf(abs(t_stat), df)) * 2.0
# return everything
return t_stat, df, cv, p
在本节中,我们将计算一些合成数据样本的 t 检验。
首先,让我们生成两个 100 高斯随机数的样本,其方差相同,分别为 50 和 51。我们期望测试拒绝原假设并找出样本之间的显着差异:
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
我们可以使用内置的 SciPy 函数 ttest_ind() 计算这些样本的 t 检验。这将为我们提供 t 统计值和要比较的 p 值,以确保我们正确地实现了测试。
下面列出了完整的示例。
# Student's t-test for independent samples
from numpy.random import seed
from numpy.random import randn
from scipy.stats import ttest_ind
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
# compare samples
stat, p = ttest_ind(data1, data2)
print('t=%.3f, p=%.3f' % (stat, p))
运行该示例,我们可以看到 t 统计值和 p 值。
我们将使用这些作为我们对这些数据进行测试的预期值。
t=-2.262, p=0.025
我们现在可以使用上一节中定义的函数对相同的数据应用我们自己的实现。
该函数将返回 t 统计值和临界值。我们可以使用临界值来解释 t 统计量,以查看测试的结果是否显着,并且确实手段与我们预期的不同。
# interpret via critical value
if abs(t_stat) <= cv:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
该函数还返回 p 值。我们可以使用α来解释 p 值,例如 0.05,以确定测试的结果是否显着,并且确实手段与我们预期的不同。
# interpret via p-value
if p > alpha:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
我们希望这两种解释始终匹配。
The complete example is listed below.
# t-test for independent samples
from math import sqrt
from numpy.random import seed
from numpy.random import randn
from numpy import mean
from scipy.stats import sem
from scipy.stats import t
# function for calculating the t-test for two independent samples
def independent_ttest(data1, data2, alpha):
# calculate means
mean1, mean2 = mean(data1), mean(data2)
# calculate standard errors
se1, se2 = sem(data1), sem(data2)
# standard error on the difference between the samples
sed = sqrt(se1**2.0 + se2**2.0)
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
# degrees of freedom
df = len(data1) + len(data2) - 2
# calculate the critical value
cv = t.ppf(1.0 - alpha, df)
# calculate the p-value
p = (1.0 - t.cdf(abs(t_stat), df)) * 2.0
# return everything
return t_stat, df, cv, p
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
# calculate the t test
alpha = 0.05
t_stat, df, cv, p = independent_ttest(data1, data2, alpha)
print('t=%.3f, df=%d, cv=%.3f, p=%.3f' % (t_stat, df, cv, p))
# interpret via critical value
if abs(t_stat) <= cv:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
# interpret via p-value
if p > alpha:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
首先运行该示例计算测试。
打印测试结果,包括 t 统计量,自由度,临界值和 p 值。
我们可以看到 t 统计量和 p 值都与 SciPy 函数的输出相匹配。测试似乎正确实现。
然后使用 t 统计量和 p 值来解释测试结果。我们发现,正如我们所期望的那样,有足够的证据可以拒绝零假设,发现样本均值可能不同。
t=-2.262, df=198, cv=1.653, p=0.025
Reject the null hypothesis that the means are equal.
Reject the null hypothesis that the means are equal.
我们现在可以看一下计算依赖样本的 T 检验的情况。
在这种情况下,我们收集来自种群的样本的一些观察结果,然后应用一些处理,然后从同一样本收集观察结果。
结果是两个相同大小的样本,其中每个样本中的观察结果是相关的或配对的。
依赖样本的 t 检验称为配对 T 检验。
配对 T 检验的计算与独立样本的情况类似。
主要区别在于分母的计算。
t = (mean(X1) - mean(X2)) / sed
WhereX1
andX2
are the first and second data samples andsed
is the standard error of the difference between the means.
这里,sed
计算如下:
sed = sd / sqrt(n)
其中sd
是依赖样本平均值与 _ 之间的差异的标准偏差 n_ 是配对观察的总数(例如每个样本的大小)。
sd
的计算首先需要计算样本之间的平方差之和:
d1 = sum (X1[i] - X2[i])^2 for i in n
它还需要样本之间(非平方)差异的总和:
d2 = sum (X1[i] - X2[i]) for i in n
然后我们可以将 sd 计算为:
sd = sqrt((d1 - (d2**2 / n)) / (n - 1))
而已。
我们可以直接在 Python 中实现配对 Student's t-test 的计算。
第一步是计算每个样本的平均值。
# calculate means
mean1, mean2 = mean(data1), mean(data2)
接下来,我们将需要对的数量(n
)。我们将在几个不同的计算中使用它。
# number of paired samples
n = len(data1)
接下来,我们必须计算样本之间的平方差的总和,以及总和差异。
# sum squared difference between observations
d1 = sum([(data1[i]-data2[i])**2 for i in range(n)])
# sum difference between observations
d2 = sum([data1[i]-data2[i] for i in range(n)])
我们现在可以计算平均值之差的标准差。
# standard deviation of the difference between means
sd = sqrt((d1 - (d2**2 / n)) / (n - 1))
然后用它来计算平均值之间差异的标准误差。
# standard error of the difference between the means
sed = sd / sqrt(n)
最后,我们拥有计算 t 统计量所需的一切。
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
此实现与独立样本实现之间唯一的其他关键区别是计算自由度的数量。
# degrees of freedom
df = n - 1
和以前一样,我们可以将所有这些结合在一起成为可重用的功能。该函数将采用两个配对样本和显着性水平(alpha)并计算 t 统计量,自由度数,临界值和 p 值。
完整的功能如下所列。
# function for calculating the t-test for two dependent samples
def dependent_ttest(data1, data2, alpha):
# calculate means
mean1, mean2 = mean(data1), mean(data2)
# number of paired samples
n = len(data1)
# sum squared difference between observations
d1 = sum([(data1[i]-data2[i])**2 for i in range(n)])
# sum difference between observations
d2 = sum([data1[i]-data2[i] for i in range(n)])
# standard deviation of the difference between means
sd = sqrt((d1 - (d2**2 / n)) / (n - 1))
# standard error of the difference between the means
sed = sd / sqrt(n)
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
# degrees of freedom
df = n - 1
# calculate the critical value
cv = t.ppf(1.0 - alpha, df)
# calculate the p-value
p = (1.0 - t.cdf(abs(t_stat), df)) * 2.0
# return everything
return t_stat, df, cv, p
在本节中,我们将在工作示例中使用与独立 Student's t 检验相同的数据集。
数据样本没有配对,但我们会假装它们。我们希望测试拒绝原假设并找出样本之间的显着差异。
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
和以前一样,我们可以使用 SciPy 函数评估测试问题,以计算配对 t 检验。在这种情况下, ttest_rel() 功能。
The complete example is listed below.
# Paired Student's t-test
from numpy.random import seed
from numpy.random import randn
from scipy.stats import ttest_rel
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
# compare samples
stat, p = ttest_rel(data1, data2)
print('Statistics=%.3f, p=%.3f' % (stat, p))
运行该示例计算并打印 t 统计量和 p 值。
我们将使用这些值来验证我们自己的配对 t 检验函数的计算。
Statistics=-2.372, p=0.020
我们现在可以测试我们自己的配对 T 检验的实现。
下面列出了完整的示例,包括已开发的函数和函数结果的解释。
# t-test for dependent samples
from math import sqrt
from numpy.random import seed
from numpy.random import randn
from numpy import mean
from scipy.stats import t
# function for calculating the t-test for two dependent samples
def dependent_ttest(data1, data2, alpha):
# calculate means
mean1, mean2 = mean(data1), mean(data2)
# number of paired samples
n = len(data1)
# sum squared difference between observations
d1 = sum([(data1[i]-data2[i])**2 for i in range(n)])
# sum difference between observations
d2 = sum([data1[i]-data2[i] for i in range(n)])
# standard deviation of the difference between means
sd = sqrt((d1 - (d2**2 / n)) / (n - 1))
# standard error of the difference between the means
sed = sd / sqrt(n)
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
# degrees of freedom
df = n - 1
# calculate the critical value
cv = t.ppf(1.0 - alpha, df)
# calculate the p-value
p = (1.0 - t.cdf(abs(t_stat), df)) * 2.0
# return everything
return t_stat, df, cv, p
# seed the random number generator
seed(1)
# generate two independent samples (pretend they are dependent)
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
# calculate the t test
alpha = 0.05
t_stat, df, cv, p = dependent_ttest(data1, data2, alpha)
print('t=%.3f, df=%d, cv=%.3f, p=%.3f' % (t_stat, df, cv, p))
# interpret via critical value
if abs(t_stat) <= cv:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
# interpret via p-value
if p > alpha:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
运行该示例计算样本问题的配对 t 检验。
计算出的 t 统计量和 p 值与我们对 SciPy 库实现的期望相匹配。这表明实现是正确的。
具有临界值的 t 检验统计量和具有显着性水平的 p 值的解释都发现了显着的结果,拒绝了平均值相等的零假设。
t=-2.372, df=99, cv=1.660, p=0.020
Reject the null hypothesis that the means are equal.
Reject the null hypothesis that the means are equal.
本节列出了一些扩展您可能希望探索的教程的想法。
- 将每个测试应用于您自己设计的样本问题。
- 更新独立测试并为具有不同方差和样本大小的样本添加校正。
- 对 SciPy 库中实现的其中一个测试执行代码审查,并总结实现细节的差异。
如果你探索任何这些扩展,我很想知道。
如果您希望深入了解,本节将提供有关该主题的更多资源。
- 普通英语统计,第三版,2010 年。
在本教程中,您了解了如何在 Python 中从零开始实现 Student's t 检验统计假设检验。
具体来说,你学到了:
- 学生的 t 检验将评论是否可能观察到两个样本,因为样本来自同一人群。
- 如何从零开始实现 T 检验两个独立样本。
- 如何从零开始对两个相关样本实现配对 T 检验。
你有任何问题吗? 在下面的评论中提出您的问题,我会尽力回答。