别再死记硬背了!用Python(NumPy/SciPy)可视化理解离散与连续概率分布
·
用Python玩转概率分布:从公式恐惧到图形直觉
概率论是数据科学的基石,但很多初学者在面对"概率密度函数"、"累积分布"这些抽象概念时,常常陷入公式记忆的困境。本文将通过Python的NumPy和Matplotlib,带你用代码和可视化手段重新认识概率分布,让数学直觉从屏幕上自然生长出来。
1. 环境准备与基础概念
在开始之前,确保你的Python环境已安装以下库:
pip install numpy matplotlib scipy
概率分布分为离散型和连续型两大类:
- 离散型 :取值可列举(如掷骰子的结果)
- 连续型 :取值充满一个区间(如人的身高)
它们的核心区别在于:
- 离散型用**概率质量函数(PMF)**描述
- 连续型用**概率密度函数(PDF)**描述
关键理解:概率密度不是概率,它的积分才是。就像线密度不是质量,需要乘以长度才能得到质量。
2. 离散型分布可视化实战
让我们从最简单的伯努利分布开始。假设有一个不公平硬币,正面朝上的概率为0.7:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import bernoulli
p = 0.7
x = [0, 1]
pmf = bernoulli.pmf(x, p)
plt.stem(x, pmf, use_line_collection=True)
plt.title('Bernoulli Distribution PMF (p=0.7)')
plt.xlabel('Outcome')
plt.ylabel('Probability')
plt.xticks(x, ['Tails', 'Heads'])
plt.show()
进阶到二项分布——n次独立伯努利试验的成功次数分布:
from scipy.stats import binom
n, p = 10, 0.4
x = np.arange(0, n+1)
pmf = binom.pmf(x, n, p)
plt.bar(x, pmf)
plt.title(f'Binomial Distribution PMF (n={n}, p={p})')
plt.xlabel('Number of successes')
plt.ylabel('Probability')
plt.show()
离散型分布的三个关键特征 :
- 每个点有明确的概率值
- 所有点概率之和为1
- CDF是右连续的阶梯函数
3. 连续型分布可视化解析
正态分布是最著名的连续型分布。让我们绘制它的PDF和CDF:
from scipy.stats import norm
mu, sigma = 0, 1
x = np.linspace(-4, 4, 1000)
pdf = norm.pdf(x, mu, sigma)
cdf = norm.cdf(x, mu, sigma)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
ax1.plot(x, pdf)
ax1.set_title('Normal Distribution PDF')
ax2.plot(x, cdf)
ax2.set_title('Normal Distribution CDF')
plt.show()
连续型分布的核心特性 :
- PDF曲线下的总面积等于1
- CDF是PDF的积分,单调递增
- 单点概率为0,只有区间概率有意义
4. 概率分布的变换与可视化技巧
4.1 随机变量变换
当Y=g(X)时,如何求Y的分布?对于单调函数,我们可以使用变量替换法:
from scipy.stats import uniform
# 原始X分布:均匀分布
X = uniform(loc=0, scale=1)
x = np.linspace(0, 1, 1000)
pdf_x = X.pdf(x)
# Y = -log(X)变换
y = -np.log(x)
pdf_y = pdf_x / np.abs(-1/x) # 变量替换公式
plt.figure(figsize=(10, 4))
plt.subplot(121)
plt.plot(x, pdf_x)
plt.title('Original X ~ Uniform(0,1)')
plt.subplot(122)
plt.plot(y, pdf_y)
plt.title('Transformed Y = -log(X)')
plt.tight_layout()
plt.show()
4.2 多维分布可视化
对于二维正态分布,我们可以用等高线和3D图来展示:
from scipy.stats import multivariate_normal
from mpl_toolkits.mplot3d import Axes3D
mu = [0, 0]
cov = [[1, 0.5], [0.5, 1]]
x, y = np.mgrid[-3:3:.1, -3:3:.1]
pos = np.dstack((x, y))
rv = multivariate_normal(mu, cov)
fig = plt.figure(figsize=(12, 5))
ax1 = fig.add_subplot(121)
ax1.contourf(x, y, rv.pdf(pos))
ax1.set_title('2D Contour Plot')
ax2 = fig.add_subplot(122, projection='3d')
ax2.plot_surface(x, y, rv.pdf(pos), cmap='viridis')
ax2.set_title('3D Surface Plot')
plt.show()
5. 实际应用案例:假设检验可视化
让我们用可视化方法理解p值的概念。假设我们有一组数据,想检验其均值是否为0:
np.random.seed(42)
data = np.random.normal(loc=0.5, scale=1, size=30)
t_stat, p_value = ttest_1samp(data, 0)
# 可视化
null_dist = t(df=len(data)-1)
x = np.linspace(-4, 4, 1000)
plt.plot(x, null_dist.pdf(x))
plt.axvline(t_stat, color='r', linestyle='--')
plt.fill_between(x[x>=abs(t_stat)], null_dist.pdf(x[x>=abs(t_stat)]), color='red', alpha=0.3)
plt.fill_between(x[x<=-abs(t_stat)], null_dist.pdf(x[x<=-abs(t_stat)]), color='red', alpha=0.3)
plt.title(f't-distribution with p-value={p_value:.3f}')
plt.xlabel('t-statistic')
plt.ylabel('Density')
plt.show()
假设检验可视化的关键点 :
- 绘制零假设下的理论分布
- 标记样本统计量的位置
- 着色表示更极端的区域(p值)
6. 交互式可视化进阶
静态图有时难以展示概率分布的动态特性。我们可以使用IPython的交互功能:
from ipywidgets import interact
def plot_normal(mean=0, std=1):
x = np.linspace(-10, 10, 1000)
pdf = norm.pdf(x, mean, std)
plt.plot(x, pdf)
plt.ylim(0, 0.5)
plt.title(f'N(μ={mean}, σ={std})')
plt.show()
interact(plot_normal, mean=(-5, 5), std=(0.1, 2.0))
这种交互式探索特别适合:
- 理解参数变化对分布形态的影响
- 演示中心极限定理
- 比较不同分布之间的差异
7. 从可视化到蒙特卡洛模拟
可视化不仅能帮助我们理解,还能引导出强大的计算方法。比如计算复杂积分:
def f(x):
return np.exp(-x**2) * np.sin(x)**2
x = np.linspace(-3, 3, 1000)
plt.plot(x, f(x), label='Integrand')
plt.fill_between(x, f(x), alpha=0.2)
plt.plot(x, norm.pdf(x), label='Normal PDF')
plt.legend()
# 蒙特卡洛积分
samples = np.random.normal(size=10000)
integral = np.mean(f(samples) / norm.pdf(samples))
print(f'Monte Carlo estimate: {integral:.4f}')
蒙特卡洛方法的三步可视化 :
- 绘制被积函数和目标分布
- 生成目标分布的随机样本
- 计算样本点的加权平均
更多推荐



所有评论(0)