Data Science for Beginners 统计与概率入门:从随机变量到假设检验的 Python 实战指南
【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners
统计学与概率论是数据科学的两大数学基石。本指南以 Data-Science-For-Beginners 课程第 04 课(捷克语翻译版)为核心骨架,系统讲解概率、随机变量、概率分布、均值/方差/中位数等基础统计量,并以真实的美国职棒大联盟(MLB)球员数据集为实战案例,手把手演示如何用 NumPy、Pandas、SciPy 计算置信区间、执行 Student t 检验、验证中心极限定理并分析变量相关性。读完本文,你将掌握数据科学入门阶段最核心的统计工具与可复现的 Python 代码。
概率与随机变量:数据科学的出发点
概率(Probability)是介于 0 与 1 之间的数,用来衡量某个事件(Event)发生的可能性。在所有结果等可能的前提下,概率定义为"导致该事件的有利结果数 ÷ 结果总数"。例如掷一枚骰子,得到偶数(2、4、6)的概率为 3/6 = 0.5。
讨论事件时我们会使用随机变量(Random Variable)。例如,表示"掷骰子所得点数"的随机变量取值为 1 到 6,这个取值集合被称为样本空间(Sample Space)。我们可以讨论随机变量取某个特定值的概率,例如 P(X=3)=1/6。
随机变量分两类:
- 离散随机变量(Discrete):样本空间可数,存在能一一列举的独立取值。骰子点数就是典型例子。
- 连续随机变量(Continuous):样本空间是实数区间或整个实数集 ℝ。公交车的到达时间是一个经典例子——它可能落在任意一个时间点上。
概率分布:描述随机变量的行为
对于离散随机变量,可以借助函数 P(X) 描述每个事件的概率:对样本空间S中的每个值s,函数返回 0 到 1 之间的数,且所有事件 P(X=s) 之和为 1。
最著名的离散分布是均匀分布(Uniform Distribution):样本空间含 N 个元素,每个元素概率均为 1/N。
描述连续变量的概率分布则更复杂。考虑公交车到达时间:事实上,公交车恰好在某一精确时刻t到达的概率等于 0!
现在你知道了:概率为 0 的事件确实会发生,而且经常发生!至少每次公交车到站都是如此!
对于连续变量,我们只能讨论变量落在某个区间内的概率,例如 P(t₁≤X<t₂)。此时概率分布由概率密度函数(Probability Density Function)p(x) 描述:
P(t₁≤X<t₂) = ∫(t₁→t₂) p(x)dx
均匀分布的连续版本叫连续均匀分布,定义在有限区间上;X 落入长度为 l 的区间的概率与 l 成正比,最大趋近于 1。另一个重要的分布是正态分布(Normal Distribution),下文将详细展开。
均值、方差与标准差:刻画数据的中心与离散
假设我们抽取随机变量 X 的 n 个样本:x₁, x₂, ..., xₙ,可以用传统方式定义序列的均值(Mean)即算术平均值 (x₁+x₂+...+xₙ)/n。当样本量趋近无穷(n→∞)时,得到分布的均值,也叫期望(Expectation),记为E(x)。
可以证明:对取值为 {x₁, x₂, ..., xₙ}、对应概率为 p₁, p₂, ..., pₙ 的任意离散分布,期望等于 E(X)=x₁p₁+x₂p₂+...+xₙpₙ。
要衡量数值的散布程度,可以计算方差(Variance)σ² = Σ(xᵢ-μ)²/n,其中 μ 是序列均值。σ 被称为标准差(Standard Deviation),σ² 被称为方差。
在配套教学 notebook中,作者先用 Python 内置random模块从 0 到 10 均匀抽样 30 个值,再计算均值与方差:
import numpy as np import pandas as pd import random import matplotlib.pyplot as plt sample = [ random.randint(0,10) for _ in range(30) ] print(f"Sample: {sample}") print(f"Mean = {np.mean(sample)}") print(f"Variance = {np.var(sample)}")之后 notebook 加载真实的 MLB 球员数据,并依次计算身高(Height)的均值、方差与标准差:
df = pd.read_csv("../../data/SOCR_MLB.tsv", sep='\t', header=None, names=['Name','Team','Role','Weight','Height','Age']) mean = df['Height'].mean() var = df['Height'].var() std = df['Height'].std() print(f"Mean = {mean}\nVariance = {var}\nStandard Deviation = {std}")原始数据以制表符分隔,存放在仓库的 data/SOCR_MLB.tsv 中,共 1034 行记录,包含姓名、球队、场上位置(Role)、体重(Weight)、身高(Height)与年龄(Age)六个字段。
众数、中位数与四分位数:抵抗异常值的"典型值"
有时均值并不能很好代表数据的"典型值"。当数据中存在完全偏离区间的极端值时,均值会被严重影响。这时中位数(Median)是更好的指标:一半数据点低于它,另一半高于它。
为了更好理解数据分布,可以引入四分位数(Quartiles):
- 第一四分位数 Q1:25% 的数据低于它;
- 第三四分位数 Q3:75% 的数据低于它。
中位数与四分位数之间的关系可以用箱线图(Box Plot)直观呈现:
在此基础上还可以计算四分位距IQR=Q3-Q1,以及所谓的离群值(Outliers)——落在区间 [Q1-1.5×IQR, Q3+1.5×IQR] 之外的值。
对于只含少量可能取值的有限分布,"出现频率最高"的值就是好的典型值,称为众数(Mode)。它常用于颜色这类类别型数据。假设有两组人,一组强烈偏好红色、另一组偏好蓝色:若把颜色编码成数字,均值得出的"最受欢迎颜色"会落在橙绿之间,无法反映任何一组的真实偏好;而众数会直接给出红或蓝,若投票人数相等则同时给出两者(此时称样本为多模态(Multimodal))。
真实世界数据:MLB 球员体重与身高的统计分析
真实生活数据分析中,数据往往并非严格意义上的随机变量——我们并非在做结果未知的实验。例如一支棒球队队员的身高、体重、年龄这些数字并不完全随机,但我们仍可套用同样的数学概念:把一串体重值看成从某个随机变量中抽取的值序列。下面是取自 MLB 的真实球员体重序列(仅展示前 20 个值):
[180.0, 215.0, 210.0, 210.0, 188.0, 176.0, 209.0, 200.0, 231.0, 180.0, 188.0, 180.0, 185.0, 160.0, 180.0, 185.0, 197.0, 189.0, 185.0, 219.0]注意:与该数据集配套的完整操作示例见教学 notebook。本课还包含若干挑战任务,可通过在该 notebook 中添加代码完成。如果还不熟悉 Python 数据处理不必担心,课程稍后会专门讲解。
用箱线图可以直观展示数据的均值、中位数与四分位数:
由于数据包含不同球员位置(Role)的信息,还可以按位置绘制箱线图,从而观察参数取值在不同角色间的差异。这次以身高为例:
这张图提示:一垒手(First Baseman)的平均身高高于二垒手(Second Baseman)。在本课稍后我们会学习如何更正式地检验这一假设,以及如何证明数据在统计上显著地支持该结论。
处理真实世界数据时,我们假定所有数据点都是从某个概率分布中抽取的样本。这个假设使我们能够应用机器学习技术、构建可用的预测模型。
为观察数据分布形态,可以绘制直方图(Histogram):X 轴是若干体重区间(称为bin),Y 轴是随机变量样本落入对应区间的次数:
从直方图可以看出:所有值都集中在某个平均体重附近,离该体重越远,出现该体重值的频率越低。也就是说,棒球运动员体重大幅偏离平均值的可能性很低;体重方差衡量的是体重偏离均值的可能程度。
如果取的是非棒球联盟人群的体重,分布很可能不同。但分布的形状会保持一致,变化的只是均值和方差。因此,用棒球运动员训练出的模型,套用到大学生身上时很可能给出错误结果——因为底层分布不同。
正态分布:真实世界的钟形曲线
上面观察到的体重分布非常典型,现实世界中许多测量值遵循同一种分布形态,只是均值和方差不同。这种分布被称为正态分布(Normal Distribution),在统计学中扮演着极其重要的角色。
利用正态分布生成潜在棒球运动员的随机体重,是正确的方式。只要知道平均体重mean和标准差std,就能生成 1000 个体重样本:
samples = np.random.normal(mean,std,1000)如果绘制生成样本的直方图,会得到与上面非常相似的图形。增加样本数和 bin 数后,可以得到更接近理想形态的正态分布图:
均值=0、标准差=1 的标准正态分布
配套 notebook 中还特别演示了为什么不能用均匀分布生成体重数据:wrong_sample = np.random.rand(1000)*2*std+mean-std得到的直方图与真实体重分布形态完全不同——这提醒我们,现实世界大多数测量值服从正态分布,而不是均匀分布。
置信区间:用样本估计总体均值
讨论棒球运动员体重时,我们假设存在某个随机变量 W,对应全体棒球运动员体重的理想概率分布(即总体 Population)。我们的体重序列对应全体球员的一个子集,称为样本(Sample)。一个有趣的问题是:能否知道 W 分布的参数,即总体的均值与方差?
最简单的答案就是直接计算样本的均值与方差。但随机样本未必能精确代表整个总体,因此讨论置信区间(Confidence Interval)是有意义的。
置信区间:基于样本对总体真实均值给出的估计,该估计以一定概率(置信水平)准确。
假设从分布中抽取样本 X₁, ..., Xₙ。每次抽样得到的均值 μ 都不同,因此 μ 可被视为一个随机变量。置信水平为 p 的置信区间是一对值 (Lₚ, Rₚ),满足P(Lₚ≤μ≤Rₚ) = p,即测得均值落入该区间的概率等于 p。
详细计算置信区间的方法超出入门范围,简要来说:我们定义"样本均值相对总体真实均值"的分布,称为Student 分布(t 分布)。
趣闻:Student 分布以数学家 William Sealy Gosset 命名,他以笔名 "Student" 发表论文。他曾在健力士啤酒厂工作,据说雇主不希望公众知道他们用统计检验来判断原材料品质。
若要以置信度 p 估计总体均值 μ,需要取 Student 分布的(1-p)/2分位数 A——可以从数值表中查得,也可用统计软件(如 Python、R)内置函数计算。此时 μ 的区间为 X±A×D/√n,其中 X 是样本均值,D 是标准差。
注:此处略去了与 Student 分布密切相关的重要概念自由度(Degrees of Freedom),想深入理解可参阅更完整的统计学书籍。
配套 notebook 给出了权重与身高的置信区间计算示例。核心代码如下(来自教学 notebook):
import scipy.stats def mean_confidence_interval(data, confidence=0.95): a = 1.0 * np.array(data) n = len(a) m, se = np.mean(a), scipy.stats.sem(a) # 样本均值与标准误 h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1) # t 分布临界值 return m, h for p in [0.85, 0.9, 0.95]: m, h = mean_confidence_interval(df['Weight'].ffill(),p) print(f"p={p:.2f}, mean = {m:.2f} ± {h:.2f}")以体重为例,不同置信水平对应的区间如下:
| p | 体重均值 |
|---|---|
| 0.85 | 201.73±0.94 |
| 0.90 | 201.73±1.08 |
| 0.95 | 201.73±1.28 |
注意:置信概率越高,置信区间越宽。
假设检验:用 t 检验证明"一垒手更高"
MLB 球员数据集中包含多种场上位置,可以汇总如下(如何计算该表参见教学 notebook,其核心是df.groupby('Role').agg({...})):
| 位置 | 身高 | 体重 | 人数 |
|---|---|---|---|
| Catcher | 72.723684 | 204.328947 | 76 |
| Designated_Hitter | 74.222222 | 220.888889 | 18 |
| First_Baseman | 74.000000 | 213.109091 | 55 |
| Outfielder | 73.010309 | 199.113402 | 194 |
| Relief_Pitcher | 74.374603 | 203.517460 | 315 |
| Second_Baseman | 71.362069 | 184.344828 | 58 |
| Shortstop | 71.903846 | 182.923077 | 52 |
| Starting_Pitcher | 74.719457 | 205.163636 | 221 |
| Third_Baseman | 73.044444 | 200.955556 | 45 |
可以注意到一垒手的平均身高高于二垒手,因此我们可能得出结论:一垒手比二垒手高。
这个陈述被称为假设(Hypothesis),因为我们并不知道该事实是否真的成立。
然而,能否下此结论并不总是显而易见。由上文可知每个均值都关联一个置信区间,因此这个差异可能只是统计误差。我们需要更正式的方法来检验假设。
先分别计算一垒手与二垒手身高的置信区间:
| 置信水平 | 一垒手 | 二垒手 |
|---|---|---|
| 0.85 | 73.62..74.38 | 71.04..71.69 |
| 0.90 | 73.56..74.44 | 70.99..71.73 |
| 0.95 | 73.47..74.53 | 70.92..71.81 |
可以看到,在任何置信水平下两个区间都不重叠。这支持了"一垒手比二垒手高"的假设。
更形式化地说,我们真正要解决的问题是判断两个概率分布是否相同,或至少参数相同。根据分布类型需选用不同检验;若已知分布为正态,可用[Student t 检验]。
在 Student t 检验中,计算t 值(t-value),它衡量考虑方差后的均值差。已证明 t 值服从Student 分布,据此可得到给定置信水平p的阈值(可计算或查数值表),然后比较 t 值与阈值以接受或拒绝假设。
在 Python 中可以使用SciPy包,它包含ttest_ind函数(此外还有大量有用的统计函数)。该函数为我们计算 t 值,并反向查表给出置信度对应的 p 值,因此只需观察 p 值即可得出结论。
例如,一垒手与二垒手身高的比较得到如下结果:
from scipy.stats import ttest_ind tval, pval = ttest_ind(df.loc[df['Role']=='First_Baseman',['Height']], df.loc[df['Role']=='Second_Baseman',['Height']],equal_var=False) print(f"T-value = {tval[0]:.2f}\nP-value: {pval[0]}")T-value = 7.65 P-value: 9.137321189738925e-12ttest_ind返回的两个值含义如下(见 notebook 说明):
- p 值可视为"两个分布均值相同"的概率。本例中 p 值极低,意味着有强证据支持一垒手更高;
- t 值是 t 检验中归一化均值差的中间量,需与给定置信水平下的阈值比较。
在我们的情形中 p 值非常低,说明存在强证据支持"一垒手更高"。此外,还可能想检验其他类型的假设,例如:
- 证明给定样本服从某个分布(本课假设身高服从正态分布,但这需要正式的统计验证);
- 证明样本均值等于某个预先定义的值;
- 比较多个样本的均值(例如不同年龄段人群的幸福水平差异)。
大数定律与中心极限定理:正态分布为何无处不在
正态分布如此重要的原因之一是中心极限定理(Central Limit Theorem)。假设我们从任意一个均值为 μ、方差为 σ² 的分布中独立抽取 N 个大样本 X₁, ..., Xₙ,那么当 N 足够大(即 N→∞)时,均值 ΣᵢXᵢ 服从正态分布,均值为 μ,方差为 σ²/N。
中心极限定理的另一种解读是:无论原分布是什么,当你计算任意随机变量取值之和的均值时,最终都会得到正态分布。
由中心极限定理还可推出:当 N→∞ 时,样本均值等于 μ 的概率趋近于 1,这就是大数定律(Law of Large Numbers)。
配套 notebook 用一个漂亮的实验验证了中心极限定理:Python 的伪随机生成器本应给出均匀分布,但我们只需取一组均匀生成样本的均值,就能造出一个正态分布生成器:
def normal_random(sample_size=100): sample = [random.uniform(0,1) for _ in range(sample_size) ] return sum(sample)/sample_size sample = [normal_random() for _ in range(100)] plt.figure(figsize=(10,6)) plt.hist(sample) plt.tight_layout() plt.show()从直方图可以直观看到,100 个均匀样本均值构成的分布已经呈现钟形——这就是中心极限定理的威力。
协方差与相关性:发现变量之间的关系
数据科学的一项重要工作就是发现数据间的联系。当两个序列在同一时刻表现出相似行为时(同时上升/下降,或一个上升另一个下降),我们说它们相关(Correlate)。换言之,两个序列之间似乎存在某种关系。
相关并不必然意味着两个序列之间存在因果关系;有时两个变量都依赖某个外部原因,或者相关性纯属巧合。但强数学相关性是"两个变量以某种方式关联"的良好指示。
数学上,衡量两个随机变量关系的主要概念是协方差(Covariance):Cov(X,Y) =E[(X-E(X))(Y-E(Y))]。我们计算两个变量相对各自均值的偏差,再求这些偏差的乘积:若两个变量同向偏离,乘积恒为正,累加得到正协方差;若反向偏离(一个低于均值而另一个高于均值),乘积恒为负,累加得到负协方差;若偏差相互独立,累加后大致为零。
协方差的绝对值并不能告诉我们相关性的强弱,因为它取决于实际数值的量级。为将其归一化,可以把协方差除以两个变量的标准差,得到相关系数(Correlation)。相关系数始终落在 [-1,1]:1 表示强正相关,-1 表示强负相关,0 表示完全不相关(变量独立)。
示例:计算上述数据集中棒球运动员体重与身高的相关性:
print(np.corrcoef(weights,heights))结果得到一个相关矩阵(Correlation Matrix):
array([[1. , 0.52959196], [0.52959196, 1. ]])相关矩阵 C 可对任意数量的输入序列 S₁, ..., Sₙ 计算:Cᵢⱼ 是 Sᵢ 与 Sⱼ 的相关系数,对角元素恒为 1(即 Sᵢ 的自相关)。
本例中 0.53 表明人的体重与身高存在一定相关性。也可以用散点图直观观察两者的关系:
更多协方差与相关性示例见教学 notebook。
notebook 中还有一个有趣的"邪恶棒球公司"玩具示例:假设公司按身高支付球员薪水(底薪 1000 美元加 0~100 美元的身高奖金),计算np.cov(heights, salaries)与np.corrcoef(heights, salaries)得到相关系数为 1(完全线性关系);随后把公式改成包含np.sin的非线性函数并混入随机噪声,相关系数随之下降——直观展示了相关性与线性关系的联系。此外,直接对含缺失值nan的序列调用np.corrcoef(df['Height'].ffill(), df['Weight'])会得到nan,这凸显了数据清洗(Data Preparation)的重要性:没有干净的数据,我们什么也算不出来。
小结与进阶作业
本节我们学习了:
- 数据的基本统计性质,如均值、方差、众数与四分位数;
- 随机变量的不同分布,包括正态分布;
- 如何寻找不同特征之间的相关性;
- 如何用严谨的数学与统计工具验证假设;
- 如何基于数据样本计算随机变量的置信区间。
这当然远非概率与统计领域的全部主题,但足以让你在本课程中有一个良好开端。
课程还提供了配套作业——小糖尿病研究(Malá studie o cukrovce)。作业使用 data/diabetes.tsv 中的 442 条糖尿病患者记录(字段包括 AGE、SEX、BMI、BP、S1~S6 六项血液指标,以及 Y——一年内病情进展的量化度量),要求在作业 notebook中完成:
- 计算所有变量的均值与方差;
- 按性别绘制 BMI、BP 与 Y 的箱线图;
- 分析 AGE、SEX、BMI、Y 的分布形态;
- 检验各变量与病情进展(Y)之间的相关性(提示:相关矩阵能给出哪些变量相互依赖的最有效信息);
- 检验"男女糖尿病进展程度不同"的假设。
参考作业解答可以看到完整的解题思路:用df.describe()与df.var()计算统计量;df.corr()得到的相关矩阵显示与 Y 相关性最强的是 BMI(0.586)和 S5(0.566,血糖指标),结论符合医学直觉;最后用ttest_ind检验男女 Y 值差异,得到 T-value = -0.90、P-value ≈ 0.367,p 值远大于常规显著性水平,说明没有足够证据支持男女糖尿病进展存在差异。评分标准强调:优秀完成需要所有任务完整、有图形佐证且结论解释充分,而仅完成均值/方差计算与基础绘图则只能算"需改进"。
【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考