一、什么是采样

  • 在信号系统和数字信号处理中,采样是每隔一定的时间测量一次声音信号的幅值,把时间连续的模拟信号转换成时间离散幅值的采样信号。
  • 如果采样的时间间隔相等,这种采样称为均匀采样
  • 在计算机系统中有一个重要的问题叫随机采样:就是给定一个概率分布python随机抽取数据 python 随机取样_人工智能,我们如何按照该分布产生样本
  • 在机器学习或统计学习中,我们是给定一堆样本数据,通过参数估计的方法求出这堆样本所符合的概率分布python随机抽取数据 python 随机取样_人工智能;而随机采样刚相反:给定一个概率分布p(x),如何生成满足条件的样本?

二、均匀分布的采样

  • 首先需要明确,计算机程序都是确定性的,因此并不能产生真正意义上的随机数,只能产生伪随机数.
  • 另外由于计算机的存储和计算单元只能处理离散状态值,因此也不能产生连续均匀分布的随机数,只能通过离散分布来逼近连续分布.
  • 均匀分布式是一种最简单的分布。在计算机中使rand()函数生成的伪随机数序列,就可以看做是一种均匀分布
  • 一般可采用线性同余法来生成离散均匀分布伪随机数,计算公式为:python随机抽取数据 python 随机取样_均匀分布_03
  • 根据当前生成的随机数python随机抽取数据 python 随机取样_随机数_04来进行适当变换,进而产生下一次的随机数python随机抽取数据 python 随机取样_人工智能_05.初始值python随机抽取数据 python 随机取样_随机数_06称为随机种子.上式可得到区间python随机抽取数据 python 随机取样_python随机抽取数据_07上的伪随机数.
  • 想要真正的随机数可以通过自然界的物理产生,比如放射性物质的衰变,温度,气流的扰动等.有一些网站可以提供基于大自然的随机现象的随机数,有兴趣的读者可以尝试一下.
  • 代码:
import time
start = int(time.time()); # 以当前时间作为种子
m = (1 << 31) -1; # 2^31 -1
a = 1103515245;
b = 12345;
R=start
for i in range(5):
    R = ( a *R + b ) % m;
    print(R/m)#产生[0,1]的随机数

三、离散分布采样

  • 离散分布是比均匀分布稍微复杂一点的情况。下面用一个例子来详细说明:
  • 令概率分布为:python随机抽取数据 python 随机取样_算法_08python随机抽取数据 python 随机取样_人工智能_09,我们可以使用将每个概率视为区间[0,1]中的一个小线段,线段长度为概率的大小,然后用上面均匀分布产生随机数,随机所在区间就是当前要采的样本。
  • 代码:
import numpy as np
from collections import defaultdict

dic = defaultdict(int)#key是x的取值,value是x被采样的次数
def sample():
    u = np.random.rand()#在[0,1]上按照均匀分布产生一个随机数
    if u <= 0.1:#[0,0.1]=>x=hello
        dic["hello"] += 1
    elif u <= 0.3:#(0.1,0.3]=>x=java
        dic["java"] += 1
    elif u <= 0.6:#(0.3,0.6]=>x=python
        dic["python"] += 1
    else:#(0.6,1]=>x=scala
        dic["scala"] += 1


for i in range(10000):#进行100词采样
    sample()
for k,v in dic.items():
    print(k,v)

输出:
python 2991
scala 3940
hello 1037
java 2032

四、逆变换采样法

  • 对于连续型随机变量python随机抽取数据 python 随机取样_人工智能_10,一点有两个函数:
  • 概率密度函数:python随机抽取数据 python 随机取样_python随机抽取数据_11
  • 分布函数:python随机抽取数据 python 随机取样_随机数_12 :表示随后变量取值在区间python随机抽取数据 python 随机取样_随机数_13的概率
  • 两个函数的图如下所示:
  • python随机抽取数据 python 随机取样_均匀分布_14


  • 并且有下面性质:
  • python随机抽取数据 python 随机取样_随机数_15python随机抽取数据 python 随机取样_算法_16的一个原函数
  • 并且python随机抽取数据 python 随机取样_均匀分布_17.
  • python随机抽取数据 python 随机取样_随机数_15是一个单独递增的函数,并存在反函数python随机抽取数据 python 随机取样_python随机抽取数据_19.
  • 重要定理: 若联系型随机变量python随机抽取数据 python 随机取样_人工智能_20与连续型随机变量python随机抽取数据 python 随机取样_人工智能_10是关系为:python随机抽取数据 python 随机取样_随机数_22,即他们的关系函数是python随机抽取数据 python 随机取样_人工智能_10是分布函数。则随机变量python随机抽取数据 python 随机取样_人工智能_20python随机抽取数据 python 随机取样_算法_25上的均匀分布,即:python随机抽取数据 python 随机取样_人工智能_20~python随机抽取数据 python 随机取样_人工智能_27.下面证明一下:python随机抽取数据 python 随机取样_人工智能_28 python随机抽取数据 python 随机取样_python随机抽取数据_29 python随机抽取数据 python 随机取样_人工智能_30python随机抽取数据 python 随机取样_算法_31 这恰恰是python随机抽取数据 python 随机取样_随机数_32上均匀分布的分布函数,所以:python随机抽取数据 python 随机取样_人工智能_20~python随机抽取数据 python 随机取样_python随机抽取数据_34
  • 若Y~U(0,1)则(只是为了说明上面的证明):
  • 概率密度函数为:python随机抽取数据 python 随机取样_python随机抽取数据_35
  • 分布函数::python随机抽取数据 python 随机取样_算法_36
  • 有了上面这个定理,我们可以:(逆变换采样法)
  • 首先对于随机变量Y进行均匀采样抽取一个数python随机抽取数据 python 随机取样_算法_37
  • 由于:python随机抽取数据 python 随机取样_人工智能_38
  • 我们可以得到一个随机变量X的样本python随机抽取数据 python 随机取样_算法_39python随机抽取数据 python 随机取样_随机数_40
  • 过程可以如下图所示:
  • python随机抽取数据 python 随机取样_随机数_41


  • 例子:
  • 假设随机变量X的概率密度函数为:python随机抽取数据 python 随机取样_随机数_42
  • 则其相应的分布函数为:python随机抽取数据 python 随机取样_算法_43
  • 在区间[0,1]上进行均匀分布的采样,得到序列:python随机抽取数据 python 随机取样_人工智能_44
  • 将序列带入python随机抽取数据 python 随机取样_随机数_45,得到随机变量X的样本python随机抽取数据 python 随机取样_均匀分布_46

五、Box-Muller算法

  • Box-Muller算法实质是逆变换采样法的一个特例,即随机变量python随机抽取数据 python 随机取样_人工智能_10服从正态分布的情况。
  • 假设python随机抽取数据 python 随机取样_人工智能_10~python随机抽取数据 python 随机取样_python随机抽取数据_49,其概率密度函数为:python随机抽取数据 python 随机取样_随机数_50
  • 但是注意到直接对python随机抽取数据 python 随机取样_人工智能_51进行定积分得到其分布函数python随机抽取数据 python 随机取样_人工智能_52是行不通。
  • 假设:python随机抽取数据 python 随机取样_人工智能_10 ~ python随机抽取数据 python 随机取样_python随机抽取数据_49python随机抽取数据 python 随机取样_人工智能_20~python随机抽取数据 python 随机取样_python随机抽取数据_49并且python随机抽取数据 python 随机取样_人工智能_10python随机抽取数据 python 随机取样_人工智能_20相互独立,则其联合概率密度函数为:python随机抽取数据 python 随机取样_均匀分布_59
  • 进行下面随机变量变换:python随机抽取数据 python 随机取样_python随机抽取数据_60其中python随机抽取数据 python 随机取样_人工智能_61python随机抽取数据 python 随机取样_人工智能_62都为随机变量
  • 则有:python随机抽取数据 python 随机取样_人工智能_63
  • 则随机变量python随机抽取数据 python 随机取样_人工智能_61python随机抽取数据 python 随机取样_人工智能_62的边缘概率分布函数为:python随机抽取数据 python 随机取样_均匀分布_66 python随机抽取数据 python 随机取样_人工智能_67
  • python随机抽取数据 python 随机取样_python随机抽取数据_68表达式可知:python随机抽取数据 python 随机取样_人工智能_62~python随机抽取数据 python 随机取样_算法_70
  • 令随机变量python随机抽取数据 python 随机取样_人工智能_71与随机变量python随机抽取数据 python 随机取样_人工智能_61的关系为:python随机抽取数据 python 随机取样_均匀分布_73python随机抽取数据 python 随机取样_算法_74python随机抽取数据 python 随机取样_算法_75~python随机抽取数据 python 随机取样_python随机抽取数据_34
  • python随机抽取数据 python 随机取样_均匀分布_77~python随机抽取数据 python 随机取样_算法_70python随机抽取数据 python 随机取样_python随机抽取数据_79~python随机抽取数据 python 随机取样_python随机抽取数据_34 则:python随机抽取数据 python 随机取样_算法_81~python随机抽取数据 python 随机取样_均匀分布_82~python随机抽取数据 python 随机取样_python随机抽取数据_34
  • python随机抽取数据 python 随机取样_算法_81python随机抽取数据 python 随机取样_python随机抽取数据_85可以通过按python随机抽取数据 python 随机取样_随机数_32上的均匀分布采样得到。并且有:
  • python随机抽取数据 python 随机取样_人工智能_87
  • python随机抽取数据 python 随机取样_算法_88
  • python随机抽取数据 python 随机取样_算法_89
  • python随机抽取数据 python 随机取样_python随机抽取数据_90
  • python随机抽取数据 python 随机取样_随机数_91
  • 代码:
import numpy as np
from pylab import *

def sample():
    U1 = np.random.rand()  # 两个均匀分布分别为x, y
    U2 = np.random.rand()
    theta = 2 * np.pi * U1
    R = np.sqrt(-2 * np.log(U2))
    X= R * np.cos(theta)
    Y= R * np.sin(theta)
    return X


def sampleNtimes():
    list = []
    n = 100000
    for i in range(n):
        x = sample()
        list.append(x)
    y=np.array(list).reshape(n,1)
    hist(y, 20,normed=1, fc='c')  # 采样直方图

    x = arange(-5, 5, 0.1)
    plot(x, 1 / np.sqrt(2 * np.pi) * np.exp(-0.5 * x ** 2), 'g', lw=6)  # 标准正态分布
    xlabel('x', fontsize = 24)
    ylabel('p(x)', fontsize = 24)
    show()
sampleNtimes()

输出:

python随机抽取数据 python 随机取样_人工智能_92



五、接受/拒绝采样

  • 很多实际问题中,对于目标分布python随机抽取数据 python 随机取样_随机数_93直接采样比较难, 因此选取一个容易采样的参考分布python随机抽取数据 python 随机取样_人工智能_94比如高斯分布,使得对于任意python随机抽取数据 python 随机取样_均匀分布_95都有python随机抽取数据 python 随机取样_算法_96,则可以按如下过程采用:
  • 从参考分布python随机抽取数据 python 随机取样_算法_97中随机抽取一个样本python随机抽取数据 python 随机取样_人工智能_98
  • 从均匀分布python随机抽取数据 python 随机取样_人工智能_99)产生一个随机数python随机抽取数据 python 随机取样_均匀分布_100
  • 如果python随机抽取数据 python 随机取样_随机数_101 ,则接受样本python随机抽取数据 python 随机取样_人工智能_98;否则拒绝重新进行步骤1~3,直到新产生的样本 被接
  • python随机抽取数据 python 随机取样_人工智能_103python随机抽取数据 python 随机取样_算法_97的关系图:
  • python随机抽取数据 python 随机取样_随机数_105


  • 现在我们来分析一下接受/拒绝采样在python随机抽取数据 python 随机取样_均匀分布_106采样数量的决定因素:
  • 第一个因素是python随机抽取数据 python 随机取样_随机数_107 :因为如果python随机抽取数据 python 随机取样_随机数_107大,那么python随机抽取数据 python 随机取样_python随机抽取数据_109就会比较大,而我们采样是按照python随机抽取数据 python 随机取样_python随机抽取数据_109来进行采样的则python随机抽取数据 python 随机取样_人工智能_98被采样的概率就大,
  • 第一个因素是python随机抽取数据 python 随机取样_人工智能_112python随机抽取数据 python 随机取样_算法_113 越大而python随机抽取数据 python 随机取样_均匀分布_100python随机抽取数据 python 随机取样_随机数_115上的均匀分布,则python随机抽取数据 python 随机取样_算法_116
  • 当然最主要的因素是第一个因素。
  • 拒绝采用的关键是为目标分布python随机抽取数据 python 随机取样_随机数_93选取一个合适的包络网络函数python随机抽取数据 python 随机取样_人工智能_118:包络函数越紧,每次采样时样本被接受的概率越大,采样效率越高.
  • 代码:
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
from pylab import *

#标准正态分布
def qsample():
    U1 = np.random.rand()  # 两个均匀分布分别为x, y
    U2 = np.random.rand()
    theta = 2 * np.pi * U1
    R = np.sqrt(-2 * np.log(U2))
    X= R * np.cos(theta)
    Y= R * np.sin(theta)
    return X

#正态分布函数
def q(x):
    return 1 / np.sqrt(2 * np.pi) * np.exp(-0.5 * x ** 2)

#目标分布
def p(x):
    x=x+1.2#左移一点点让正态分布正好覆盖
    return 0.3 * np.exp(-(x - 0.3) ** 2) + 0.7 * np.exp(-(x - 2.) ** 2 / 0.3)


def rejection(nsamples):
    K=3  #  k值
    samples = np.zeros(nsamples, dtype=float)
    for i in range(nsamples):
        accept = False
        while not accept:
            x = qsample()
            u = np.random.rand()
            if u < p(x)/(K*q(x)):
                accept = True
                samples[i] = x
    return samples


x = np.arange(-4, 4, 0.01)
x2 = np.arange(-4.5, 4.5, 0.1)
realdata = p(x)  #目标概率函数p(x)图
stardline=3*q(x)    #正态分布函数q(x)
box = np.ones(len(x2))*0.8
plt.plot(x, realdata, 'g', lw=3)
plt.plot(x, stardline, 'r', lw=3)
samples = rejection(100000)

plt.hist(samples, 100, normed=1, fc='c')
plt.xlabel('x', fontsize=24)
plt.ylabel('p(x)', fontsize=24)
plt.show()

输出:

python随机抽取数据 python 随机取样_python随机抽取数据_119

参考连接: