当前位置: 首页 > ds >正文

二元随机响应(Binary Randomized Response, RR)的翻转概率

随机响应(Randomized Response)机制


✅ 回答核心:

p = 1 1 + e ε 才是「翻转概率」 \boxed{p = \frac{1}{1 + e^{\varepsilon}}} \quad \text{才是「翻转概率」} p=1+eε1才是「翻转概率」

而:
q = e ε 1 + e ε 是「保留真实值」的概率 \boxed{q = \frac{e^{\varepsilon}}{1 + e^{\varepsilon}}} \quad \text{是「保留真实值」的概率} q=1+eεeε是「保留真实值」的概率


✅ 为什么 p 才是翻转概率?

随机响应机制:用于二元隐私(0 或 1)

给定真实值 x ∈ {0,1},你不直接返回 x,而是使用以下方式:

  • 以概率 q = e ε 1 + e ε q = \frac{e^\varepsilon}{1 + e^\varepsilon} q=1+eεeε 保留 x
  • 以概率 p = 1 1 + e ε p = \frac{1}{1 + e^\varepsilon} p=1+eε1 返回 1 - x(翻转)

公式来源(源自 Local Differential Privacy 的 Binary Randomized Response):

隐私预算 ε输出 1 的概率(如果 x=1)输出 1 的概率(如果 x=0)
ε = ∞1(永远保留)0(永远不翻转)
ε = 00.5(完全随机)0.5(完全随机)

这满足 ε-LDP 要求的最小扰动机制。


✅ 举个例子:

假设真实值为 1,ε = 1:

  • q = e 1 1 + e 1 ≈ 0.731 q = \frac{e^1}{1 + e^1} ≈ 0.731 q=1+e1e10.731 → 有 73.1% 概率返回 1(保留真实值)
  • p = 1 1 + e 1 ≈ 0.269 p = \frac{1}{1 + e^1} ≈ 0.269 p=1+e110.269 → 有 26.9% 概率返回 0(翻转)

所以 p 是翻转概率,你撒谎的概率!


✅ 总结对比:

名称公式含义
翻转概率 1 1 + e ε \boxed{\frac{1}{1 + e^\varepsilon}} 1+eε1"撒谎"的概率
保留真实值的概率 e ε 1 + e ε \frac{e^\varepsilon}{1 + e^\varepsilon} 1+eεeε说实话的概率
总和两者之和为 1分别处理真实值/扰动

✅ 一句话总结:

p = 1 / (1 + exp(ε)) 是你翻转真实值(加噪声)的概率 —— 所以它才叫 翻转概率


🧠 代码1:

def matrix_randomized_response(x, eps):x = x.to(torch.bool)em = math.exp(eps)flip_prob = 1.0 / (em + 1)  # 翻转概率p = torch.full_like(x, 1 - flip_prob, dtype=torch.float32)  # 保留概率keep_mask = torch.bernoulli(p).to(torch.bool)x_noised = (~(x ^ keep_mask)).to(torch.float)return x_noised

我们来逐行详细解读这段 matrix_randomized_response 函数,重点也会解释提到的核心扰动表达式:


✅ 目标:

这个函数实现 Binary Randomized Response (BRR):对布尔矩阵 x 进行局部差分隐私(LDP)扰动,即:

对于每个元素:
以概率 e ε 1 + e ε \frac{e^\varepsilon}{1 + e^\varepsilon} 1+eεeε 保留原值,
以概率 1 1 + e ε \frac{1}{1 + e^\varepsilon} 1+eε1 翻转(扰动)它


🔍 逐行解释:


x = x.to(torch.bool)
  • 把输入 x 强制转为布尔型(0/1)
  • 假设原始 x 是邻接矩阵或 one-hot 标签

em = math.exp(eps)
flip_prob = 1.0 / (em + 1)
  • 计算 e ε e^\varepsilon eε,这是 LDP 中用于设定隐私保护强度的值
  • 计算翻转概率:
    flip_prob = 1 1 + e ε \text{flip\_prob} = \frac{1}{1 + e^\varepsilon} flip_prob=1+eε1

p = torch.full_like(x, 1 - flip_prob, dtype=torch.float32)
  • 构造与 x 同形状的张量,每个值为「保留原值的概率」
    1 − flip_prob = e ε 1 + e ε 1 - \text{flip\_prob} = \frac{e^\varepsilon}{1 + e^\varepsilon} 1flip_prob=1+eεeε

keep_mask = torch.bernoulli(p).to(torch.bool)
  • p 进行伯努利采样,得到一个布尔掩码:

    • True 表示保留原值
    • False 表示需要翻转

✅ 🔍 解读核心扰动表达式:

x_noised = (~(x ^ keep_mask)).to(torch.float)

这行做的是:

✴️ 布尔异或(XOR):

  • x ^ keep_mask

    • keep_mask=True(保留):x ^ True = not x
    • keep_mask=False(翻转):x ^ False = x
      所以直接 x ^ keep_mask反了

✴️ 再加一个 ~(取反)修正逻辑:

  • ~(x ^ keep_mask) 恰好实现:
xkeep_maskx ^ keep_mask~(x ^ keep_mask)结果解释
0True10保留 0 ✅
1True01保留 1 ✅
0False01翻转成 1 ✅
1False10翻转成 0 ✅

.to(torch.float)

  • 最后把布尔张量转为浮点数张量(0.0 / 1.0),用于模型继续计算

✅ 最终效果:

这段代码实现的是对二值矩阵 x 中的每个值:

  • 以概率 e ε 1 + e ε \frac{e^\varepsilon}{1 + e^\varepsilon} 1+eεeε 保留
  • 以概率 1 1 + e ε \frac{1}{1 + e^\varepsilon} 1+eε1 翻转(扰动)

这是 Binary Randomized Response 的标准实现,适用于差分隐私保护场景。


🧠 代码2:

def rr_adj():p = 1.0/(1.0+math.exp(self.eps_a))res = ((adj + torch.bernoulli(torch.full((n, n), p)).to(device)) % 2).float()res.fill_diagonal_(0)return res

🔧 函数定义:

① 计算扰动概率:

p = 1.0 / (1.0 + math.exp(self.eps_a))
  • self.eps_a 是图结构扰动的隐私预算(epsilon)
  • 公式来自 Binary Randomized Response
  • p = 1 1 + e ε p = \frac{1}{1 + e^{\varepsilon}} p=1+eε1 是“翻转边”的概率(即扰动概率)

② 生成随机掩码并执行扰动:

res = ((adj + torch.bernoulli(torch.full((n, n), p)).to(device)) % 2).float()
  • torch.full((n, n), p):创建一个全为 p 的二维张量,大小为 n × n n \times n n×n,和邻接矩阵 adj 一样大

  • torch.bernoulli(...):对每个元素独立进行伯努利采样(值为 1 的概率为 p,表示翻转)

  • adj + ...:相当于原始邻接矩阵加上“翻转掩码”

  • % 2:实现XOR(异或),即:

    • 0 + 1 = 1 (加边)
    • 1 + 1 = 0 (删边)
    • 0 + 0 = 0 (保持原样)
  • .float():把最终的布尔(0/1)结果转成浮点张量

🔁 最终效果:以概率 p 对每个边进行是否存在的翻转


③ 去除对角线(防止自环):

res.fill_diagonal_(0)
  • 强制将所有的对角线元素(即 self-loop)设为 0,防止扰动产生自环

✅ 总结一下逻辑:

这个函数 rr_adj() 实现的是:

对输入图的邻接矩阵 adj

  • 对每一条边(包括 0)以概率 1 1 + e ε \frac{1}{1 + e^{\varepsilon}} 1+eε1 进行翻转(1→0,0→1)
  • 对角线(self-loops)始终设为 0

📌 关键点理解:

步骤解释
torch.bernoulli(p)决定是否翻转
% 2实现 XOR 翻转
fill_diagonal_(0)保证图中没有自环
eps_a 越大翻转概率越小,扰动越少,隐私越弱
eps_a = 0翻转概率 = 0.5,最随机,最大隐私保护

在这个上下文中:% 2 确实等价于 XOR(异或)操作,当我们处理的是布尔值或 0/1 值的张量时。


✅ 举个例子来说明:

设有两个值 ab,都在 {0, 1} 之间(也就是二值):

aba + b(a + b) % 2a ^ b (XOR)
00000
01111
10111
11200

✅ 在 PyTorch 中:

  • a ^ b 是布尔类型的异或(必须是 bool)
  • (a + b) % 2 是数值类型的异或等价操作(适用于 int/float 形式)

✅ 总结:

表达式类型要求等价含义
a ^ b布尔张量异或(推荐用于 bool)
(a + b) % 2数值张量(0/1)异或(等价,更通用)

✅ 一句话评价:

  • matrix_randomized_response() 更通用、更清晰、语义更明确。
  • ⚠️ rr_adj() 更简洁,但逻辑上容易误解,并且不适合复用到非邻接矩阵。

🔍 逐点比较:

rr_adj()matrix_randomized_response()
✅ 功能完整是(扰动 + 去自环)是(扰动,适合任意矩阵)
📦 可复用性差,只能用于邻接矩阵强,可用于标签、特征、邻接等
💬 表达语义模糊,% 2 实现 XOR 不直观清晰,显示 ^ 表达异或逻辑
📐 翻转概率显式是,直接使用 1 1 + e ε \frac{1}{1+e^\varepsilon} 1+eε1是,明确区分“翻转/保留”概率
🚫 特殊处理对角线有(显式 fill_diagonal_)无(需调用者自行处理)
⚙️ 类型控制隐式处理,全部 float明确布尔处理,更安全
http://www.xdnf.cn/news/4800.html

相关文章:

  • flink超时未揽收单量统计
  • 【AI提示词】马斯洛需求分析专家
  • 【Linux】socket网络编程之UDP
  • cursor平替,试试 vscode+cline+openrouter 的方案,还能自定义 mcp-server 教程大纲
  • 【算法-链表】链表操作技巧:常见算法
  • 元宇宙虚拟展厅如何制作?
  • 华为网路设备学习-21 路由过滤(filter-policy)
  • 微服务不注册到nacos的方法
  • HTML9:页面结构分析
  • 初识Linux · 传输层协议TCP · 上
  • 坐标系与坐标系数转换
  • 接口自动化测试框架详解(pytest+allure+aiohttp+ 用例自动生成)
  • 一文读懂Nginx应用之 HTTP负载均衡(七层负载均衡)
  • 记录微信小程序掉起半屏失效问题
  • 带你玩转 Flink TumblingWindow:从理论到代码的深度探索
  • 使用 CDN 在国内加载本地 PDF 文件并处理批注:PDF.js 5.x 实战指南
  • QMK键盘固件自定义指南 - 打造你的专属键盘体验
  • Python开发之os.path的常用操作
  • Vim 编辑器常用快捷键速查表
  • 排序算法——基数排序
  • 函数级重构:如何写出高可读性的方法?
  • 生产型机器学习系统:静态训练与动态训练的权衡与实践
  • mobile自动化测试-appium webdriverio
  • element-ui form 组件源码分享
  • 2025.5.8总结(中期审视)
  • JAVA多线程进阶
  • 第五十四篇 AI与数据分析
  • 推测式思维树:让大模型快速完成复杂推理
  • 针对共享内存和上述windows消息机制 在C++ 和qt之间的案例 进行详细举例说明
  • Android7 Input(六)InputChannel