PrivKV: Key-Value Data Collection with Local Differential Privacy论文阅读
文献阅读课需要制作ppt但是感觉选的这篇论文都是公式,决定做点动画直观展示一下。还没有完成会继续更新这个笔记
manim动画代码
- 需要下载ffmpeg
- 下载latex
https://docs.manim.org.cn/getting_started/installation.html
ffmpeg下载教程
texlive官网
但是其实不需要这两样也可以播放只是很丑陋。。。
论文的ppt做好了不知道怎么上传,后续整理成笔记完善一下这篇blog
概念 | 定义 | 噪声添加方式 | 优势 | 劣势 | ε 相关性 |
---|---|---|---|---|---|
差分隐私(DP,含 CDP) | 保护查询结果不泄露个体数据,通过中心化添加噪声 | 在查询结果或中间计算中添加噪声 | 提供严格数学隐私保证,数据效用较高,适合有可信中心的场景 | 需要信任数据收集者,存在数据泄露风险 | ε 小则隐私强,数据效用可能低 |
本地差分隐私(LDP) | 用户本地扰动数据后再发送,无需可信第三方 | 每个数据点独立添加噪声 | 无需信任中心,增强隐私,用户控制数据,适合分布式架构 | 数据效用低,需较多用户参与,准确性通常低于 DP | 常需高 ε 以平衡实用性 |
集中式差分隐私(CDP) | 可信管理者收集数据后添加噪声发布结果 | 在聚合数据后添加噪声 | 数据效用较高,适合需要高准确度的场景 | 需要信任管理者,存在单点故障风险 | 与 DP 类似,ε 影响隐私与效用 |
from manim import *
import numpy as npclass LDPIntroduction(Scene):def construct(self):# 标题title = Text("本地差分隐私 (Local Differential Privacy)", font_size=40)title.to_edge(UP)self.play(Write(title))self.wait(1)# 传统数据收集 vs LDPtraditional = VGroup()ldp = VGroup()# 图标和节点 - 使用几何图形代替SVGuser_icon = VGroup(Circle(radius=0.3, color=BLUE, fill_opacity=0.8),Circle(radius=0.1, color=BLUE, fill_opacity=0.8).shift(UP*0.05),Arc(start_angle=3.14/6, angle=3.14*2/3, radius=0.15, color=BLUE, fill_opacity=0.8).shift(DOWN*0.1))server_icon = VGroup(Rectangle(height=0.6, width=0.8, color=GREEN, fill_opacity=0.8),Line(LEFT*0.2, RIGHT*0.2, color=GREEN).shift(UP*0.1),Line(LEFT*0.3, RIGHT*0.3, color=GREEN),Line(LEFT*0.2, RIGHT*0.2, color=GREEN).shift(DOWN*0.1))# 传统数据收集trad_title = Text("传统数据收集", font_size=30)trad_user = user_icon.copy()trad_server = server_icon.copy()trad_data = Text("原始数据", color=RED, font_size=24)trad_arrow = Arrow(LEFT*2, RIGHT*2, buff=0.1, color=BLUE)traditional.add(trad_title, trad_user, trad_data, trad_arrow, trad_server)traditional.arrange(RIGHT, buff=0.5)traditional.shift(UP*1.5 + LEFT*3)# LDP数据收集ldp_title = Text("LDP数据收集", font_size=30)ldp_user = user_icon.copy()ldp_server = server_icon.copy()ldp_original = Text("原始数据", color=RED, font_size=24)ldp_perturb = Text("扰动", color=YELLOW, font_size=20)ldp_perturbed = Text("扰动后数据", color=GREEN, font_size=24)ldp_arrow = Arrow(LEFT*2, RIGHT*2, buff=0.1, color=BLUE)ldp.add(ldp_title, ldp_user, ldp_original, ldp_perturb, ldp_perturbed, ldp_arrow, ldp_server)ldp.arrange(RIGHT, buff=0.5)ldp.shift(DOWN*1.5 + LEFT*1.5)# 显示传统数据收集self.play(FadeIn(traditional))self.wait(1)# 显示LDP数据收集self.play(FadeIn(ldp))self.wait(2)# 差分隐私定义 - 使用Text替代MathTexdefinition = Text("Pr[M(t) = t*] ≤ e^ε × Pr[M(t') = t*]", font_size=36)definition.shift(DOWN*3.5)definition_text = Text("ε-局部差分隐私的数学定义", font_size=28)definition_text.next_to(definition, UP, buff=0.5)self.play(FadeIn(definition_text),Write(definition))self.wait(2)# 清除场景self.play(FadeOut(traditional, ldp, definition, definition_text, title))class RandomizedResponse(Scene):def construct(self):# 标题title = Text("随机响应机制 (Randomized Response)", font_size=40)title.to_edge(UP)self.play(Write(title))self.wait(1)# 随机响应过程epsilon = 1.0 # 隐私预算p = np.exp(epsilon) / (1 + np.exp(epsilon)) # 真实回答的概率# 创建可视化rr_diagram = VGroup()# 原始值original_data = Text("原始值", font_size=30)original_values = VGroup(Text("1", font_size=30, color=GREEN),Text("0", font_size=30, color=RED)).arrange(RIGHT, buff=2)original_group = VGroup(original_data, original_values).arrange(DOWN, buff=0.5)# 随机硬币coin_text = Text("概率机制", font_size=30)coin_values = VGroup(Text(f"p = {p:.2f}", font_size=24, color=GREEN),Text(f"1-p = {1-p:.2f}", font_size=24, color=RED)).arrange(RIGHT, buff=2)coin_group = VGroup(coin_text, coin_values).arrange(DOWN, buff=0.5)# 输出值output_data = Text("输出值", font_size=30)output_values = VGroup(Text("1", font_size=30, color=GREEN),Text("0", font_size=30, color=RED)).arrange(RIGHT, buff=2)output_group = VGroup(output_data, output_values).arrange(DOWN, buff=0.5)# 箭头arrow1 = Arrow(original_group.get_bottom() + DOWN*0.2, coin_group.get_top() - UP*0.2, buff=0.1)arrow2 = Arrow(coin_group.get_bottom() + DOWN*0.2, output_group.get_top() - UP*0.2, buff=0.1)# 组织整个图表rr_diagram.add(original_group, arrow1, coin_group, arrow2, output_group)rr_diagram.arrange(DOWN, buff=0.7)rr_diagram.scale(0.9)self.play(FadeIn(rr_diagram))self.wait(2)# 显示校准公式 - 使用Text替代MathTexcalibration = Text("f̂ = (f' - (1-p))/(2p - 1)", font_size=36)calibration_text = Text("频率校准公式", font_size=28)calibration_group = VGroup(calibration_text, calibration).arrange(DOWN, buff=0.3)calibration_group.to_edge(DOWN, buff=0.8)self.play(Write(calibration_group))self.wait(2)# 清除场景self.play(FadeOut(rr_diagram, calibration_group, title))class KeyValueTransformation(Scene):def construct(self):# 标题title = Text("Key-Value数据的转换", font_size=40)title.to_edge(UP)self.play(Write(title))self.wait(1)# 创建原始KV数据original_title = Text("原始KV数据", font_size=30)original_data = VGroup(Text("<Cancer, 0.6>", font_size=24),Text("<HIV, 0.9>", font_size=24),Text("<Fever, 0.08>", font_size=24)).arrange(DOWN, buff=0.3)original_group = VGroup(original_title, original_data).arrange(DOWN, buff=0.5)original_group.shift(LEFT*4)# 创建规范形式KV数据canonical_title = Text("规范形式", font_size=30)canonical_data = VGroup(Text("<1, 0.6>", font_size=24, color=GREEN),Text("<0, 0>", font_size=24, color=RED),Text("<1, 0.9>", font_size=24, color=GREEN),Text("<0, 0>", font_size=24, color=RED),Text("<1, 0.08>", font_size=24, color=GREEN),Text("<0, 0>", font_size=24, color=RED)).arrange(DOWN, buff=0.2)canonical_group = VGroup(canonical_title, canonical_data).arrange(DOWN, buff=0.5)canonical_group.shift(RIGHT*4)# 箭头transform_arrow = Arrow(original_group.get_right() + RIGHT*0.2, canonical_group.get_left() - LEFT*0.2, buff=0.1, color=BLUE)# 显示原始数据self.play(FadeIn(original_group))self.wait(1)# 显示转换过程self.play(GrowArrow(transform_arrow))self.wait(1)# 显示规范形式self.play(FadeIn(canonical_group))self.wait(2)# 显示示意解释explanation = Text("将KV对转换为完整的规范形式,每个键都有对应的值", font_size=24)explanation.to_edge(DOWN, buff=0.8)self.play(Write(explanation))self.wait(2)# 清除场景self.play(FadeOut(original_group, transform_arrow, canonical_group, explanation, title))class PrivKVIteration(Scene):def construct(self):# 标题title = Text("PrivKVM: 迭代改进估计准确性", font_size=40)title.to_edge(UP)self.play(Write(title))self.wait(1)# 创建迭代流程图iteration_diagram = VGroup()# 用户部分user_title = Text("用户", font_size=28)user_box = Rectangle(height=3, width=4, color=BLUE)user_content = VGroup(Text("<1, v>", font_size=24),Text("<0, 0>", font_size=24)).arrange(DOWN, buff=0.5)user_group = VGroup(user_title, user_box, user_content)user_box.surround(user_content, buff=0.5)user_title.next_to(user_box, UP, buff=0.2)# 数据收集器部分collector_title = Text("数据收集器", font_size=28)collector_box = Rectangle(height=3, width=4, color=GREEN)collector_content = VGroup(Text("数据收集", font_size=24),Text("频率估计", font_size=24),Text("均值估计", font_size=24)).arrange(DOWN, buff=0.5)collector_group = VGroup(collector_title, collector_box, collector_content)collector_box.surround(collector_content, buff=0.5)collector_title.next_to(collector_box, UP, buff=0.2)# 排列用户和收集器iteration_diagram.add(user_group, collector_group)iteration_diagram.arrange(RIGHT, buff=2)# 添加箭头arrow1 = Arrow(user_group.get_right(), collector_group.get_left(), buff=0.1, color=RED)arrow1_text = Text("发送扰动数据", font_size=18, color=RED)arrow1_text.next_to(arrow1, UP, buff=0.1)arrow2 = Arrow(collector_group.get_left() + DOWN*0.5, user_group.get_right() + DOWN*0.5, buff=0.1, color=BLUE)arrow2_text = Text("反馈估计结果", font_size=18, color=BLUE)arrow2_text.next_to(arrow2, DOWN, buff=0.1)iteration_diagram.add(arrow1, arrow1_text, arrow2, arrow2_text)# 显示迭代图self.play(FadeIn(iteration_diagram))self.wait(2)# 创建收敛图表axes = Axes(x_range=[0, 10, 1],y_range=[0, 1, 0.2],axis_config={"include_tip": False})axes_labels = VGroup(Text("迭代次数", font_size=20).next_to(axes.x_axis, DOWN, buff=0.2),Text("误差", font_size=20).next_to(axes.y_axis, LEFT, buff=0.2))# 误差曲线error_values = [0.9, 0.7, 0.5, 0.35, 0.25, 0.17, 0.13, 0.1, 0.08, 0.07]error_points = [axes.c2p(i, error_values[i]) for i in range(len(error_values))]error_line = VMobject()error_line.set_points_as_corners([*error_points])error_line.set_color(RED)dots = VGroup(*[Dot(point, color=RED) for point in error_points])convergence_group = VGroup(axes, axes_labels, error_line, dots)convergence_group.scale(0.6)convergence_group.to_edge(DOWN, buff=0.8)# 显示收敛图表self.play(FadeOut(iteration_diagram, shift=UP),FadeIn(convergence_group, shift=UP))# 添加收敛说明convergence_text = Text("通过多次迭代,PrivKVM能够不断减小估计误差", font_size=24)convergence_text.next_to(convergence_group, UP, buff=0.5)self.play(Write(convergence_text))self.wait(2)# 清除场景self.play(FadeOut(convergence_group, convergence_text, title))class ComparisonScene(Scene):def construct(self):# 标题title = Text("PrivKV系列方法比较", font_size=40)title.to_edge(UP)self.play(Write(title))self.wait(1)# 创建比较内容compare_group = VGroup()# PrivKVprivkv_title = Text("PrivKV", font_size=28, color=RED)privkv_feature = Text("单次迭代,最低通信成本", font_size=24)privkv_scenario = Text("适用于无迭代能力的场景", font_size=22, color=GRAY)privkv_group = VGroup(privkv_title, privkv_feature, privkv_scenario).arrange(DOWN, buff=0.2)# PrivKVMprivkvm_title = Text("PrivKVM", font_size=28, color=GREEN)privkvm_feature = Text("多次固定迭代,高精度", font_size=24)privkvm_scenario = Text("适用于固定通信带宽的场景", font_size=22, color=GRAY)privkvm_group = VGroup(privkvm_title, privkvm_feature, privkvm_scenario).arrange(DOWN, buff=0.2)# PrivKVM+privkvmplus_title = Text("PrivKVM+", font_size=28, color=BLUE)privkvmplus_feature = Text("精度与带宽之间的平衡", font_size=24)privkvmplus_scenario = Text("适用于灵活通信带宽的场景", font_size=22, color=GRAY)privkvmplus_group = VGroup(privkvmplus_title, privkvmplus_feature, privkvmplus_scenario).arrange(DOWN, buff=0.2)# 排列三个方法compare_group.add(privkv_group, privkvm_group, privkvmplus_group)compare_group.arrange(DOWN, buff=0.5, aligned_edge=LEFT)compare_group.shift(UP*0.5)# 显示比较内容self.play(FadeIn(compare_group))self.wait(2)# 创建效果图表axes = Axes(x_range=[0, 3.5, 1],y_range=[0, 1, 0.2],axis_config={"include_tip": False})axes_labels = VGroup(Text("隐私预算", font_size=20).next_to(axes.x_axis, DOWN, buff=0.2),Text("准确度", font_size=20).next_to(axes.y_axis, LEFT, buff=0.2))# 创建三条曲线x_values = np.linspace(0.1, 3.2, 10)privkv_values = 1 - np.exp(-x_values)privkvm_values = 1 - np.exp(-1.5 * x_values)privkvmplus_values = 1 - np.exp(-1.3 * x_values)privkv_points = [axes.c2p(x, y) for x, y in zip(x_values, privkv_values)]privkvm_points = [axes.c2p(x, y) for x, y in zip(x_values, privkvm_values)]privkvmplus_points = [axes.c2p(x, y) for x, y in zip(x_values, privkvmplus_values)]privkv_line = VMobject().set_points_as_corners([*privkv_points]).set_color(RED)privkvm_line = VMobject().set_points_as_corners([*privkvm_points]).set_color(GREEN)privkvmplus_line = VMobject().set_points_as_corners([*privkvmplus_points]).set_color(BLUE)# 添加图例legend_privkv = VGroup(Dot(color=RED), Text("PrivKV", font_size=16, color=RED)).arrange(RIGHT, buff=0.1)legend_privkvm = VGroup(Dot(color=GREEN), Text("PrivKVM", font_size=16, color=GREEN)).arrange(RIGHT, buff=0.1)legend_privkvmplus = VGroup(Dot(color=BLUE), Text("PrivKVM+", font_size=16, color=BLUE)).arrange(RIGHT, buff=0.1)legend = VGroup(legend_privkv, legend_privkvm, legend_privkvmplus).arrange(RIGHT, buff=0.3)graph_group = VGroup(axes, axes_labels, privkv_line, privkvm_line, privkvmplus_line)graph_group.scale(0.5)graph_group.to_edge(DOWN, buff=0.8)legend.next_to(graph_group, UP, buff=0.3)# 显示效果图表self.play(FadeIn(graph_group),FadeIn(legend))self.wait(2)# 清除场景self.play(FadeOut(compare_group, graph_group, legend, title))# 构建完整的演示
class CompletePresentation(Scene):def construct(self):# 开场标题main_title = Text("PrivKV: 使用本地差分隐私进行Key-Value数据收集", font_size=40)self.play(Write(main_title))self.wait(2)self.play(FadeOut(main_title))# 依次呈现每个场景LDPIntroduction().construct()self.wait(0.5)RandomizedResponse().construct()self.wait(0.5)KeyValueTransformation().construct()self.wait(0.5)PrivKVIteration().construct()self.wait(0.5)ComparisonScene().construct()self.wait(0.5)# 结束标题end_title = Text("谢谢观看!", font_size=48)self.play(Write(end_title))self.wait(2)