- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
本文其实还是信概 report, 所以写得比较严肃 qwq. 。
概率数据结构 (Probabilistic Data Structure, PDS) 是一种依赖随机性质来获取相较确定性数据结构更优秀的时空效率的数据结构. 其核心要义是通过允许对询问的回答以一定的概率错误, 来极大地简化存储或计算成本. 当对答案的精确性要求不高, 或者精确答案的求解开销过大时, PDS 是一种适合的解决手段. 其在大数据和大模型等领域有较多的应用. 。
本文试介绍 Bloom Filter, Four-colored Filter 和 Fermat Sketch, 前者是经典的 PDS, 后两者或许相对少见; 最后略作思考补充. 由于相关资料 (或者笔者的论文检索能力) 有限, 对 Four-colored Filter 和 Fermat Sketch 的介绍只基于信概课程的粗略笔记, 再由笔者重新推导成形, 可能有偏颇错漏, 还望批评指正. 。
Bloom Filter 是一种经典的 PDS, 它可以用于处理以下问题
问题 1.1 。
给定集合 \(S\), 回答若干次询问, 每次询问给出元素 \(x\), 回答是否有 \(x\in S\). 。
传统做法无非是使用 hash table 或者平衡树. 在数据量极大时, 它们都有较大的开销. 。
算法 1.2 (Bloom Filter) 对 问题 1.1, 选定 hash 函数值域 \([0:m-1]\) 和 \(k\) 个不同且相互独立的 hash 函数 \(\{h_k\}\) 来维护一个长为 \(m\), 初始全 \(0\) 的 bit array, 以支持对 \(S\) 的元素插入和在线查询. 。
- 插入元素 \(x\) 时: 将 bit array 中 \(h_1(x),\cdots,h_k(x)\) 位置对应的 bit 全部置为 \(1\).
- 查询元素 \(y\) 时: 检查 bit array 中 \(h_1(y),\cdots,h_k(y)\) 位置对应的 bit 是否全部为 \(1\). 若全为 \(1\), 回答 "\(y\overset{?}\in S\)", 否则回答 "\(y\notin S\)".
容易看出, Bloom Filter 只可能给出假阳性结果. 即, 若 Bloom Filter 认为 \(y\notin S\), 则 \(y\notin S\) 事实上一定成立; 若 Bloom Filter 认为 \(y\overset{?}\in S\), 事实上不一定有 \(y\in S\), 因为 \(h_1(y),\cdots,h_k(y)\) 这些 bit 可能被其他元素的 hash 值命中, 而产生错误. 。
为了平衡效率和正确率, 我们需要对 \(m\) 和 \(k\) 进行适当调节. 作为例子, 这里仅考察 \(m\) 和 \(|S|=n\) 固定时对 \(k\) 的选取, 同时假设 hash 函数的取值皆均匀随机. 在 \(n\) 个元素插入完成后, 单个 bit 处于 \(0\) 的概率为 \(p_0=\br{1-\frac{1}{m}}^{kn}\). 在 \(m\) 充分大时, 根据 。
可化简得 。
则 Bloom Filter 的假阳性概率可以估计为 。
令 \(q=n/m\), 那么 。
令 \(t=e^{-kq}\), 则 \(kq=-\ln t\); 令导数取 \(0\), 则在极值点处有 。
其中 \(t\in(0,1)\), 由单调性不难看出当且仅当 \(t=\frac{1}{2}\) 时取等. 这时 。
此外, 在给定期待的误差率 \(\eps\) 时, 也能给出相应的 \(m\) 选取, 相关计算这里略去. 经此例可以看出, 诸如 Bloom Filter 这样的 PDS 内部具有较大的自由度, 因此有必要针对参数优化问题 (甚至结合硬件效率, 成本等因素) 进行充分的数学处理. 。
在某种意义上, Four-colored Filter 是在一个限制更强的集合判属问题上对 Bloom Filter 的扩展. 。
问题 2.1 。
给定 \(n\) 个无交集 \(\seq S1n\), 设 \(S=\bigsqcup_{i=1}^n S_i\). 回答若干次询问, 每次询问给定元素 \(x\in S\), 回答包含该元素的集合标号 \(k\) (即存在且唯一的一个 \(k\) 使得 \(S_k\ni x\)). 。
暂不谈实现时的内存效率, 我们可以通过二分或者二进制分组将 问题 2.1 转化为一个更简单的问题
问题 2.2 。
给定 \(n=2\) 个无交集 \(S^+,S^-\), 设 \(S=S^+\sqcup S^-\). 回答若干次询问, 每次询问给定元素 \(x\in S\), 判断是否 \(x\in S^+\). 。
问题 2.2 明显不强于 问题 1.1, 因此可以使用 Bloom Filter 解决: 对 \(S^+\) (或 \(S^-\)) 建立 Bloom Filter, 查询是否有 \(x\in S^+\) (或 \(x\in S^-\)) 即可得到 问题 2.2 解决方法. 然而, Bloom Filter 无法利用 \(x\in S=S^+\sqcup S^-\) 这一信息, 而 Four-colored Filter 则是充分利用这一点来对算法进行了改进. 。
算法 2.3 (Four-colored Filter) 。
对 问题 2.2, 取定 hash 值域 \(n\) 和 hash 函数 \(h:S\to[1:n]^2\), 以此生成无向图 \(G=(V,E)\), 其中 \(V:=[1:n]\).
\[E^+:=\{(u,v,+):(u,v)\in h(S^+)\},\quad E^-:=\{(s,t,-):(s,t)\in h(S^-)\};\\ E:=E^+\sqcup E^-. \]称 \(E^+\) 的元素为实边, \(E^-\) 的元素为虚边. 不妨 \(|S^+|\ge|S^-|\), 反复尝试构造四染色 \(c:V\to\{0,1,2,3\}\), 满足 。
- 实边异色: \(\A(u,v,+)\in E^+,~c(u)\neq c(v)\);
- 虚边同色: \(\A(s,t,-)\in E^-,~c(u)=c(v)\).
若成功得到 \(c\), 则 Four-colored Filter 建立完成. 此后 。
- 查询元素 \(y\) 时: 计算 \(h(y)=(a,b)\), 若 \(c(a)=c(b)\), 则 \(y\in S^-\), 否则 \(y\in S^+\).
- (若要求 Four-colored Filter 在线) 插入元素 \(x\) 时: 在原图基础上加入 \(x\) 对应的实边或虚边, 并从其两端出发搜索调整染色方案直到 \(c\) 再次合法.
相比于 Bloom Filter, 一旦 Four-colored Filter 成功建立, 它的回答都一定是快速且完全正确的, 它适合用于应对对固定数据的大规模查询. 不过, 由于 4-coloring 问题是 NPC 的, 对 \(c\) 的寻找必然依赖于随机性算法. 此外, \(h\) 给出的 \(G\) 本身可能带有明显的矛盾: 若虚边连通块中出现了实边, 则 \(c\) 不可能存在, 这要求我们对 \(h\) 的随机选取或调整. 事实上, 制定染色策略时认定 \(|S^+|\ge|S^-|\) 也正是因此: 大量的同色连边倾向于在 \(G\) 中形成一个巨大的连通块, 且此连通块在缩点后的度数较大, 二者分别容易导致块内和块外的染色不存在; 将较小的 \(E^-\) 作为同色边则倾向于让 \(G\) 的连通块和缩点后度数更加均匀, 更容易成功染色. 。
笔者认为值得探索的地方
所谓 "sketch", 即 "草图", 指的是对数据的一种压缩存储方式. Fermat Sketch 试图解决以下问题
问题 3.1 。
假设云端向本地用户传输了若干份数据包, 每个数据包有相应的 ID 和包数. 传输完成后, 要求云端向本地附带一则 sketch 信息, 帮助用户检查传输完整性 (是否丢包, 有哪几份数据包发生丢包). 。
我们可以将 (ID, 包数) 集合视为一个关于 ID 的可重集, 目标便是对两个可重集进行快速比较, 尽可能地描述出它们的差异. 。
算法 3.2 (Fermat Sketch) 。
对 问题 3.1, 设 ID 的值域 \(I=[1:m]\), 总包数 \(q\). 选定 hash 范围 \(n\), 两个 hash 函数 \(f,g:I\to[1:n]\) 和素数 \(p>\max\{m,q\}\). 定义一个 Abel 群 \(G=(\F_p\x\Z,+)\), 其中 。
\[+:(u,a)\mapsto (v,b)\mapsto (u+_{\F_p}v,a+_\N b). \]本地和云端分别维护两份 sketch \(\{s_i\}_{i=1}^n,\{t_i\}_{i=1}^n\), 其中 \(s_i,t_i\in G\). 当接收到 ID 为 \(i\) 的包时, 令 。
\[s_{f(i)}\gets s_{f(i)}+(i,1),\quad t_{g(i)}\gets t_{g(i)}+(i,1). \]传输完成后, 云端将自己的两份 sketch 提供给本地. 不妨设此时云端 sketch 为 \(\{s_i\},\{t_i\}\), 本地 sketch 为 \(\{s_i'\},\{t_i'\}\). 接下来, 不断寻找下标 \(i\) 使得 \(s_i\neq s_i'\) 或者 \(t_i\neq t_i'\), 不妨设找到某个 \(s_i\neq s_i'\), 计算 。
\[(w,c):=s_i-s_i',\quad i_?:=w\x c^{-1}\in\F_p. \]检查是否有 \(f(i_?)=i\) (rehash verification), 讨论
若是, 相信 \((w,c)\) 恰好描述了 ID 为 \(i_?\) 的包的本地-云端差异. 此时 \(c\) 就是差异数量. 此后在本地 sketch 中消除此差异, 令 。
\[s_i'\gets s_i,\quad t_{g(i_?)}'\gets t_{g(i_?)}'+(i,c). \]否则, 忽略这个 \(i\), 寻找其他的 \(i\). 。
如果一切 \(s_i=s_i'\) 且 \(t_i=t_i'\), Fermat Sketch 便认为成功找出了所有差异; 否则若找不到任何一个合适的 \(i\), 则认为 Fermat Sketch 的搜索失败. 。
可以感知到, 用两个 hash 维护两份 sketch 的目的是让 "消除差异" 变得可能: 例如某处 \(s_i\) 的 hash 冲突导致无法通过 \(s_i\) 还原差异, 我们还有 \(t_i\) 能提供线索; 如果某处 \(s_i\) 可以用作还原差异, 它也能为对应的 \(t_{g(i_?)}\) 提供修正, 如此迭代便提高了顺利找出所有差异的概率. 。
如果希望提高 rehash verification 的置信度, 只需要对每个 ID 附带上随机指纹 \(\textit{fp}\in\F_p\), 参与与 ID 相同的运算, rehash 时顺便比较随机指纹即可. 。
本文尚有大量未提及的经典 PDS, 例如 Count-min Sketch, Universal Sketch 等. PDS 在诸多计算机领域有所应用, 如垂直领域大模型的检索增强生成, 缓存替换策略等, 不一而足. 。
笔者认为, PDS 有很大的研究价值. 理论上, 一切问题都可以通过附带一个 "错误接受程度" 来引入 PDS; 工业上, 大多数问题都并不要求精确求解, 因此 PDS 具有很强的普适性和实用性. 受 Four-colored Filter 的启发, 笔者猜测一种可能的研究方向是将某些问题先映射到一个 NPC 但足以提供良好性质的问题上, 进而借助已有的对 NPC 问题的丰富研究来设计更多 PDS. 。
References 。
最后此篇关于Report-「概率数据结构」随机化骗分?我们是专业的!的文章就讲到这里了,如果你想了解更多关于Report-「概率数据结构」随机化骗分?我们是专业的!的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我让随机数低于之前的随机数。 if Airplane==1: while icounter0: print "You have enoph fuel to get to New
是否可以生成 BigFloat 的随机数?类型均匀分布在区间 [0,1)? 我的意思是,因为 rand(BigFloat)不可用,看来我们必须使用 BigFloat(rand())为了那个结局。然而,
我正在尝试学习 Kotlin,所以我正在学习互联网上的教程,其中讲师编写了一个与他们配合良好的代码,但它给我带来了错误。 这是错误 Error:(26, 17) Kotlin: Cannot crea
是否有任何方法可以模拟 Collections.shuffle 的行为,而不使比较器容易受到排序算法实现的影响,从而保证结果的安全? 我的意思是不违反类似的契约(Contract)等.. 最佳答案 在
我正在创建一个游戏,目前必须处理一些math.random问题。 我的Lua能力不是那么强,你觉得怎么样 您能制定一个使用 math.random 和给定百分比的算法吗? 我的意思是这样的函数: fu
我想以某种方式让按钮在按下按钮时随机改变位置。我有一个想法如何解决这个问题,其中一个我在下面突出显示,但我已经认为这不是我需要的。 import javafx.application.Applicat
对于我的 Java 类(class),我应该制作一个随机猜数字游戏。我一直陷入过去几天创建的循环中。程序的输出总是无限循环,我不明白为什么。非常感谢任何帮助。 /* This program wi
我已经查看了涉及该主题的一些其他问题,但我没有在任何地方看到这个特定问题。我有一个点击 Web 元素的测试。我尝试通过 ID 和 XPath 引用它,并使用 wait.until() 等待它变得可见。
我在具有自定义类的字典和列表中遇到了该异常。示例: List dsa = (List)Session["Display"]; 当我使用 Session 时,转换工作了 10-20 次..然后它开始抛
需要帮助以了解如何执行以下操作: 每隔 2 秒,这两个数字将生成包含从 1 到 3 的整数值的随机数。 按下“匹配”按钮后,如果两个数字相同,则绿色标签上的数字增加 1。 按下“匹配”按钮后,如果两个
void getS(char *fileName){ FILE *src; if((src = fopen(fileName, "r")) == NULL){ prin
如果我有 2 个具有以下字段的 MySQL 数据库... RequestDB: - Username - Category DisplayDB: - Username - Category
我有以下语句 select random() * 999 + 111 from generate_series(1,10) 结果是: 690,046183290426 983,732229881454
我有一个使用 3x4 CSS 网格构建的简单网站。但出于某种原因,当我在 chrome“检查”中检查页面时,有一个奇怪的空白 显然不在我的代码中的标签。 它会导致网站上出现额外的一行,从而导致出现
我有两个动画,一个是“过渡”,它在悬停时缩小图像,另一个是 animation2,其中图像的不透明度以周期性间隔重复变化。 我有 animation2 在图像上进行,当我将鼠标悬停在它上面时,anim
如图所示post在 C++ 中有几种生成随机 float 的方法。但是我不完全理解答案的第三个选项: float r3 = LO + static_cast (rand()) /( static_c
我正在尝试将类添加到具有相同类的三个 div,但我不希望任何被添加的类重复。 我有一个脚本可以将一个类添加到同时显示的 1、2 或 3 个 div。期望的效果是将图像显示为背景图像,并且在我的样式表中
我有一个基本上可以工作的程序,它创建由用户设置的大小的嵌套列表,并根据用户输入重复。 但是,我希望各个集合仅包含唯一值,目前这是我的输出。 > python3 testv.py Size of you
我正在尝试基于 C# 中的种子生成一个数字。唯一的问题是种子太大而不能成为 int32。有什么方法可以像种子一样使用 long 吗? 是的,种子必须很长。 最佳答案 这是我移植的 Java.Util.
我写这个函数是为了得到一个介于 0 .. 1 之间的伪随机 float : float randomFloat() { float r = (float)rand()/(float)RAN
我是一名优秀的程序员,十分优秀!