O(1) 的离散概率分布采样方法 - Alias Method

2023-05-16

前言

如果你对这篇文章感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。


Alias Method

给定一个离散概率分布 p = [ 0.3   0.2   0.4   0.1 ] p=[0.3 \ 0.2\ 0.4\ 0.1] p=[0.3 0.2 0.4 0.1],现要对该分布进行采样,最直接的方法是随机一个 [ 0 , 1 ] [0,1] [0,1] 之间的数 v v v,从左往右比:

  • v ≤ 0.3 v\leq 0.3 v0.3,则采样类别 A A A
  • v > 0.3 v>0.3 v>0.3,则和 0.5 = 0.3 + 0.2 0.5=0.3+0.2 0.5=0.3+0.2 对比,若比 0.5 0.5 0.5 小,则采样类别 B B B
  • 否则继续往后,和 0.9 = 0.3 + 0.2 + 0.4 0.9=0.3+0.2+0.4 0.9=0.3+0.2+0.4 对比。

上述过程的时间复杂度为 O ( n ) O(n) O(n),可通过二分算法加速至 O ( log ⁡ n ) O(\log n) O(logn)。那么还有没有更快的方式?

考虑一种「接受 & 拒绝」的方式,对于上述离散概率分布 p p p,先在 [ 1 , 4 ] [1,4] [1,4] 中随机一个整数 i i i,再在 [ 0 , 1 ] [0,1] [0,1] 中随机一个实数 r r r,若 r ≤ p [ i ] r\leq p[i] rp[i],则接受 i i i(即采样 i i i 对应类别),否则拒绝 i i i,重新执行上述过程。

上述过程显然较慢,而 Alias Method 便是对其进行加速的方法。Alias Method 的思想是,用概率高的填充概率低的,使得随机的 i i i 一定可以对应一个结果,具体如下:

  • p ∗ n p*n pn 得到 p ′ = p ∗ 4 = [ 1.2   0.8   1.6   0.4 ] p'=p*4=[1.2\ 0.8\ 1.6\ 0.4 ] p=p4=[1.2 0.8 1.6 0.4],如下图所示:
    在这里插入图片描述

  • 随后将概率高的类别填充至概率低的类别,实现每个位置只存在两个类别,且和为 1,即得到 Alias Table:
    在这里插入图片描述

可以发现经过转换后,每一列最多只有两个类别,且和为 1。因此重新执行之前「接受 & 拒绝」的方式,先在 [ 1 , 4 ] [1,4] [1,4] 中随机一个整数 i i i,再在 [ 0 , 1 ] [0,1] [0,1] 中随机一个实数 r r r,例如 i = 2 i=2 i=2,则若 r ≤ 0.8 r\leq 0.8 r0.8,则采样类别 B B B,否则采样类别 A A A

通过上述的构造,Alias Method 只需执行一遍,实现 O ( 1 ) O(1) O(1) 的时间复杂度。具体细节可参照如下代码实现:

import numpy as np


class aliasMethod:
    def __init__(self, prob):
        self.n = len(prob)
        self.prob = prob
        assert np.sum(prob) == 1.0
        self.accept, self.alias = self.create_table()

    def create_table(self):
        area = self.prob * self.n
        small, large = [], []
        accept, alias = [0] * self.n, [0] * self.n

        for idx, value in enumerate(area):
            if value < 1.0:
                small.append(idx)
            else:
                large.append(idx)

        while small and large:
            sid, lid = small.pop(), large.pop()
            accept[sid] = area[sid]
            alias[sid] = lid
            area[lid] = area[lid] + area[sid] - 1

            if area[lid] < 1.0:
                small.append(lid)
            elif area[lid] > 1.0:
                large.append(lid)

        for lid in large:
            accept[lid] = 1
        for sid in small:
            accept[sid] = 1

        return accept, alias

    def sample(self):
        i = int(np.random.random() * self.n)
        r = np.random.random()
        if r < self.accept[i]:
            return i
        else:
            return self.alias[i]


if __name__ == "__main__":
    n = 10
    prob = np.random.rand(n)
    prob /= np.sum(prob)

    alias_table = aliasMethod(prob)
    sample_cnt = 10000
    res = np.zeros(n)
    
    for i in range(sample_cnt):
        res[alias_table.sample()] += 1
    res /= np.sum(res)

    print(f"prob: {list(prob)}")
    print(f"simulation: {list(res)}")

参考资料

  • [TOMS - 1977 - Alastair J Walker] An efficient method for generating discrete random variables with general distributions
  • 内容解析 - Alias Method
  • 代码实现 1 - Alias Method
  • 代码实现 2 - Alias Method
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

O(1) 的离散概率分布采样方法 - Alias Method 的相关文章

  • 关于使用Antd中的DatePicker出现的日期格式转化问题(Dayjs和Momentjs)

    在测试过程中发现了一个比较有意思的bug问题 xff0c 我们使用的是antd中的DatePicker组件 xff0c 当时间选择框存在已经设定的初始值后 xff0c 点击时间选择框直接报错 xff0c 但是当清除内容或者处于新建没有默认值
  • Javascript基础知识整理—1

    1 JS数据类型 原始数据类型 xff1a boolean xff0c string xff0c null xff0c undefined xff0c symbol xff0c bigint xff0c number 引用类型 xff1a
  • React基础

    1 Context全局值 链接地址 链接地址 目的是为了避免一些外部的传参向下传递时需要通过一层层的组件 span class token comment defaultValue只有在找不到附近的Provider时才会起作用 span s
  • git基础知识

    1 对当前commit的内容进行修正 如果发现commit的内容有问题想要修改 xff0c 正常做法可以重新再commit一次 通过amend可以直接将commit和暂存区的内容进行合并 xff0c 就不需要再重新commit一次了 ame
  • Typescript基础

    1 Pick和Omit 源码地址 相似点 xff1a 都是对接口进行剪裁 keyof 操作符常和接口结构一起使用 xff0c 得到一组对象键值的字面量类型组成的联合类型 xff0c 如 a b c 我们也常用 keyof any 表示成员未
  • Javascript基础知识整理—2

    1 节流和防抖的实现 https blog csdn net weixin 45709829 article details 123910592 防抖 Debounce 在设定的n秒内只会执行最新的函数 防抖实现 立即执行和非立即执行 sp
  • node文件系统 常用文件处理方法

    打开文件 获取文件描述符 java件描述符 xff1a 被打开的文件分配的一个简单的数字作为标识符 span class token keyword const span fs span class token operator 61 sp
  • Electron基础

    安装 span class token comment 基于Vue span span class token number 1 span 全局安装Vue脚手架 npm install span class token operator s
  • node、npm 、package.json、Angular Cli、webpack之间的关系(Windows环境下)

    IDE xff1a webstorm xff0c 已安装angular插件 Angular Cli 依赖webpack xff0c 简化创建项目流程 xff1b npm属于node一部分 xff0c npm 从package json找对应
  • node文件系统—将目标文件夹中的所有文件复制到指定目录

    span class token keyword const span fs span class token operator 61 span span class token function require span span cla
  • Great Habits of Programmer(程序员的好习惯)

    原文出处 xff1a https github com benjycui benjycui github io issues 1 Most of you heard about Refactoring Improving the Desig
  • You -- Yes, You -- Can Speak at a Conference(你 -- 是的,你 -- 可以在会议上发言)

    原文出处 xff1a https engineering appfolio com appfolio engineering 2017 1 9 you yes you can speak at a conference I ve been
  • 自制前端项目脚手架

    准备工作 xff08 一些常用库 xff09 ora 可以用于表示当前模板的状态 span class token keyword const span oraIcon span class token operator 61 span s
  • 一些奇奇怪怪的问题收集

    1 parseInt string radix span class token keyword const span arr span class token operator 61 span span class token punct
  • 微前端—qiankun:主应用和子应用之间的传值问题

    主应用给子应用传值 主应用配置 span class token comment action js span span class token comment 主应用当中将默认值提出来 xff0c 方便其他功能也要修改 span span
  • Mysql的sql优化方法

    Mysql的sql优化方法 1 选择最合适的字段属性 Mysql是一种关系型数据库 xff0c 可以很好地支持大数据量的存储 xff0c 但是一般来说 xff0c 数据库中的表越小 xff0c 在它上面执行的查询也就越快 因此 xff0c
  • 在jupyter NoteBook使用Pytorch进行MNIST实现

    34 流程 34 1 加载必要的库 import torch nn as nn import torch nn functional as F import torch import torch optim as optim from to
  • IP地址

    CIDR采用各种长度的 34 网络前缀 34 来代替分类地址中的网络号和子网号 xff0c 其格式为 xff1a IP地址 61 lt 网络前缀 gt lt 主机号 gt 为了区分网络前缀 xff0c 通常采用 34 斜线记法 34 xff
  • Snipaste截图软件的下载和使用(日常常用的一些功能)

    文章目录 前言一 如何安装二 如何使用1 开始截图2 快速复制截图3 快速将截好的图缩小4 可同时进行多个截图放在一边5 获取截图中的rgb格式颜色或16进制HEX来表示颜色6 其他 总结 前言 强烈推荐这款截图工具Snipaste xff
  • 盘符没有显示,磁盘管理器提示磁盘没有初始化(已解决)

    一 问题 插入移动硬盘 xff0c 文件资源管理器未显示对应的磁盘 xff0c 拔出硬盘重新插入也没有用 打开磁盘管理 xff0c 提示磁盘没有初始化 xff1a 二 解决方法 右击window图标 xff0c 打开磁盘管理或者计算机管理

随机推荐

  • vue3使用sse

    以下是chatgpt4对于sse技术的阐述 SSE Server Sent Events 技术是一种基于 HTTP 的推送技术 xff0c 通过一个持久性的 HTTP 连接 xff0c 服务器可以将实时数据推送给客户端 xff0c 而客户端
  • ubuntu-firefox有网但是打不开网页的解决办法

    1 检查ubuntu右上角联网开关是否打开 xff0c 需要勾选Rnable Networking 2 如果能ping通其他主机地址 xff0c 浏览器却连不上网 xff0c 很有可能是DNS域名解析的问题 解决办法如下 xff1a 查看域
  • Vue 前端笔记 采坑 | verbose stack Error: vue-element-xxx build: `vue-cli-service build`

    vue 项目 运行 npm run build 出现如下错误 xff0c 记录下来 xff0c 希望可以解答 这是在GitHub 上 找的一份项目 https github com chachaxw vue element quick st
  • Linux_CenterOS环境下JDK安装

    JDK配置 1 卸载已有的open jdk 查看目前已有的JDK rpm qa grep jdk 输出如下 copy jdk configs 3 3 10 el7 5 noarch java 1 8 0 openjdk 1 8 0 181
  • 树莓派上设置程序开机自启动

    方法一 xff1a 向rc local文件添加启动代码 修改rc local文件 xff1a sudo nano etc rc local 在打开的rc local找到exit 0 xff0c 在exit 0 之前添加一行代码 xff1a
  • smartcar仿真学习记录

    操作系统 xff1a ubuntu 18 04 ROS版本 xff1a melodic 本记录是跟随古月居的smartcar教程进行学习的 终端 文件夹下的操作 首先创建目录 也就是catkin ws src mkdir p smartca
  • 在树莓派上手动添加ROS包(usb_cam)

    在ROS下 xff0c 下载包源码编译后 xff0c 手动添加包 系统 xff1a ubuntu1804 xff08 树莓派 xff09 在树莓派上安装了ubuntu xff0c 但树莓派是arm架构 xff0c 所以用的下载源也不同于在电
  • /etc/apt/sources.list

    统一格式 xff1a deb https A B C main restricted universe multiverse deb src https A B C main restricted universe multiverse d
  • WARNING: pip is being invoked by an old script wrapper.

  • Keil 添加库文件(xxx.h)路径

  • 时间复杂度中的log(n)底数到底是多少?

    其实这里的底数对于研究程序运行效率不重要 xff0c 写代码时要考虑的是数据规模n对程序运行效率的影响 xff0c 常数部分则忽略 xff0c 同样的 xff0c 如果不同时间复杂度的倍数关系为常数 xff0c 那也可以近似认为两者为同一量
  • ubuntu1804(树莓派)使用AV接口播放音频问题

    2条消息 在运行ubuntu 18 04的树莓派上播放声音 Qrpucp的博客 CSDN博客 config txt还需加入 audio pwm mode 61 2
  • 在Modelsim内编辑testbench并重新仿真

    方法同样适用于编辑 v文件
  • 【SSH连接阿里云服务器失败解决办法】

    SSH连接阿里云服务器失败解决办法 1 添加安全组规则 找到要修改的实例 点击实例名 xff0c 进入实例详情界面 xff0c 点击 配置安全组规则 点击配置规则 添加一条如下图所示的入方向端口22 测试连接是否成功 xff0c 若不成功
  • sklearn实战-----6.聚类算法K-Means

    1 概述 1 1 无监督学习与聚类算法 在过去的五周之内 xff0c 我们学习了决策树 xff0c 随机森林 xff0c 逻辑回归 xff0c 他们虽然有着不同的功能 xff0c 但却都属于 有监督学习 的一部分 xff0c 即是说 xff
  • 过于神奇的 ChatGPT

    实在好奇究竟用的什么数据集 xff0c 居然能得到下述问答 xff1a 最后又扣回了第一个问题 按照你的要求直接给出答案 xff0c 确实很强 xff01
  • 优质 CS 读博 (PhD) 经验贴汇总

    前言 如果你对这篇文章感兴趣 xff0c 可以点击 访客必读 指引页 一文囊括主页内所有高质量博客 xff0c 查看完整博客分类与对应链接 Advice for early stage Ph D students 读博的核心是在研究上取得进
  • 推荐系统中的协同过滤算法

    前言 如果你对这篇文章感兴趣 xff0c 可以点击 访客必读 指引页 一文囊括主页内所有高质量博客 xff0c 查看完整博客分类与对应链接 概述 协同过滤是一种推荐算法 xff0c 其通常建模为 m m m 个用户 xff0c n
  • 哈希函数的学习算法整理

    前言 如果你对这篇文章感兴趣 xff0c 可以点击 访客必读 指引页 一文囊括主页内所有高质量博客 xff0c 查看完整博客分类与对应链接 概述 哈希函数学习的两个步骤 xff1a 转为二进制编码 xff1a 可以先降维成实数 xff0c
  • O(1) 的离散概率分布采样方法 - Alias Method

    前言 如果你对这篇文章感兴趣 xff0c 可以点击 访客必读 指引页 一文囊括主页内所有高质量博客 xff0c 查看完整博客分类与对应链接 Alias Method 给定一个离散概率分布 p 61 0 3