沐神《动手学深度学习》之2.6概率
一、基本概率论
注意!概率论只是深度学习的预备知识,我这里只对代码部分做出解释,想要进一步了解概率论,可以看书或者找视频。现在不看也行,等后面遇到了再补。
书上的掷骰子的例子,我们这里也用这个例子。只不过我对代码进行了修改,不用d2l包,而是直接使用matplotlib来绘制散点图。
首先设置环境变量:os.environ['KMP_DUPLICATE_LIB_OK'] = 'True',这是为了解决 OpenMP 库冲突引。
当PyTorch和另一个库(Matplotlib)都尝试初始化OpenMP时,可能会发生冲突。这段代码是为了告诉 OpenMP:"允许多个库初始化同一个 OpenMP 库,不要报错"
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
这段代码是用于配置 matplotlib 的字体设置,主要解决中文显示和负号显示的问题。
fair_probs = torch.ones([6]) / 6 #创建公平概率的骰子,每个概率都是1/6
print("公平骰子概率:", fair_probs)
现在我们已经创建了一个骰子,现在我们开始摇骰子。
Multinomial(total_count, probs)# total_count表示实验的次数,也就是掷骰子的次数,probs表示掷骰子的概率。
sample()#表示抽样,也就是做了多少次抽样,没有参数默认1次。
counts = multinomial.Multinomial(10, fair_probs).sample((500,))# 表示进行500组实验,每组10次掷骰,每个面的概率等于我们之前设置的1/6
# 计算累积和(沿着实验组数维度)
cum_counts = counts.cumsum(dim=0)
# 第n行 = 前n组实验的累计结果
# 例如: cum_counts[0] = 第1组结果
# cum_counts[1] = 第1+2组结果
# cum_counts[49] = 前50组结果
# 计算累计的相对频率
estimates = cum_counts / cum_counts.sum(dim=1, keepdims=True)
# 每个概率 = 累计出现次数 / 总实验次数
以下是所有代码:
注意!我把书上的单次投掷和1000次也给写了上去,为了方便对比结果。
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True' # 必须放在最开头
import torch
from torch.distributions import multinomial
import matplotlib.pyplot as plt
import numpy as np
# 设置中文字体(可选)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 1. 创建公平骰子概率
fair_probs = torch.ones([6]) / 6
print("公平骰子概率:", fair_probs)
# 2. 模拟掷骰子
print("\n--- 单次掷骰子 ---")
one_roll = multinomial.Multinomial(1, fair_probs).sample()
print("结果:", one_roll)
print("掷出的是第", torch.argmax(one_roll).item() + 1, "面")
print("\n--- 10次掷骰子 ---")
ten_rolls = multinomial.Multinomial(10, fair_probs).sample()
print("结果:", ten_rolls)
print("频率:", ten_rolls / 10)
print("\n--- 1000次掷骰子 ---")
thousand_rolls = multinomial.Multinomial(1000, fair_probs).sample()
print("结果:", thousand_rolls)
print("频率:", thousand_rolls / 1000)
# 3. 大数定律演示
print("\n--- 大数定律演示 ---")
# 进行500组实验,每组10次掷骰
counts = multinomial.Multinomial(10, fair_probs).sample((500,))
print("实验数据形状:", counts.shape) # (500, 6)
# 计算累积结果
cum_counts = counts.cumsum(dim=0) # 沿实验组数维度累积
print("累积数据形状:", cum_counts.shape) # (500, 6)
# 计算累计概率估计
estimates = cum_counts / cum_counts.sum(dim=1, keepdims=True)
print("概率估计形状:", estimates.shape) # (500, 6)
# 4. 绘制图表
plt.figure(figsize=(10, 6))#创建宽10寸,高6寸的窗口
# 绘制每个面的概率曲线
for i in range(6):
plt.plot(estimates[:, i].numpy(),#获取所有实验组中第i+1个面的概率估计
label=f"P(骰子={i+1})",
linewidth=2)
# 添加真实概率参考线
plt.axhline(y=1/6, color='black', linestyle='dashed',#真实概率的线在y = 1/6的位置
linewidth=1, label='真实概率 (1/6)')
plt.xlabel('实验组数 (每组10次掷骰)')
plt.ylabel('估计概率')
plt.title('大数定律演示: 随着实验次数增加,频率收敛到概率')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 5. 验证收敛性
print("\n--- 收敛性验证 ---")
print("前10组实验的平均概率:", estimates[9].numpy().round(3))
print("前100组实验的平均概率:", estimates[99].numpy().round(3))
print("所有500组实验的平均概率:", estimates[-1].numpy().round(3))
#所有500组实验后的最终概率(-1表示最后一个) round(3)是四舍五入保留三位小数
print("真实概率:", [round(1/6, 3)] * 6)
运行结果:
公平骰子概率: tensor([0.1667, 0.1667, 0.1667, 0.1667, 0.1667, 0.1667])
--- 单次掷骰子 ---
结果: tensor([0., 0., 0., 0., 0., 1.])
掷出的是第 6 面
--- 10次掷骰子 ---
结果: tensor([0., 3., 3., 1., 2., 1.])
频率: tensor([0.0000, 0.3000, 0.3000, 0.1000, 0.2000, 0.1000])
--- 1000次掷骰子 ---
结果: tensor([159., 161., 160., 185., 157., 178.])
频率: tensor([0.1590, 0.1610, 0.1600, 0.1850, 0.1570, 0.1780])
--- 大数定律演示 ---
实验数据形状: torch.Size([500, 6])
累积数据形状: torch.Size([500, 6])
概率估计形状: torch.Size([500, 6])
--- 收敛性验证 ---
前10组实验的平均概率: [0.18 0.23 0.14 0.16 0.12 0.17]
前100组实验的平均概率: [0.183 0.184 0.156 0.155 0.168 0.154]
所有500组实验的平均概率: [0.168 0.171 0.163 0.172 0.159 0.167]
真实概率: [0.167, 0.167, 0.167, 0.167, 0.167, 0.167]
更多推荐



所有评论(0)