1.伯努利试验

我们做一个抛硬币的实验,假设硬币是均匀的

我们抛10次记做一组实验,第一组4正6反,第二组7正3反….

假设我们做了1000组实验,我们把每组结果得到的正面数量记录下来,共1000个数字,比如

4,6,5,7,5,9,4,5,6,1,…..

我们统计一下每个数字出现的频率,并画成柱状图

import random
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation


plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
plt.rcParams["axes.unicode_minus"] = False



def board(rows, balls):

    positions = {}

    for _ in range(balls):
        num = 0

        for _ in range(rows):
            if random.random() < 0.5:  # 概率
                num += 1
                
        if num in positions:
            positions[num] += 1
        else:
            positions[num] = 1

    return positions



if __name__ == "__main__":
    rows = 10  # 投币次数
    balls = 1000  # 实验次数

    fig, ax = plt.subplots(figsize=(10, 6))

    ax.clear()
    positions = board(rows, balls)
    
    ax.bar(positions.keys(), positions.values(), color="skyblue", edgecolor="black")
    ax.set_title("投币实验", fontsize=16)
    ax.set_xlabel("正面次数", fontsize=12)
    ax.set_ylabel("组数", fontsize=12)
    ax.grid(True)
    plt.show()

得到结果图

很像正态分布曲线

在概率学上,抛十次同一枚硬币的实验,叫做十重伯努利试验。

数学定理表明:大量的n重伯努利试验的结果能够产生正态曲线

事实上,可以用一个简易的装置来进行n重抛硬币实验,这个装置就是高尔顿板。

高尔顿板为一块竖直放置的板,上面有交错排列的钉子。让小球从板的上端自由下落,当其碰到钉子后会随机向左或向右落下。最终,小球会落至板底端的某一格子中。假设板上共有n排钉子,每个小球撞击钉子后向右落下的概率为p,则小球落入第k个格子概率为二项分布\(\begin{pmatrix}n\\k\end{pmatrix}p^k(1-p)^{n-k}\)

假设小球落到中间格n,说明向左的次数和向右的次数相同,如果落在n+1格,那么说明向右的次数比向左的次数多2次,以此类推

import random
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation


plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
plt.rcParams["axes.unicode_minus"] = False


# 高尔顿板模拟函数
def galton_board(rows, balls, probs):

    positions = [0] * (rows*2 + 1)

    for _ in range(balls):
        position = rows

        for row in range(rows):
            if random.random() < probs[row]:  # 概率
                position += 1
            else:
                position -= 1

        position = max(0, min(position, rows*2))
        positions[position] += 1

    return positions


# 动画更新函数
def update(frame):
    ax.clear()
    positions = galton_board(rows, frame, probs)
    
    ax.bar(range(rows*2+1), positions, color="skyblue", edgecolor="black")
    ax.set_title("高尔顿板模拟", fontsize=16)
    ax.set_xlabel("位置", fontsize=12)
    ax.set_ylabel("球的数量", fontsize=12)
    ax.set_xticks(range(rows*2+1))
    ax.grid(True)


if __name__ == "__main__":
    rows = 10  # 行数
    balls = 15000  # 球的数量
    step = 5
    rand = False

    probs = [random.random() if rand else 0.5 for _ in range(rows)]

    print(f"概率分布为:{probs}")
    fig, ax = plt.subplots(figsize=(10, 6))

    ani = animation.FuncAnimation(
        fig, update, frames=np.arange(0, balls, balls//step), repeat=False
    )

    plt.show()

可以得到一个近似正太分布的曲线

这是每一排概率都是0.5的结果,事实上,如果每一排概率都不一样,也能得到正态分布的曲线。在上面代码中,我们把rand = True

结果只是对称轴的位置有些差异,即便概率不同,在大量n重伯努利试验的概率分布仍然是正太分布

下面给出中心极限定理

数学表述为:所研究的随机变量如果由大量独立的随机变量相加而成,那么它的分布近似于正态分布

通俗表达:如果一个结果由大量的不相干的因素累加而成,那么这个结果一定表现为正态分布。

2.68-95-99法则

总体均值\(\mu=\frac{X_1+X_2+...+X_N}{N}\)

总体方差\(\sigma^2=\frac{(x_1-\mu)^2+(x_2-\mu)^2+...+(x_N-\mu)^2}{N}\)

还是高尔顿板,假设我们算出了方差和均值。然后我们可以定义一个区间[\(\mu-\sigma\),\(\mu+\sigma\)],假设\(\mu-\sigma=a-1.34\),\(\mu+\sigma=a+0.99\)

那么我们可以近似出这个区间的豆子数量,约670颗,占总体的67%左右

同理,我们定义一个\(2\sigma\)区间[\(\mu-2\sigma\),\(\mu+2\sigma\)]

可以算出区间内有967颗豆子,占总体的95.7%

同理,定义一个\(3\sigma\)区间[\(\mu-3\sigma\),\(\mu+3\sigma\)]

共999颗豆子,占总体的99.9%

从大量的案例可以发现,若总体一个服从正态分布,不论其标准差是多少,以均值为中心,都有

  • \(1\sigma\)区间覆盖总体的68.2%的样本
  • \(2\sigma\)区间覆盖总体的95.4%的样本
  • \(3\sigma\)区间覆盖总体的99.7%的样本

这就是68-95-99.7法则

3.均值抽样分布

假设我们要估计某一种情况的平均值,比如人口身高,但是我们不可能拿到所有中国人的数据。这时候,该怎么办?

答案是,我们可以做抽样,就是从总体中,抽取一些个体,抽取的个体数量N,叫做样本容量

我们可以计算这个样本的平均值,用来估计总体的平均值\(\mu\)

模拟代码如下

import matplotlib.pyplot as plt
import numpy as np


plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
plt.rcParams["axes.unicode_minus"] = False

np.random.randint

# 模拟采样的
def sample_N(N):
    # 均匀分布
    data1 = np.random.uniform(0, 10, N)
    
    # 正态分布
    data2 = np.random.normal(0, 10, N)
    
    # 泊松分布
    data3 = np.random.poisson(5, N)
    
    # 指数分布
    data4 = np.random.exponential(2, N)
    
    # 二项分布
    data5 = np.random.binomial(10, 0.5, N)
    
    # 随机组合
    data = data1+data3*np.log(data4)-data5*np.abs(data2)

    return data

def board(total,N):
    res = {}
    datas = {}
    for _ in range(total):
        data = sample_N(N) #均值抽样
        
        for i in data:
            i = round(i)
            if i not in datas:
                datas[i]=0
            datas[i]+=1
            
        num = round(np.mean(data))
        if num not in res:
            res[num] = 0
        res[num] += 1
        
    return res,datas
        
    
if __name__ == "__main__":
    total = 10000  # 抽样次数
    N = 30  # 样本容量

    res,datas = board(total, N)
    
    
    plt.figure(1)
    plt.bar(res.keys(), res.values(), color="skyblue", edgecolor="black")
    plt.title("抽样分布", fontsize=16)
    plt.xlabel("x", fontsize=12)
    plt.ylabel("y", fontsize=12)
    plt.grid(True)
    
    plt.figure(2)
    plt.bar(datas.keys(), datas.values(), color="skyblue", edgecolor="black")
    plt.title("数据分布", fontsize=16)
    plt.xlabel("x", fontsize=12)
    plt.ylabel("y", fontsize=12)
    
    plt.grid(True)
    plt.show()

我们用了多种原始的数据分布的组合去生成一个未知的数据分布

下图所示,这里样本容量N=30,可以发现,只要抽样次数足够多,容量N足够大,就能得到一个正态分布轮廓的均值抽样分布,而这个分布的对称轴必然是总体均值的真实值\(\mu\)。

(模拟方法:我们可以用sample_N提前生成一个大量数据的数组,然后从这个固定数组中反复抽样。最终抽样分布的对称轴必定接近数组的平均值)

如果我们缩小N,比如N=5,可以发现分布变宽了

加大N=100,可以发现分布变窄了

下面给出均值抽样分布的中心极限定理

对一个总体进行大量重复的随机抽样并计算均值,用柱状图来表示这些均值出现的频次,最终将近似出正态分布的轮廓。正态分布对称轴所表示的值即为总体的真实均值,抽样的样本容量N越大则均值分布越窄(方差变小),抽样次数越多则直方图越平滑

在现实中,比如某国的平均收入是\(\mu\),标准差是\(\sigma\)。假设我们想知道我国的平均收入是否和这个分布差别不大。我们可以做一次采样,随机抽取 n 个观测值并计算样本均值 \(\bar{x}\),如果这仅仅一次的结果就位于\(3\sigma\)区间之外,我们有很大理由怀疑,我国的平均收入分布不属于均值为\(\mu\)的总体(不严谨)。

4.假设检验

假设有一个高一数学成绩的抽样分布如下图,每一个柱子的大小转为了百分比,代表占样本总体的比例

可以看出,样本均值落到两边尾巴的概率是非常低的,尾巴尖就代表是极端事件,那么如何界定是否是尾巴尖?其实就是频次小于某个数值,这个数值,叫做临界值,是一个人为规定的数值。

例如,人为规定,从两边尾巴尖项对称轴的方向,数出5%的频次的就是极端情况(其实就是\(2\sigma\))。如上图,从左边数到134共0.8%的,从右边数到141共1.2%。(再往中间数就超过5%了,所以不会继续数)

也就是说均值\(<=134或者>=141\)就是极端区域

假设高二数学成绩和高一数学总体是一样的,都是\(\mu=137.41\)的总体。我们在高二中进行一次抽样,得到样本均值为134,很明显落入了极端区域,极端事件发生,说明我们这个假设是有问题的。

下面给出定义


我们把一开始这个假设记作\(H_0\)

\(H_0\):高一数学成绩和高二数学成绩没有明显差别

\(H_0\):为零假设、原假设或Null Hypothesis

\(H_0\):\(\mu_{高一}=\mu_{高二}\)

\(H_1\):高一数学成绩和高二数学成绩有明显差别


在人为规定双边尾巴为5%,只抽样了一次,极端事件就发生了,我们便有理由拒绝\(H_0\),接受\(H_0\)的对立面假设\(H_1\),\(H_1\)也叫做对立假设、备择假设或Alternative Hypothesis。

这个双边尾巴5%,我们简化一下说法,叫做显著性水平\(\alpha\),英文是signification level,这个\(\alpha\)可以5%、2%或0.1%等,具体看实际案例,上面\(\alpha=5\%\),也就是两边各分配2.5%。

如果我们重新设置\(\alpha=0.1%\)%,那么,133-134就不是极端区域。那我们就不能拒绝\(H_0\),。这个“极端区域”有个专业的名字,英文为rejection region,中文为拒绝域、否定域或临界域

上述就是假设检验的基本思路。