用Python实战理解期望、方差与协方差:告别数学公式恐惧

很多数据分析师和机器学习工程师在面试时会被问到概率论的基础概念,比如"解释一下协方差的含义",结果往往支支吾吾地说"就是两个变量的相关性..."。这种模糊的理解在实际工作中远远不够——当你需要评估两个金融产品的风险关联度,或者分析用户行为特征间的依赖关系时,仅凭直觉是远远不够的。

1. 从数学公式到Python代码的思维转换

传统概率论教学最大的问题是过度依赖数学符号而缺乏直观感受。让我们用Python构建一个虚拟班级的成绩数据集,通过代码来感受这些统计量的实际意义。

首先创建一个包含50名学生、3门课程成绩的DataFrame:

import numpy as np
import pandas as pd

np.random.seed(42)
students = pd.DataFrame({
    'Math': np.random.normal(loc=75, scale=10, size=50),
    'Physics': np.random.normal(loc=70, scale=8, size=50),
    'Literature': np.random.normal(loc=80, scale=5, size=50)
})

1.1 期望:数据分布的中心点

期望值(E)在概率论中代表随机变量取值的"中心位置"。在Python中,我们直接用mean()方法计算:

math_mean = students['Math'].mean()
physics_mean = students['Physics'].mean()
print(f"数学平均分: {math_mean:.2f}, 物理平均分: {physics_mean:.2f}")

输出结果可能显示数学约75分,物理约70分。这意味着如果随机抽取一个学生,他的数学成绩更可能接近75分。

可视化理解期望值

import matplotlib.pyplot as plt

plt.hist(students['Math'], bins=15, alpha=0.7)
plt.axvline(math_mean, color='red', linestyle='--')
plt.title('数学成绩分布与期望值')
plt.show()

红线位置就是期望值,它位于分布的中心区域。

2. 方差与标准差:数据离散程度的度量

2.1 方差的计算与解读

方差(D)衡量数据点与期望值的偏离程度。计算数学成绩的方差:

math_var = students['Math'].var(ddof=0)  # 总体方差
print(f"数学成绩方差: {math_var:.2f}")

方差值越大,说明学生成绩差异越大。但方差的单位是原始数据的平方,不够直观,因此常用标准差:

math_std = students['Math'].std(ddof=0)
print(f"数学成绩标准差: {math_std:.2f}")

2.2 不同学科离散程度对比

比较三个学科的标准差:

学科 期望值 标准差
数学 75.12 9.87
物理 70.24 7.92
文学 79.85 4.91

从表格可见,文学课成绩最集中,数学成绩差异最大。这提示教师可能需要调整数学课的教学策略。

3. 协方差与相关性:变量关系的度量

3.1 协方差的计算

协方差衡量两个变量的共同变化趋势。计算数学与物理成绩的协方差:

cov_math_physics = students[['Math', 'Physics']].cov().iloc[0,1]
print(f"数学与物理成绩协方差: {cov_math_physics:.2f}")

正值表示两科成绩倾向于同向变化,负值则表示反向变化。

3.2 相关系数更直观

协方差的值受变量尺度影响,相关系数(ρ)将其标准化到[-1,1]区间:

corr = students['Math'].corr(students['Physics'])
print(f"数学与物理成绩相关系数: {corr:.2f}")

相关系数解读指南:

  • 0.8-1.0:极强相关
  • 0.6-0.8:强相关
  • 0.4-0.6:中等相关
  • 0.2-0.4:弱相关
  • 0.0-0.2:极弱相关或无相关

3.3 可视化变量关系

绘制散点图观察两科成绩的关系:

plt.scatter(students['Math'], students['Physics'])
plt.xlabel('Math Scores')
plt.ylabel('Physics Scores')
plt.title('数学与物理成绩关系')
plt.show()

如果点呈右上趋势,说明正相关;如果呈右下趋势,则是负相关。

4. 实际应用案例:股票投资组合分析

4.1 模拟两只股票收益率

创建两只相关股票的日收益率数据:

days = 252
np.random.seed(42)

# 股票A:年化收益10%,波动率20%
returns_A = np.random.normal(loc=0.10/252, scale=0.20/np.sqrt(252), size=days)

# 股票B与A有0.7的相关性
returns_B = 0.7*returns_A + np.random.normal(loc=0.08/252, scale=0.15/np.sqrt(252), size=days)

stocks = pd.DataFrame({'StockA': returns_A, 'StockB': returns_B})

4.2 计算关键统计量

print("期望收益率:")
print(stocks.mean() * 252)

print("\n年化波动率:")
print(stocks.std() * np.sqrt(252))

print("\n收益率协方差矩阵:")
print(stocks.cov() * 252)

print("\n收益率相关系数:")
print(stocks.corr())

4.3 投资组合风险分析

假设投资组合包含50%的A和50%的B:

weights = np.array([0.5, 0.5])
port_return = np.dot(weights, stocks.mean()) * 252
port_volatility = np.sqrt(np.dot(weights.T, np.dot(stocks.cov()*252, weights)))

print(f"组合预期年化收益: {port_return:.2%}")
print(f"组合年化波动率: {port_volatility:.2%}")

通过调整weights数组,可以找到最优风险收益比的投资比例。

5. 高级应用:特征工程中的统计量

在机器学习特征工程中,这些统计量有广泛应用:

5.1 特征选择

计算各特征与目标变量的相关系数,筛选重要特征:

# 假设target是我们要预测的变量
data = pd.concat([students, pd.Series(np.random.randint(0,2,50), name='target')], axis=1)

corr_with_target = data.corr()['target'].abs().sort_values(ascending=False)
print("特征与目标变量的相关性排序:")
print(corr_with_target[1:])  # 排除target自身

5.2 特征缩放

不同尺度的特征需要标准化:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaled_features = scaler.fit_transform(students)

标准化后各特征均值为0,方差为1,便于模型训练。

5.3 异常值检测

利用标准差识别异常值:

math_scores = students['Math']
outliers = math_scores[(math_scores - math_mean).abs() > 2*math_std]
print(f"数学成绩异常值: {outliers.values}")

在实际项目中,我发现当特征间的相关系数超过0.9时,通常只需要保留其中一个特征,既能减少维度又能避免多重共线性问题。

更多推荐