Report -「概率数据结构」随机化骗分?我们是专业的!

news/2025/1/9 19:30:30/文章来源:https://www.cnblogs.com/rainybunny/p/18662683

\[\mathscr{Lorain~y~w~la~Lora~blea.}\newcommand{\DS}[0]{\displaystyle}% operators alias \newcommand{\opn}[1]{\operatorname{#1}} \newcommand{\card}[0]{\opn{card}} \newcommand{\lcm}[0]{\opn{lcm}} \newcommand{\char}[0]{\opn{char}} \newcommand{\Char}[0]{\opn{Char}} \newcommand{\Min}[0]{\opn{Min}} \newcommand{\rank}[0]{\opn{rank}} \newcommand{\Hom}[0]{\opn{Hom}} \newcommand{\End}[0]{\opn{End}} \newcommand{\im}[0]{\opn{im}} \newcommand{\tr}[0]{\opn{tr}} \newcommand{\diag}[0]{\opn{diag}} \newcommand{\coker}[0]{\opn{coker}} \newcommand{\id}[0]{\opn{id}} \newcommand{\sgn}[0]{\opn{sgn}} \newcommand{\cent}[0]{\u{\degree C}}% symbols alias \newcommand{\E}[0]{\exist} \newcommand{\A}[0]{\forall} \newcommand{\l}[0]{\left} \newcommand{\r}[0]{\right} \newcommand{\eps}[0]{\varepsilon} \newcommand{\Ra}[0]{\Rightarrow} \newcommand{\Eq}[0]{\Leftrightarrow} \newcommand{\d}[0]{\mathrm{d}} \newcommand{\oo}[0]{\infty} \newcommand{\mmap}[0]{\hookrightarrow} \newcommand{\emap}[0]{\twoheadrightarrow} \newcommand{\lin}[0]{\lim_{n\to\oo}} \newcommand{\linf}[0]{\liminf_{n\to\oo}} \newcommand{\lsup}[0]{\limsup_{n\to\oo}} \newcommand{\F}[0]{\mathbb F} \newcommand{\x}[0]{\times} \newcommand{\M}[0]{\mathbf{M}} \newcommand{\T}[0]{\intercal}% symbols with parameters \newcommand{\der}[1]{\frac{\d}{\d #1}} \newcommand{\ul}[1]{\underline{#1}} \newcommand{\ol}[1]{\overline{#1}} \newcommand{\br}[1]{\l(#1\r)} \newcommand{\abs}[1]{\l|#1\r|} \newcommand{\bs}[1]{\boldsymbol{#1}} \newcommand{\env}[2]{\begin{#1}#2\end{#1}} % why not? \newcommand{\pmat}[1]{\env{pmatrix}{#1}} \newcommand{\dary}[2]{\l|\begin{array}{#1}#2\end{array}\r|} \newcommand{\pary}[2]{\l(\begin{array}{#1}#2\end{array}\r)} \newcommand{\pblk}[4]{\l(\begin{array}{c|c}{#1}&{#2}\\\hline{#3}&{#4}\end{array}\r)} \newcommand{\u}[1]{\mathrm{#1}} \newcommand{\lix}[1]{\lim_{x\to #1}} \newcommand{\ops}[1]{#1\cdots #1} \newcommand{\seq}[3]{{#1}_{#2}\ops,{#1}_{#3}} \newcommand{\dedu}[2]{\u{(#1)}\Ra\u{(#2)}} \]

  本文其实还是信概 report, 所以写得比较严肃 qwq.

  概率数据结构 (Probabilistic Data Structure, PDS) 是一种依赖随机性质来获取相较确定性数据结构更优秀的时空效率的数据结构. 其核心要义是通过允许对询问的回答以一定的概率错误, 来极大地简化存储或计算成本. 当对答案的精确性要求不高, 或者精确答案的求解开销过大时, PDS 是一种适合的解决手段. 其在大数据和大模型等领域有较多的应用.

  本文试介绍 Bloom Filter, Four-colored Filter 和 Fermat Sketch, 前者是经典的 PDS, 后两者或许相对少见; 最后略作思考补充. 由于相关资料 (或者笔者的论文检索能力) 有限, 对 Four-colored Filter 和 Fermat Sketch 的介绍只基于信概课程的粗略笔记, 再由笔者重新推导成形, 可能有偏颇错漏, 还望批评指正.

\(1\) Bloom Filter

  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\) 充分大时, 根据

\[\lim_{m\to\oo}\br{1-\frac{1}{m}}^m=\frac{1}{e}, \]

可化简得

\[p_0\approx e^{-kn/m}. \]

则 Bloom Filter 的假阳性概率可以估计为

\[\eps\approx(1-p_0)^k\approx\br{1-e^{-kn/m}}^k. \]

\(q=n/m\), 那么

\[\ln\eps=k\ln\br{1-e^{-kq}}\\ \Ra \frac{\d \ln\eps}{\d k}=\ln\br{1-e^{-kq}}+\frac{kqe^{-kq}}{1-e^{-kq}}. \]

\(t=e^{-kq}\), 则 \(kq=-\ln t\); 令导数取 \(0\), 则在极值点处有

\[\ln(1-t)-\frac{t\ln t}{1-t}=0\Eq (1-t)\ln(1-t)=t\ln t. \]

其中 \(t\in(0,1)\), 由单调性不难看出当且仅当 \(t=\frac{1}{2}\) 时取等. 这时

\[e^{-kn/m}=\frac{1}{2}\Ra k=\frac{m}{n}\ln2 . \]

  此外, 在给定期待的误差率 \(\eps\) 时, 也能给出相应的 \(m\) 选取, 相关计算这里略去. 经此例可以看出, 诸如 Bloom Filter 这样的 PDS 内部具有较大的自由度, 因此有必要针对参数优化问题 (甚至结合硬件效率, 成本等因素) 进行充分的数学处理.

\(2\) Four-colored Filter

  在某种意义上, 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\) 的连通块和缩点后度数更加均匀, 更容易成功染色.

  笔者认为值得探索的地方:

  1. \(n\) 的选取. 从信息熵粗略估计, 当 \(n=\sqrt{|S|/2}\) 时就已经能够无损地存放 \(S^+\)\(S^-\) 的信息. 一般实现的时候取的是 \(n=|S|\) (此处存疑), 这是否有必要?
  2. 染色数 \(k\) 的选取. 我们直接承认了 \(k=4\), 这是因为 \(k\) 更小时染色难以完成, \(k\) 更大时会带来更大空间开销. 如何更细致地描述并推导 \(k\) 的选取?

\(3\) Fermat Sketch

  所谓 "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 时顺便比较随机指纹即可.

\(4\) 补充与思考

  本文尚有大量未提及的经典 PDS, 例如 Count-min Sketch, Universal Sketch 等. PDS 在诸多计算机领域有所应用, 如垂直领域大模型的检索增强生成, 缓存替换策略等, 不一而足.

  笔者认为, PDS 有很大的研究价值. 理论上, 一切问题都可以通过附带一个 "错误接受程度" 来引入 PDS; 工业上, 大多数问题都并不要求精确求解, 因此 PDS 具有很强的普适性和实用性. 受 Four-colored Filter 的启发, 笔者猜测一种可能的研究方向是将某些问题先映射到一个 NPC 但足以提供良好性质的问题上, 进而借助已有的对 NPC 问题的丰富研究来设计更多 PDS.


References

  1. 《信息科学技术概论》2024/09/13 课程内容 (by 杨仝老师).
  2. https://en.wikipedia.org/wiki/Bloom_filter

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/866692.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA-Day 09:While循环语句

While循环 while循环格式 初始化语句; while(条件判断语句){ 循环体语句; 条件控制语句; } 初始化语句只执行一次 判断语句为True,循环继续 判断语句为False,循环结束 例: 世界最高山峰珠穆朗玛峰的高度为8844.43米=8844430毫米,假如有 一张足够大的纸,它的厚度为0.1毫米。…

rust学习十六.2、并发-利用消息传递进行线程间通讯

通过信道是rust的解决线程之间通信的2个工具之一,另外1个是是共享内存状态。 rust推出这个,明显地是因为受到go之类的影响。 在书籍中,作者提到go编程文档中的内容: 不要通过共享内存来通讯;而是通过通讯来共享内存(Do not communicate by sharing memory; instead, share…

2025,谁会成为 AI Agent 的新入口?|播客《编码人声》

「编码人声」是由「RTE开发者社区」策划的一档播客节目,关注行业发展变革、开发者职涯发展、技术突破以及创业创新,由开发者来分享开发者眼中的工作与生活。2024 年末,一群来自 Android、Chrome OS、Oculus 等操作系统的开发元老联合创业,推出 AI Agent 操作系统 /dev/agen…

【Windows内核】Ntdll解除挂钩学习

简介 我们之前都是直接通过使用直接系统调用的方式来绕过用户态钩子,通过在项目文件中创建并调用系统调用来实现此目标。还有另外一种方法也可以绕过用户态的钩子,那么这种方法是将已经加载到进程中的钩子DLL替换为一个未经修改且未被钩主的版本来达到相同的目标。 将勾住的D…

21. 主窗口控件

一、主窗口控件之前,我们使用可视控件创建具体的实例时都选择了一个父窗体,将控件放到这个窗体上,即使在创建实例时没有选择父窗体,也可以用控件的 setParent() 方法将控件放到父窗体上。如果一个控件没有放到任何窗体上,则这个控件可以单独成为窗口,并且可以作为父窗口来…

智慧帮手:一站式搭建帮助中心,优化客户服务体验

在数字化时代,客户服务已成为企业赢得市场、留住客户的关键。一个高效、便捷的帮助中心,不仅能够快速响应客户需求,还能提升客户满意度和忠诚度。然而,如何搭建一个既满足客户需求又符合企业特色的帮助中心,成为众多企业面临的挑战。本文将探讨如何借助一站式解决方案,如…

解锁餐饮新篇:精准搭建内部知识库,赋能高效运营

在当今竞争激烈的餐饮行业中,提升运营效率和服务质量已成为企业脱颖而出的关键。随着餐饮业务的不断扩展,内部信息管理和知识传承成为了一大挑战。如何构建一个高效、精准的内部知识库,成为解锁餐饮新篇章的重要一环。本文将探讨如何借助智能化工具,如HelpLook,实现这一目…

【YashanDB知识库】进行load data的时候报找不到动态库liblz4.so

本文内容来自YashanDB官网,原文内容请见 https://www.yashandb.com/newsinfo/7863047.html?templateId=1718516 现象 23.2版本的依赖项准备里指明,要依赖动态库:liblz4.so,liblz4.so.1,liblz4.so.1.9.3 在执行load data的时候报找不到动态库liblz4.so 操作系统在/lib64/目…

JAVA-Day 08:For循环语句

For循环 For循环格式 for循环语句格式 for(初始化语句;条件判断语句;条件控制语句){ 循环语句体; } 执行流程: 1、执行初始化语句 2、执行条件判断语句,看其结果是True还是False,如果是True,执行循语句体,如果是False,循环结束 3、执行条件控制语句 4、回到2继续执行条件判…

记录---JS 的蝴蝶效应 —— 事件流

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣前言 在 JavaScript 的世界里,事件流就像一只永不停歇的蝴蝶,每一个动作、每一个点击、每一个滚动,都会触发一连串的蝴蝶效应。作为一名开发者,掌握事件流的艺术,不仅能让你的网页更加生动、更加交互,也能让用户体验…

HTTPS 加密机制

HTTPS 概述 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。…

leetcode131 分割回文串

leetcode 131思路:回溯 比如说aab,对于每个元素currentNum,有两种选择: 1.如果currentNum<len-1,可以将当前元素加入到currentStr中,然后dfs(start,currentNum+1)。而currentNum==len-1时不能dfs(start,currentNum+1),这样下一轮循环就执行以下代码了 if (currentNum…