利用Matplotlib绘制硬币抛掷概率分布
立即解锁
发布时间: 2025-09-03 00:53:21 阅读量: 2 订阅数: 12 AIGC 

### 利用 Matplotlib 绘制硬币抛掷概率分布
在概率研究中,我们常常希望直观地理解不同事件发生的概率。以硬币抛掷为例,通过绘制概率分布,我们可以清晰地看到不同头朝上数量对应的概率情况。本文将详细介绍如何使用 Matplotlib 库来绘制硬币抛掷的概率分布,并深入探讨相关的概率理论。
#### 1. 绘制 10 次硬币抛掷的样本空间
我们首先关注 10 次硬币抛掷的情况。`weighted_sample_space` 字典包含了所有可能的头朝上数量及其对应的组合数。为了直观展示这些数据,我们可以绘制散点图,其中 x 轴表示头朝上的数量,y 轴表示对应头朝上数量的硬币抛掷组合数。
```python
import matplotlib.pyplot as plt
# 假设 weighted_sample_space 已经定义
x_10_flips = list(weighted_sample_space.keys())
y_10_flips = [weighted_sample_space[key] for key in x_10_flips]
plt.scatter(x_10_flips, y_10_flips)
plt.xlabel('Head-count')
plt.ylabel('Number of coin-flip combinations with x heads')
plt.show()
```
运行上述代码后,我们得到一个散点图,该图呈现出对称的形状,峰值位于头朝上数量为 5 的位置。这表明头朝上数量接近 5 的组合出现的频率更高,而距离 5 越远的组合出现的频率越低。
#### 2. 绘制 10 次硬币抛掷的概率分布
为了更直接地展示概率,我们可以将 y 轴的值转换为概率。具体做法是将每个组合数除以样本空间的总大小。
```python
sample_space_size = sum(weighted_sample_space.values())
prob_x_10_flips = [value / sample_space_size for value in y_10_flips]
plt.scatter(x_10_flips, prob_x_10_flips)
plt.xlabel('Head-count')
plt.ylabel('Probability')
plt.show()
```
通过这个概率分布图,我们可以直观地估计任何头朝上数量的概率。例如,观察到 5 个头朝上的概率约为 0.25。这种 x 值与概率之间的映射关系被称为概率分布。概率分布具有一些数学上的一致性属性,使得它们在可能性分析中非常有用。
概率分布的一个重要性质是,其曲线下的总面积始终等于 1.0。这意味着对于任何概率分布,所有可能事件的概率之和为 1。我们可以通过以下代码验证这一点:
```python
assert sum(prob_x_10_flips) == 1.0
```
#### 3. 可视化特定区间的概率
我们还可以可视化特定头朝上数量区间的概率。例如,头朝上数量在 8 到 10 之间的概率等于该区间下概率曲线的面积。我们可以使用 `plt.fill_between` 方法来突出显示这个区间。
```python
plt.plot(x_10_flips, prob_x_10_flips)
plt.scatter(x_10_flips, prob_x_10_flips)
where = [is_in_interval(value, 8, 10) for value in x_10_flips]
plt.fill_between(x_10_flips, prob_x_10_flips, where=where)
plt.xlabel('Head-count')
plt.ylabel('Probability')
plt.show()
```
同样,我们可以突出显示观察到 8 个或更多尾巴(即头朝上数量在 0 到 2 之间)的概率区间。
```python
plt.plot(x_10_flips, prob_x_10_flips)
plt.scatter(x_10_flips, prob_x_10_flips)
where = [not is_in_interval(value, 3, 7) for value in x_10_flips]
plt.fill_between(x_10_flips, prob_x_10_flips, where=where)
plt.xlabel('Head-count')
plt.ylabel('Probability')
plt.show()
```
这两个对称的阴影区间覆盖了硬币抛掷曲线的左右尾部。根据之前的分析,观察到超过 7 个头或尾巴的概率约为 10%,因此每个对称的阴影尾部区间大约覆盖曲线下总面积的 5%。
#### 4. 比较不同硬币抛掷次数的概率分布
为了更全面地理解硬币抛掷次数对概率分布的影响,我们可以比较 10 次和 20 次硬币抛掷的概率分布。首先,我们需要计算 20 次硬币抛掷的 x 轴头朝上数量和 y 轴概率。
```python
x_20_flips = list(weighted_sample_space_20_flips.keys())
y_20_flips = [weighted_sample_space_20_flips[key] for key in x_20_flips]
sample_space_size = sum(weighted_sample_space_20_flips.values())
prob_x_20_flips = [value / sample_space_size for value in y_20_flips]
```
然后,我们可以在同一个图中绘制这两个分布,并使用不同的颜色、线条样式和标记来区分它们。
```python
plt.plot(x_10_flips, prob_x_10_flips, label='A: 10 coin-flips')
plt.scatter(x_10_flips, prob_x_10_flips)
plt.plot(x_20_flips, prob_x_20_flips, color='black', linestyle='--', label='B: 20 coin-flips')
plt.scatter(x_20_flips, prob_x_20_flips, color='k', marker='x')
plt.xlabel('Head-count')
plt.ylabel('Probability')
plt.legend()
plt.show()
```
接下来,我们可以突出显示我们感兴趣的区间(80% 头或尾巴)在两个曲线上的情况。
```python
plt.plot(x_10_flips, prob_x_10_flips, label='A: 10 coin-flips')
plt.plot(x_20_flips, prob_x_20_flips, color='k', linestyle=':', label='B: 20 coin-flips')
where_10 = [not is_in_interval(value, 3, 7) for value in x_10_flips]
plt.fill_between(x_10_flips, prob_x_10_flips, where=where_10)
where_20 = [not is_in_interval(value, 5, 15) for value in x_20_flips]
plt.fill_between(x_20_flips, prob_x_20_flips, where=where_20)
plt.xlabel('Head-Count')
plt.ylabel('Probability')
plt.legend()
plt.show()
```
从图中可以看出,分布 B 的尾部阴影面积比分布 A 的小得多。这是因为分布 A 的尾部更厚,覆盖的面积更大。尾部的厚度决定了区间概率的差异。
为了更方便地比较这两个分布,我们可以将头朝上数量转换为频率(即头朝上数量除以总抛掷次数)。这样,两个分布的峰值将对齐在频率为 0.5 的位置。
```python
x_10_frequencies = [head_count / 10 for head_count in x_10_flips]
x_20_frequencies = [head_count / 20 for head_count in x_20_flips]
plt.plot(x_10_frequencies, prob_x_10_flips, label='A: 10 coin-flips')
plt.plot(x_20_frequencies, prob_x_20_flips, color='k', linestyle=':', label='B: 20 coin-flips')
plt.legend()
plt.xlabel('Head-Frequency')
plt.ylabel('Probability')
plt.show()
```
然而,这种转换会导致两个曲线下的面积分别缩小 10 倍和 20 倍,使得每个曲线下的总面积不再等于 1.0。为了解决这个问题,我们可以将曲线 A 和 B 的 y 轴值分别乘以 10 和 20,得到相对似然值。
```python
relative_likelihood_10 = [10 * prob for prob in prob_x_10_flips]
relative_likelihood_20 = [20 * prob for prob in prob_x_20_flips]
plt.plot(x_10_frequencies, relative_likelihood_10, label='A: 10 coin-flips')
plt.plot(x_20_frequencies, relative_likelihood_20, color='k', linestyle=':', label='B: 20 coin-flips')
plt.fill_between(x_10_frequencies, relative_likelihood_10, where=where_10)
plt.fill_between(x_20_frequencies, relative_likelihood_20, where=where_20)
plt.legend()
plt.xlabel('Head-Frequency')
plt.ylabel('Relative Likelihood')
plt.show()
```
在这个新的图中,曲线 A 就像一个矮而宽肩的健美运动员,而曲线 B 则像一个更高更瘦的人。由于曲线 A 更宽,它在更极端的头朝上频率区间上的面积更大。因此,当硬币抛掷次数为 10 时,观察到这些频率的记录更有可能发生。而曲线 B 更细更垂直,在中心频率 0.5 附近覆盖的面积更大。
#### 5. 大数定律的影响
根据概率理论,如果我们抛掷的硬币数量超过 20 次,频率曲线将变得更高更细。随着硬币抛掷次数增加到数百万甚至数十亿,曲线将完全失去宽度,变成一条位于频率 0.5 处的垂直直线。这意味着,当硬币抛掷次数趋近于无穷大时,头朝上的频率将绝对确定地等于头朝上的实际概率 0.5。
这种无限次硬币抛掷与绝对确定性之间的关系由概率论中的一个基本定理——大数定律保证。根据大数定律,当观察次数足够多时,观察到的频率将与该观察的概率几乎无法区分。因此,对于公平硬币抛掷,随着抛掷次数的增加,分布将由中心频率 0.5 主导。
大数定律不仅适用于硬币抛掷,还可以应用于更复杂的现象,如纸牌游戏。如果我们进行足够多的纸牌游戏模拟,那么我们获胜的频率将等于实际获胜的概率。
### 总结
- **概率分布的绘制**:通过绘制每个可能的数值观察与其概率的关系,我们可以生成概率分布。概率分布曲线下的总面积始终等于 1.0,特定区间下的面积等于在该区间内观察到某个值的概率。
- **相对似然的概念**:概率分布的 y 轴值不一定必须是概率,只要绘制的面积总和为 1.0 即可。在将头朝上数量转换为频率时,我们可以将 y 轴概率转换为相对似然,以保持面积为 1.0。
- **硬币抛掷次数的影响**:公平硬币抛掷序列的概率分布类似于对称曲线。随着硬币抛掷次数的增加,曲线的峰值将上升,两侧将变得更窄,中心频率 0.5 的主导地位将更加明显。
- **大数定律的应用**:根据大数定律,随着观察次数的增加,任何观察的频率将趋近于该观察的概率。这一原理可以应用于各种概率问题,包括纸牌游戏等复杂现象。
在后续的研究中,我们可以结合大数定律和随机模拟来近似复杂的概率。然而,由于大数定律要求大量的观察次数,这些模拟需要在大规模、计算成本高的环境中运行。因此,为了高效地实现模拟,我们需要熟悉 NumPy 数值计算库。
### 常见 Matplotlib 样式参数
| 参数 | 描述 | 示例值 |
| --- | --- | --- |
| color | 确定绘制输出的颜色,可以是颜色名称或单字符代码 | 'black' 或 'k' 表示黑色,'red' 或 'r' 表示红色 |
| linestyle | 确定连接数据点的绘制线的样式 | '-' 表示实线,'--' 表示虚线,':' 表示点线,'.' 表示点划线 |
| marker | 确定分配给单个绘制点的标记样式 | 'o' 表示圆形标记,'x' 表示 x 形标记,'s' 表示方形标记,'p' 表示五边形标记 |
| label | 将标签映射到指定的颜色和样式,该映射出现在图的图例中 | 'A: 10 coin-flips' 或 'B: 20 coin-flips' |
### 流程图
```mermaid
graph TD;
A[开始] --> B[绘制 10 次硬币抛掷样本空间];
B --> C[绘制 10 次硬币抛掷概率分布];
C --> D[可视化特定区间概率];
D --> E[比较 10 次和 20 次硬币抛掷概率分布];
E --> F[转换为频率并调整面积];
F --> G[应用大数定律分析];
G --> H[总结与展望];
H --> I[结束];
```
通过以上的分析和可视化,我们可以更深入地理解硬币抛掷的概率分布以及大数定律的影响。这些知识不仅有助于我们解决概率问题,还可以应用于实际生活中的各种决策场景。
### 利用 Matplotlib 绘制硬币抛掷概率分布(续)
#### 6. 深入理解概率分布与大数定律
在前面的内容中,我们已经了解了如何绘制硬币抛掷的概率分布,以及大数定律对其的影响。接下来,我们将进一步探讨概率分布的一些特性,以及如何利用这些特性进行更深入的分析。
##### 6.1 概率分布的对称性
公平硬币抛掷的概率分布呈现出明显的对称性。这意味着在分布曲线中,头朝上数量与尾朝上数量的概率是相等的。以 10 次硬币抛掷为例,头朝上 3 次和头朝上 7 次的概率是相同的。这种对称性反映了硬币抛掷的公平性,即每次抛掷时头朝上和尾朝上的可能性是相等的。
我们可以通过观察概率分布曲线来验证这种对称性。在之前绘制的 10 次硬币抛掷概率分布曲线中,曲线关于头朝上数量为 5 的位置对称。这表明在 10 次抛掷中,接近 5 次头朝上的情况出现的概率较高,而偏离 5 次的情况出现的概率较低。
##### 6.2 大数定律的实际应用
大数定律在实际生活中有广泛的应用。除了前面提到的纸牌游戏,它还可以应用于保险、金融等领域。例如,在保险行业中,保险公司需要根据大量的历史数据来估计不同风险事件发生的概率。通过大数定律,保险公司可以确保在大量的保险业务中,实际赔付的金额与预期赔付的金额相近。
在金融领域,大数定律可以用于投资组合的风险管理。投资者可以通过分散投资来降低单个投资的风险。根据大数定律,当投资组合中的资产数量足够多时,投资组合的整体风险将趋近于市场的平均风险。
#### 7. 结合 NumPy 进行高效模拟
为了更高效地实现基于大数定律的随机模拟,我们需要熟悉 NumPy 数值计算库。NumPy 提供了高效的数组操作和随机数生成功能,使得我们可以在大规模数据集上进行快速计算。
##### 7.1 安装和导入 NumPy
首先,我们需要安装 NumPy 库。如果你使用的是 Anaconda 环境,可以通过以下命令进行安装:
```bash
conda install numpy
```
如果你使用的是 pip 包管理器,可以使用以下命令:
```bash
pip install numpy
```
安装完成后,我们可以在 Python 代码中导入 NumPy 库:
```python
import numpy as np
```
##### 7.2 使用 NumPy 进行硬币抛掷模拟
我们可以使用 NumPy 的随机数生成功能来模拟硬币抛掷。以下是一个简单的示例,模拟 1000 次硬币抛掷,并统计头朝上的次数:
```python
import numpy as np
# 模拟 1000 次硬币抛掷
coin_flips = np.random.randint(0, 2, 1000)
# 统计头朝上的次数
head_count = np.sum(coin_flips)
print(f"在 1000 次硬币抛掷中,头朝上的次数为: {head_count}")
```
在这个示例中,`np.random.randint(0, 2, 1000)` 生成了一个包含 1000 个随机整数的数组,每个整数的值为 0 或 1,分别表示尾朝上和头朝上。然后,我们使用 `np.sum()` 函数统计数组中 1 的个数,即头朝上的次数。
##### 7.3 多次模拟并分析结果
为了更深入地理解大数定律,我们可以进行多次模拟,并分析每次模拟的结果。以下是一个示例,进行 100 次模拟,每次模拟 1000 次硬币抛掷,并计算每次模拟中头朝上的频率:
```python
import numpy as np
import matplotlib.pyplot as plt
# 进行 100 次模拟
num_simulations = 100
num_flips = 1000
head_frequencies = []
for _ in range(num_simulations):
coin_flips = np.random.randint(0, 2, num_flips)
head_count = np.sum(coin_flips)
head_frequency = head_count / num_flips
head_frequencies.append(head_frequency)
# 绘制头朝上频率的直方图
plt.hist(head_frequencies, bins=20, edgecolor='black')
plt.xlabel('Head Frequency')
plt.ylabel('Frequency Count')
plt.title('Distribution of Head Frequencies in 100 Simulations')
plt.show()
```
在这个示例中,我们使用一个循环进行 100 次模拟,每次模拟 1000 次硬币抛掷。对于每次模拟,我们计算头朝上的频率,并将其存储在 `head_frequencies` 列表中。最后,我们使用 `plt.hist()` 函数绘制头朝上频率的直方图,以直观地展示频率的分布情况。
#### 8. 总结与展望
通过本文的介绍,我们深入了解了如何使用 Matplotlib 绘制硬币抛掷的概率分布,以及概率论中的大数定律。我们学习了如何将头朝上数量转换为频率,如何计算相对似然,以及如何通过可视化来直观地理解概率分布的特性。
同时,我们还介绍了 NumPy 库的基本使用方法,并展示了如何结合大数定律和随机模拟来近似复杂的概率。在实际应用中,我们可以利用这些知识来解决各种概率问题,如风险评估、决策分析等。
未来,我们可以进一步探索更复杂的概率分布,如正态分布、泊松分布等,并学习如何使用更高级的统计方法进行数据分析。此外,我们还可以结合机器学习算法,如深度学习,来处理大规模的概率数据,从而实现更精确的预测和决策。
### 常见问题解答
| 问题 | 解答 |
| --- | --- |
| 为什么概率分布曲线下的总面积等于 1.0? | 概率分布曲线下的总面积代表了所有可能事件的概率之和。由于所有可能事件的概率之和必须为 1,因此概率分布曲线下的总面积等于 1.0。 |
| 大数定律在实际应用中有哪些限制? | 大数定律要求观察次数足够多,才能保证观察到的频率趋近于概率。在实际应用中,由于计算资源和时间的限制,可能无法进行足够多的观察。此外,大数定律假设每次观察是独立的,而在实际情况中,观察之间可能存在相关性。 |
| 如何选择合适的 Matplotlib 样式参数? | 选择合适的 Matplotlib 样式参数取决于具体的需求和可视化效果。例如,如果需要突出显示某个数据系列,可以选择不同的颜色或标记样式。如果需要区分不同的数据系列,可以使用不同的线条样式或标签。 |
### 流程图
```mermaid
graph TD;
A[深入理解概率分布] --> B[分析概率分布对称性];
B --> C[验证公平硬币抛掷对称性];
A --> D[应用大数定律];
D --> E[保险行业风险估计];
D --> F[金融投资组合风险管理];
G[结合 NumPy 进行模拟] --> H[安装和导入 NumPy];
H --> I[使用 NumPy 模拟硬币抛掷];
I --> J[多次模拟并分析结果];
K[总结与展望] --> L[回顾概率分布和大数定律];
L --> M[探索更复杂概率分布];
M --> N[结合机器学习算法];
```
通过以上的内容,我们不仅掌握了硬币抛掷概率分布的绘制和分析方法,还了解了大数定律的实际应用和 NumPy 库的基本使用。这些知识将帮助我们更好地理解和处理各种概率问题。
0
0
复制全文
相关推荐







