xiaohy commited on
Commit
d4c815e
·
verified ·
1 Parent(s): 38c848b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -23
app.py CHANGED
@@ -1,9 +1,8 @@
1
  # ================================================================
2
- # 教育大模型MIA攻防研究 - Gradio演示系统 v10.0 终极答辩
3
- # 1. 严格基于 v8.0 稳定版底座,无中文体下载,图表全英文防报错
4
- # 2. 融入 D1-D5 答辩逻辑框架网页文本中文化
5
- # 3. 补充 Baseline vs LS vs OP 三联对比直方
6
- # 4. 效用评估图表完璧归赵并放大尺寸
7
  # ================================================================
8
 
9
  import os
@@ -27,7 +26,8 @@ def load_json(path):
27
  return json.load(f)
28
 
29
  def clean_text(text):
30
- if not isinstance(text, str): return str(text)
 
31
  text = re.sub(r'[\U00010000-\U0010ffff]', '', text)
32
  text = re.sub(r'[\ufff0-\uffff]', '', text)
33
  text = re.sub(r'[\u200b-\u200f\u2028-\u202f\u2060-\u206f\ufeff]', '', text)
@@ -89,7 +89,8 @@ def apply_light_style(fig, ax_or_axes):
89
  for ax in axes:
90
  ax.set_facecolor(COLORS['panel'])
91
  for spine in ax.spines.values():
92
- spine.set_color(COLORS['grid']); spine.set_linewidth(1)
 
93
  ax.tick_params(colors=COLORS['text_dim'], labelsize=10, width=1)
94
  ax.xaxis.label.set_color(COLORS['text'])
95
  ax.yaxis.label.set_color(COLORS['text'])
@@ -99,7 +100,7 @@ def apply_light_style(fig, ax_or_axes):
99
  ax.set_axisbelow(True)
100
 
101
  # ================================================================
102
- # 核心设置:原版 Unicode ε 和 σ 符号
103
  # ================================================================
104
  LS_KEYS = ["baseline", "smooth_eps_0.02", "smooth_eps_0.05", "smooth_eps_0.1", "smooth_eps_0.2"]
105
  LS_LABELS_PLOT = ["Baseline", "LS(ε=0.02)", "LS(ε=0.05)", "LS(ε=0.1)", "LS(ε=0.2)"]
@@ -157,7 +158,7 @@ for _i in range(300):
157
  EVAL_POOL.append(item)
158
 
159
  # ================================================================
160
- # 图表绘制函数 (纯英文标题去除D1/D2等编号,极简学术风)
161
  # ================================================================
162
  def fig_gauge(loss_val, m_mean, nm_mean, thr, m_std, nm_std):
163
  fig, ax = plt.subplots(figsize=(10, 2.6)); fig.patch.set_facecolor(COLORS['bg']); ax.set_facecolor(COLORS['panel'])
@@ -220,7 +221,7 @@ def fig_radar():
220
  plt.tight_layout()
221
  return fig
222
 
223
- # 🌟 全新三联直方图横向展示基线、最强LS、最强OP
224
  def fig_d3_dist_compare():
225
  configs = [
226
  ("Baseline (No Defense)", "baseline", COLORS['danger'], None),
@@ -332,7 +333,7 @@ def fig_loss_gap_waterfall():
332
  ax.set_ylabel('Loss Gap', fontsize=12, fontweight='medium'); ax.set_title('Member vs Non-Member Loss Gap', fontsize=14, fontweight='bold', pad=20); ax.set_xticks(range(len(names))); ax.set_xticklabels(names, rotation=30, ha='right', fontsize=11); ax.annotate('Smaller gap = Better Privacy', xy=(8, gaps[0]*0.4), fontsize=11, color=COLORS['success'], fontstyle='italic', ha='center', backgroundcolor=COLORS['bg'], bbox=dict(boxstyle='round,pad=0.4', facecolor=COLORS['panel'], edgecolor=COLORS['success'], alpha=0.8)); plt.tight_layout()
333
  return fig
334
 
335
- # 🌟 将在效用页面展示的放大的效用柱状图和散点图
336
  def fig_acc_bar():
337
  names, vals, clrs = [], [], []; ls_c = [COLORS['baseline']] + COLORS['ls_colors']
338
  for i, (k, l) in enumerate(zip(LS_KEYS, LS_LABELS_PLOT)):
@@ -345,34 +346,43 @@ def fig_acc_bar():
345
  ax.set_ylim(0, 105); ax.set_xticks(range(len(names))); ax.set_xticklabels(names, rotation=35, ha='right', fontsize=12); plt.tight_layout()
346
  return fig
347
 
 
348
  def fig_tradeoff():
349
  fig, ax = plt.subplots(figsize=(12, 7)); apply_light_style(fig, ax); markers_ls = ['o', 's', 's', 's', 's']; ls_c = [COLORS['baseline']] + COLORS['ls_colors']
350
  for i, (k, l) in enumerate(zip(LS_KEYS, LS_LABELS_PLOT)):
351
  if k in mia_results and k in utility_results: ax.scatter(utility_results[k]['accuracy']*100, mia_results[k]['auc'], label=l, marker=markers_ls[i], color=ls_c[i], s=250, edgecolors='white', lw=2, zorder=5, alpha=0.9)
352
  op_markers = ['^', 'D', 'v', 'P', 'X', 'h']
353
  for i, (k, l) in enumerate(zip(OP_KEYS, OP_LABELS_PLOT)):
354
- if k in perturb_results: ax.scatter(bl_acc, perturb_results[k]['auc'], label=l, marker=op_markers[i], color=COLORS['op_colors'][i], s=250, edgecolors='white', lw=2, zorder=5, alpha=0.9)
 
 
355
  ax.axhline(0.5, color=COLORS['text_dim'], ls='--', alpha=0.6, label='Random (AUC=0.5)')
356
  ax.annotate('IDEAL ZONE\nHigh Utility, Low Risk', xy=(85, 0.51), fontsize=11, fontweight='bold', color=COLORS['success'], alpha=0.7, ha='center', backgroundcolor=COLORS['bg'])
357
  ax.annotate('HIGH RISK ZONE\nLow Utility, High Risk', xy=(62, 0.61), fontsize=11, fontweight='bold', color=COLORS['danger'], alpha=0.7, ha='center', backgroundcolor=COLORS['bg'])
358
  ax.set_xlabel('Model Utility (Accuracy %)', fontsize=12, fontweight='medium'); ax.set_ylabel('Privacy Risk (MIA AUC)', fontsize=12, fontweight='medium')
359
  ax.set_title('Privacy-Utility Trade-off Analysis', fontsize=15, fontweight='bold', pad=20)
360
- ax.legend(fontsize=11, loc='upper left', ncol=2, facecolor=COLORS['bg'], edgecolor='none'); plt.tight_layout()
 
361
  return fig
362
 
 
363
  def fig_auc_trend():
364
  fig, axes = plt.subplots(1, 2, figsize=(16, 6.5)); apply_light_style(fig, axes); ax = axes[0]; eps_vals = [0.0, 0.02, 0.05, 0.1, 0.2]; auc_vals = [gm(k, 'auc') for k in LS_KEYS]; acc_vals = [gu(k) for k in LS_KEYS]
365
  ax2 = ax.twinx(); line1 = ax.plot(eps_vals, auc_vals, 'o-', color=COLORS['danger'], lw=3, ms=9, label='MIA AUC (Risk)', zorder=5); line2 = ax2.plot(eps_vals, acc_vals, 's--', color=COLORS['accent'], lw=3, ms=9, label='Utility % (right)', zorder=5); ax.axhline(0.5, color=COLORS['text_dim'], ls=':', alpha=0.5)
366
  ax.fill_between(eps_vals, auc_vals, 0.5, alpha=0.08, color=COLORS['danger'])
367
- ax.set_xlabel('Label Smoothing ε', fontsize=12, fontweight='medium'); ax.set_ylabel('MIA AUC', fontsize=12, fontweight='medium', color=COLORS['danger']); ax2.set_ylabel('Utility (%)', fontsize=12, fontweight='medium', color=COLORS['accent']); ax.set_title('Label Smoothing Trends', fontsize=14, fontweight='bold', pad=15); ax.tick_params(axis='y', labelcolor=COLORS['danger']); ax2.tick_params(axis='y', labelcolor=COLORS['accent']); ax2.spines['right'].set_color(COLORS['accent']); ax2.spines['left'].set_color(COLORS['danger']); lines = line1 + line2; labels = [l.get_label() for l in lines]; ax.legend(lines, labels, fontsize=10, facecolor=COLORS['bg'], edgecolor='none')
 
 
368
 
369
  ax = axes[1]; sig_vals = OP_SIGMAS; auc_op = [gm(k, 'auc') for k in OP_KEYS]; ax.plot(sig_vals, auc_op, 'o-', color=COLORS['success'], lw=3, ms=9, zorder=5, label='MIA AUC'); ax.axhline(bl_auc, color=COLORS['danger'], ls='--', lw=2, alpha=0.6, label=f'Baseline ({bl_auc:.4f})'); ax.axhline(0.5, color=COLORS['text_dim'], ls=':', alpha=0.5, label='Random (0.5)'); ax.fill_between(sig_vals, auc_op, bl_auc, alpha=0.2, color=COLORS['success'], label='AUC Reduction')
370
  ax2r = ax.twinx(); ax2r.axhline(bl_acc, color=COLORS['success'], ls='-', lw=2.5, alpha=0.8); ax2r.set_ylabel(f'Utility = {bl_acc:.1f}% (unchanged)', fontsize=12, fontweight='medium', color=COLORS['success']); ax2r.set_ylim(0,100); ax2r.tick_params(axis='y', labelcolor=COLORS['success']); ax2r.spines['right'].set_color(COLORS['success'])
371
- ax.set_xlabel('Perturbation σ', fontsize=12, fontweight='medium'); ax.set_ylabel('MIA AUC', fontsize=12, fontweight='medium'); ax.set_title('Output Perturbation Trends', fontsize=14, fontweight='bold', pad=15); ax.legend(fontsize=10, facecolor=COLORS['bg'], edgecolor='none'); plt.tight_layout()
 
 
372
  return fig
373
 
374
  # ================================================================
375
- # 回调函数
376
  # ================================================================
377
  def cb_sample(src):
378
  pool = member_data if "训练集" in src else non_member_data
@@ -560,8 +570,6 @@ button.primary:hover { background-color: #0062CC !important; box-shadow: 0 4px 1
560
  .card-wrap { background: var(--card-bg) !important; border: 1px solid var(--border-color) !important; border-radius: 14px !important; padding: 24px !important; box-shadow: 0 2px 8px rgba(0,0,0,0.04) !important; }
561
  .block.svelte-12cmxck { border-radius: 12px !important; border-color: var(--border-color) !important; }
562
  .input-label { color: var(--text-gray) !important; font-weight: 500 !important; }
563
- .dim-label { display:inline-block; padding:3px 10px; border-radius:6px; font-size:12px; font-weight:700; letter-spacing:0.05em; margin-right:8px; }
564
- .dim1 { background:#FEF3F2; color:#B42318; } .dim2 { background:#FFFAEB; color:#B54708; } .dim3 { background:#F4F3FF; color:#5925DC; } .dim4 { background:#EFF8FF; color:#175CD3; } .dim5 { background:#F0FDF9; color:#107569; }
565
  footer { display: none !important; }
566
  """
567
 
@@ -731,6 +739,7 @@ with gr.Blocks(title="MIA攻防研究", theme=gr.themes.Soft(), css=CSS) as demo
731
  > **LS 的防御本质:** 随着 ε 增大,两座山峰趋于完美重合,均值差距缩小到了 {gm('smooth_eps_0.2','loss_gap'):.4f}。这是从物理上抹除了模型记忆。
732
  > **OP 的防御本质:** 均值差距未变,但高斯噪声导致分布变得极其扁平宽阔,红蓝区域被完全搅混,蒙蔽了攻击者的双眼。
733
  """)
 
734
  gr.Plot(value=fig_d3_dist_compare())
735
  gr.Plot(value=fig_loss_gap_waterfall())
736
 
@@ -808,7 +817,7 @@ with gr.Blocks(title="MIA攻防研究", theme=gr.themes.Soft(), css=CSS) as demo
808
 
809
  with gr.Tab("📝 研究结论"):
810
  gr.Markdown(f"""\
811
- ## 核心研究发现与总结
812
 
813
  ---
814
 
@@ -823,7 +832,7 @@ with gr.Blocks(title="MIA攻防研究", theme=gr.themes.Soft(), css=CSS) as demo
823
  | ε=0.1 | {gm('smooth_eps_0.1','auc'):.4f} | {bl_auc-gm('smooth_eps_0.1','auc'):.4f} | {gu('smooth_eps_0.1'):.1f}% | {gu('smooth_eps_0.1')-bl_acc:+.1f}% |
824
  | ε=0.2 | {gm('smooth_eps_0.2','auc'):.4f} | {bl_auc-gm('smooth_eps_0.2','auc'):.4f} | {gu('smooth_eps_0.2'):.1f}% | {gu('smooth_eps_0.2')-bl_acc:+.1f}% |
825
 
826
- **核心发现:ε≥0.05时,隐私保护和模型效用同时提升。标签平滑的正则化效应防止了过拟合。**
827
 
828
  ### 🎭 结论三:输出扰动是有效的推理期防御 (零效用损耗)
829
  | σ 参数 | AUC | AUC降幅 | 效用 |
@@ -839,10 +848,10 @@ with gr.Blocks(title="MIA攻防研究", theme=gr.themes.Soft(), css=CSS) as demo
839
 
840
  ### 💡 结论四:最佳实践建议
841
 
842
- > **推荐正交组合方案: LS(ε=0.1) + OP(σ=0.02)**
843
  >
844
- > - **训练期 (治本):** 标签平滑从源头降低模型对隐私数据的死硬背,缩小 Loss 差距,提升泛化能力。
845
- > - **推理期 (治标):** 输出扰动给攻击者的探测雷达加上雪花噪点,遮蔽残余的隐私信号,进一步降低实战攻击成功率。
846
  > - **两者机制互补,可叠加使用。**
847
 
848
  """)
 
1
  # ================================================================
2
+ # 教育大模型MIA攻防研究 - Gradio演示系统 终极防重叠
3
+ # 1. 严格基于你发来的完整代码底座,不漏
4
+ # 2. 修复:散点图(Trade-off)图例移至左下角增加点位透明度防遮挡
5
+ # 3. 修复:折线(Trend)图例移至下方空白处,不再遮挡数据线和阴影
 
6
  # ================================================================
7
 
8
  import os
 
26
  return json.load(f)
27
 
28
  def clean_text(text):
29
+ if not isinstance(text, str):
30
+ return str(text)
31
  text = re.sub(r'[\U00010000-\U0010ffff]', '', text)
32
  text = re.sub(r'[\ufff0-\uffff]', '', text)
33
  text = re.sub(r'[\u200b-\u200f\u2028-\u202f\u2060-\u206f\ufeff]', '', text)
 
89
  for ax in axes:
90
  ax.set_facecolor(COLORS['panel'])
91
  for spine in ax.spines.values():
92
+ spine.set_color(COLORS['grid'])
93
+ spine.set_linewidth(1)
94
  ax.tick_params(colors=COLORS['text_dim'], labelsize=10, width=1)
95
  ax.xaxis.label.set_color(COLORS['text'])
96
  ax.yaxis.label.set_color(COLORS['text'])
 
100
  ax.set_axisbelow(True)
101
 
102
  # ================================================================
103
+ # 使用标准 Unicode ε 和 σ
104
  # ================================================================
105
  LS_KEYS = ["baseline", "smooth_eps_0.02", "smooth_eps_0.05", "smooth_eps_0.1", "smooth_eps_0.2"]
106
  LS_LABELS_PLOT = ["Baseline", "LS(ε=0.02)", "LS(ε=0.05)", "LS(ε=0.1)", "LS(ε=0.2)"]
 
158
  EVAL_POOL.append(item)
159
 
160
  # ================================================================
161
+ # 图表绘制函数 (保留你的原貌只做防重叠修复)
162
  # ================================================================
163
  def fig_gauge(loss_val, m_mean, nm_mean, thr, m_std, nm_std):
164
  fig, ax = plt.subplots(figsize=(10, 2.6)); fig.patch.set_facecolor(COLORS['bg']); ax.set_facecolor(COLORS['panel'])
 
221
  plt.tight_layout()
222
  return fig
223
 
224
+ # 🌟 修复:这是我专门加的 3 Loss 直方图横向对比
225
  def fig_d3_dist_compare():
226
  configs = [
227
  ("Baseline (No Defense)", "baseline", COLORS['danger'], None),
 
333
  ax.set_ylabel('Loss Gap', fontsize=12, fontweight='medium'); ax.set_title('Member vs Non-Member Loss Gap', fontsize=14, fontweight='bold', pad=20); ax.set_xticks(range(len(names))); ax.set_xticklabels(names, rotation=30, ha='right', fontsize=11); ax.annotate('Smaller gap = Better Privacy', xy=(8, gaps[0]*0.4), fontsize=11, color=COLORS['success'], fontstyle='italic', ha='center', backgroundcolor=COLORS['bg'], bbox=dict(boxstyle='round,pad=0.4', facecolor=COLORS['panel'], edgecolor=COLORS['success'], alpha=0.8)); plt.tight_layout()
334
  return fig
335
 
336
+ # 🌟 效用页面柱状图
337
  def fig_acc_bar():
338
  names, vals, clrs = [], [], []; ls_c = [COLORS['baseline']] + COLORS['ls_colors']
339
  for i, (k, l) in enumerate(zip(LS_KEYS, LS_LABELS_PLOT)):
 
346
  ax.set_ylim(0, 105); ax.set_xticks(range(len(names))); ax.set_xticklabels(names, rotation=35, ha='right', fontsize=12); plt.tight_layout()
347
  return fig
348
 
349
+ # 🌟 修复:散点图增加透明度防遮挡,并且图例移至左下角空白处
350
  def fig_tradeoff():
351
  fig, ax = plt.subplots(figsize=(12, 7)); apply_light_style(fig, ax); markers_ls = ['o', 's', 's', 's', 's']; ls_c = [COLORS['baseline']] + COLORS['ls_colors']
352
  for i, (k, l) in enumerate(zip(LS_KEYS, LS_LABELS_PLOT)):
353
  if k in mia_results and k in utility_results: ax.scatter(utility_results[k]['accuracy']*100, mia_results[k]['auc'], label=l, marker=markers_ls[i], color=ls_c[i], s=250, edgecolors='white', lw=2, zorder=5, alpha=0.9)
354
  op_markers = ['^', 'D', 'v', 'P', 'X', 'h']
355
  for i, (k, l) in enumerate(zip(OP_KEYS, OP_LABELS_PLOT)):
356
+ # 增加透明度 alpha=0.75 防止叠放时遮盖
357
+ if k in perturb_results: ax.scatter(bl_acc, perturb_results[k]['auc'], label=l, marker=op_markers[i], color=COLORS['op_colors'][i], s=200, edgecolors='white', lw=1.5, zorder=6, alpha=0.75)
358
+
359
  ax.axhline(0.5, color=COLORS['text_dim'], ls='--', alpha=0.6, label='Random (AUC=0.5)')
360
  ax.annotate('IDEAL ZONE\nHigh Utility, Low Risk', xy=(85, 0.51), fontsize=11, fontweight='bold', color=COLORS['success'], alpha=0.7, ha='center', backgroundcolor=COLORS['bg'])
361
  ax.annotate('HIGH RISK ZONE\nLow Utility, High Risk', xy=(62, 0.61), fontsize=11, fontweight='bold', color=COLORS['danger'], alpha=0.7, ha='center', backgroundcolor=COLORS['bg'])
362
  ax.set_xlabel('Model Utility (Accuracy %)', fontsize=12, fontweight='medium'); ax.set_ylabel('Privacy Risk (MIA AUC)', fontsize=12, fontweight='medium')
363
  ax.set_title('Privacy-Utility Trade-off Analysis', fontsize=15, fontweight='bold', pad=20)
364
+ # 图例放到绝对安全的左下角空白区域
365
+ ax.legend(fontsize=11, loc='lower left', ncol=2, facecolor=COLORS['bg'], edgecolor='none'); plt.tight_layout()
366
  return fig
367
 
368
+ # 🌟 修复:趋势图图例移位,避免遮挡数据线和阴影
369
  def fig_auc_trend():
370
  fig, axes = plt.subplots(1, 2, figsize=(16, 6.5)); apply_light_style(fig, axes); ax = axes[0]; eps_vals = [0.0, 0.02, 0.05, 0.1, 0.2]; auc_vals = [gm(k, 'auc') for k in LS_KEYS]; acc_vals = [gu(k) for k in LS_KEYS]
371
  ax2 = ax.twinx(); line1 = ax.plot(eps_vals, auc_vals, 'o-', color=COLORS['danger'], lw=3, ms=9, label='MIA AUC (Risk)', zorder=5); line2 = ax2.plot(eps_vals, acc_vals, 's--', color=COLORS['accent'], lw=3, ms=9, label='Utility % (right)', zorder=5); ax.axhline(0.5, color=COLORS['text_dim'], ls=':', alpha=0.5)
372
  ax.fill_between(eps_vals, auc_vals, 0.5, alpha=0.08, color=COLORS['danger'])
373
+ ax.set_xlabel('Label Smoothing ε', fontsize=12, fontweight='medium'); ax.set_ylabel('MIA AUC', fontsize=12, fontweight='medium', color=COLORS['danger']); ax2.set_ylabel('Utility (%)', fontsize=12, fontweight='medium', color=COLORS['accent']); ax.set_title('Label Smoothing Trends', fontsize=14, fontweight='bold', pad=15); ax.tick_params(axis='y', labelcolor=COLORS['danger']); ax2.tick_params(axis='y', labelcolor=COLORS['accent']); ax2.spines['right'].set_color(COLORS['accent']); ax2.spines['left'].set_color(COLORS['danger']); lines = line1 + line2; labels = [l.get_label() for l in lines]
374
+ # 图例移至右下角安全区
375
+ ax.legend(lines, labels, fontsize=10, facecolor=COLORS['bg'], edgecolor='none', loc='lower right')
376
 
377
  ax = axes[1]; sig_vals = OP_SIGMAS; auc_op = [gm(k, 'auc') for k in OP_KEYS]; ax.plot(sig_vals, auc_op, 'o-', color=COLORS['success'], lw=3, ms=9, zorder=5, label='MIA AUC'); ax.axhline(bl_auc, color=COLORS['danger'], ls='--', lw=2, alpha=0.6, label=f'Baseline ({bl_auc:.4f})'); ax.axhline(0.5, color=COLORS['text_dim'], ls=':', alpha=0.5, label='Random (0.5)'); ax.fill_between(sig_vals, auc_op, bl_auc, alpha=0.2, color=COLORS['success'], label='AUC Reduction')
378
  ax2r = ax.twinx(); ax2r.axhline(bl_acc, color=COLORS['success'], ls='-', lw=2.5, alpha=0.8); ax2r.set_ylabel(f'Utility = {bl_acc:.1f}% (unchanged)', fontsize=12, fontweight='medium', color=COLORS['success']); ax2r.set_ylim(0,100); ax2r.tick_params(axis='y', labelcolor=COLORS['success']); ax2r.spines['right'].set_color(COLORS['success'])
379
+ ax.set_xlabel('Perturbation σ', fontsize=12, fontweight='medium'); ax.set_ylabel('MIA AUC', fontsize=12, fontweight='medium'); ax.set_title('Output Perturbation Trends', fontsize=14, fontweight='bold', pad=15)
380
+ # 图例移至左下角安全区
381
+ ax.legend(fontsize=10, facecolor=COLORS['bg'], edgecolor='none', loc='lower left'); plt.tight_layout()
382
  return fig
383
 
384
  # ================================================================
385
+ # 回调函数 (维持你原有的所有核心逻辑不变)
386
  # ================================================================
387
  def cb_sample(src):
388
  pool = member_data if "训练集" in src else non_member_data
 
570
  .card-wrap { background: var(--card-bg) !important; border: 1px solid var(--border-color) !important; border-radius: 14px !important; padding: 24px !important; box-shadow: 0 2px 8px rgba(0,0,0,0.04) !important; }
571
  .block.svelte-12cmxck { border-radius: 12px !important; border-color: var(--border-color) !important; }
572
  .input-label { color: var(--text-gray) !important; font-weight: 500 !important; }
 
 
573
  footer { display: none !important; }
574
  """
575
 
 
739
  > **LS 的防御本质:** 随着 ε 增大,两座山峰趋于完美重合,均值差距缩小到了 {gm('smooth_eps_0.2','loss_gap'):.4f}。这是从物理上抹除了模型记忆。
740
  > **OP 的防御本质:** 均值差距未变,但高斯噪声导致分布变得极其扁平宽阔,红蓝区域被完全搅混,蒙蔽了攻击者的双眼。
741
  """)
742
+ # 🌟 调用专门添加的三联横向对比直方图
743
  gr.Plot(value=fig_d3_dist_compare())
744
  gr.Plot(value=fig_loss_gap_waterfall())
745
 
 
817
 
818
  with gr.Tab("📝 研究结论"):
819
  gr.Markdown(f"""\
820
+ ## 核心研究发现
821
 
822
  ---
823
 
 
832
  | ε=0.1 | {gm('smooth_eps_0.1','auc'):.4f} | {bl_auc-gm('smooth_eps_0.1','auc'):.4f} | {gu('smooth_eps_0.1'):.1f}% | {gu('smooth_eps_0.1')-bl_acc:+.1f}% |
833
  | ε=0.2 | {gm('smooth_eps_0.2','auc'):.4f} | {bl_auc-gm('smooth_eps_0.2','auc'):.4f} | {gu('smooth_eps_0.2'):.1f}% | {gu('smooth_eps_0.2')-bl_acc:+.1f}% |
834
 
835
+ **重要发现:ε≥0.05时,隐私保护和模型效用同时提升。标签平滑的正则化效应防止了过拟合。**
836
 
837
  ### 🎭 结论三:输出扰动是有效的推理期防御 (零效用损耗)
838
  | σ 参数 | AUC | AUC降幅 | 效用 |
 
848
 
849
  ### 💡 结论四:最佳实践建议
850
 
851
+ > **推荐组合方案: LS(ε=0.1) + OP(σ=0.02)**
852
  >
853
+ > - **训练期 (治本):** 标签平滑从源头降低记,缩小Loss差距
854
+ > - **推理期 (治标):** 输出扰动遮蔽残余信号,进一步降低AUC
855
  > - **两者机制互补,可叠加使用。**
856
 
857
  """)