资讯动态

黑盒对抗攻击实战:先验知识与多臂老虎机的高效查询策略

发布时间:2026/10/13 8:37:55 来源:尧图企业网站定制
1. 为什么这篇论文值得反复读第一次看到这个标题的时候我正陷在一个安全评测项目里出不来。当时的需求是要评估一个线上推理服务的鲁棒性但对方只给了一个API接口模型结构、权重、训练数据一概不知连返回的置信度都做了截断。这种场景下传统的白盒攻击方法全部失效梯度拿不到反向传播无从谈起。翻了一圈资料这篇发表在顶会上的工作几乎是绕不开的起点。它解决的核心问题很明确在只能拿到模型输入输出、拿不到梯度的黑盒条件下如何高效地构造对抗样本。作者把这个问题拆成了两个层面来解——一是用先验知识缩小搜索空间二是用多臂老虎机的思路来组织查询。这两个东西单独看都不新鲜但组合在一起产生的效果相当可观尤其是在查询次数被严格限制的场景下。适合读这篇内容的人我大致分三类。第一类是做模型安全评测的工程师手上有黑盒服务需要压测想知道怎么用最少的查询把样本打穿。第二类是研究对抗鲁棒性的同学想理解黑盒攻击的数学框架和收敛性分析。第三类是做红队或者安全审计的从业者需要在真实业务场景里评估模型的抗攻击能力。不管你是哪一类这篇论文提供的思路都能直接落地。我后面会从设计思路、核心原理、实操复现、踩坑经验几个角度把它拆开讲。不是翻译论文而是把我自己复现过程中理解到的东西、踩过的坑、以及一些论文里没写但实际很重要的细节都摊开来说。2. 核心设计思路拆解2.1 黑盒攻击到底难在哪先说清楚问题的本质。对抗攻击的目标是找到一个扰动向量让模型把原始样本分类错。白盒条件下你有完整的梯度信息可以直接用FGSM、PGD这类方法沿着梯度方向走效率极高。但黑盒条件下梯度是未知的你只能通过查询模型来获取信息。最朴素的做法是有限差分对输入的每一个维度分别加一个小扰动观察输出变化从而估计梯度。这个方法的查询复杂度是O(d)d是输入维度。对于一张224x224x3的图片来说d接近15万意味着你每走一步就要查询15万次。这在任何实际场景里都是不可接受的。所以黑盒攻击的核心矛盾就是如何在极少的查询次数内找到有效的扰动方向。这篇论文的贡献就在于它把这个搜索问题形式化成了一个带先验的在线优化问题然后用老虎机算法来高效求解。2.2 先验知识为什么是关键论文标题里的Prior Convictions其实是个双关既指先验信念也暗含对抗攻击中确信模型会犯错的意思。这里的先验知识指的是什么呢在图像领域一个被广泛验证的观察是对抗扰动往往集中在某些特定的频率分量上。具体来说低频扰动通常更有效因为模型对低频变化的敏感度更高。另一个观察是相邻像素之间的扰动往往是相关的不是独立随机的。这些先验意味着你不需要在完整的d维空间里搜索而是可以在一个低维子空间里搜索。论文里用的是一种基于梯度的先验先用少量查询估计一个粗略的梯度方向然后在这个方向的邻域内做精细搜索。这就像你在一个巨大的停车场找车先验知识告诉你车大概率停在某个区域你就不用把整个停车场翻一遍。我自己的理解是先验的作用相当于给搜索过程加了一个正则化项把解空间约束在一个更合理的范围内。这不仅减少了查询次数还提高了攻击的成功率因为搜索过程不容易跑到那些无效的扰动区域去。2.3 老虎机框架的引入逻辑多臂老虎机是解决探索与利用权衡的经典框架。你有K个选项每个选项的收益分布未知你要在有限次尝试内最大化总收益。核心挑战是什么时候该继续利用当前看起来最好的选项什么时候该去探索其他可能更好的选项。把这个框架套到黑盒攻击上每个臂就是一个候选的扰动方向收益就是攻击的成功率或者损失函数的下降幅度。论文用的是基于置信上界的算法它在每一步选择那个乐观估计最高的臂。这个乐观估计由两部分组成当前的收益估计加上一个探索奖励项。探索奖励项随着该臂被选择的次数增加而减小从而自动平衡探索和利用。这个设计的巧妙之处在于它不需要知道模型的任何内部信息完全基于观测到的反馈来调整搜索策略。而且UCB类算法有理论上的遗憾界保证意味着你的查询次数不会浪费太多。2.4 整体方案的架构把上面几个部分串起来整个攻击流程大致是这样的初始化阶段用少量查询估计一个粗略的梯度方向作为先验。子空间构造基于先验方向构造一个低维的搜索子空间。老虎机搜索在子空间内用UCB算法选择扰动方向每次选择后查询模型获取反馈。扰动更新根据反馈更新对各个方向的收益估计并调整搜索策略。终止条件达到查询预算或者攻击成功。这个架构的好处是模块化每个部分都可以替换或改进。比如先验估计可以用不同的方法子空间构造可以用PCA或者随机投影老虎机算法也可以用Thompson采样替代UCB。论文里做了消融实验验证了每个模块的贡献。3. 核心细节与实操要点3.1 先验梯度的估计方法先验梯度的估计是整个流程的第一步也是最关键的一步。论文里用的是一种基于随机方向导数的估计方法。具体操作是随机采样若干个方向向量对每个方向计算方向导数然后用这些方向导数来重构梯度。这里有个细节很重要采样方向的数量和估计精度之间的权衡。采样太少梯度估计不准后续搜索会跑偏采样太多浪费查询预算。论文里建议的采样数量是O(√d)量级对于ImageNet规模的输入大概是几百次查询。这个数量级在实际场景里是可以接受的。我自己复现的时候发现采样方向的选择也有讲究。如果完全随机采样有时候会碰到一些坏方向导致估计方差很大。一个改进是用正交化的随机方向比如用Hadamard矩阵的行作为采样方向这样可以保证方向之间的独立性降低估计方差。还有一个实操技巧用符号而不是精确值。也就是说只关心方向导数的正负号不关心具体数值。这样做的好处是对噪声更鲁棒因为模型输出的微小波动不会影响符号判断。论文里也提到了这个技巧实测下来确实更稳。3.2 子空间的维度选择子空间的维度k是一个需要仔细调的超参数。k太小搜索空间受限可能找不到有效的扰动方向k太大查询复杂度上升违背了降维的初衷。论文里的做法是让k随查询预算自适应调整。在查询预算充足的时候用较大的k预算紧张的时候用较小的k。具体的调整策略是基于当前的攻击进展来决定的如果连续多次查询都没有找到更好的方向就增大k来扩大搜索范围如果一直在进步就保持或减小k来精细化搜索。从理论分析的角度k的最优值大概在O(√T)量级T是总查询预算。对于T10000的情况k大概在100左右。这个数值在我的实验里也基本验证了k在50到200之间效果最好。注意子空间的构造方式会影响搜索效率。论文里用的是先验方向加上一组正交基正交基可以用随机生成或者从历史查询中提取。我试过用PCA从历史扰动中提取主成分作为基效果比纯随机基好一些但计算开销也更大。3.3 UCB算法的参数配置UCB算法的核心是那个探索奖励项通常形式是sqrt(2*ln(t)/n_i)其中t是总轮数n_i是第i个臂被选择的次数。这个系数2是理论上的最优值但在实际应用中可以根据情况调整。我的经验是在攻击初期可以适当增大探索系数让算法多尝试不同的方向在后期减小探索系数专注于精细化搜索。这个调整可以通过一个衰减因子来实现比如让系数随时间按1/sqrt(t)衰减。另一个细节是收益的定义。论文里用的是损失函数的下降量但实际中模型可能只返回硬标签分类结果不返回置信度。这种情况下可以用攻击是否成功作为二值收益但这样信息量会少很多。一个折中方案是用查询之间的相对变化来构造收益信号比如当前查询是否比上一次更接近决策边界。3.4 查询预算的分配策略查询预算是黑盒攻击中最宝贵的资源。论文里把预算分成了三部分先验估计、子空间搜索、最终微调。大致的分配比例是2:6:2但这个比例可以根据任务难度调整。如果模型特别鲁棒先验估计可能需要更多查询来获得准确的方向如果模型比较脆弱子空间搜索可以少花一些查询把更多预算留给微调。我在实际项目里的做法是先用一个小预算做探测根据探测结果动态调整后续的分配比例。还有一个容易被忽略的点查询的批处理。很多线上服务支持批量查询一次可以传多个样本。这种情况下可以把多个候选扰动打包成一个批次一起查询这样单次查询的成本被摊薄了。论文里没有特别强调这一点但在工程实践中非常有用。4. 完整复现流程与关键环节4.1 环境准备与依赖复现这篇论文的工作需要的环境不算复杂。核心依赖是数值计算库和深度学习框架。我用的是Python生态主要包包括numpy、scipy、以及一个深度学习框架用来加载模型和做推理。如果你要攻击的是线上服务还需要一个HTTP客户端来发送查询请求。这里有个坑线上服务的响应时间可能不稳定有时候几毫秒有时候几秒。建议加一个重试机制和超时设置避免因为单次查询失败影响整个攻击流程。对于本地模型建议用GPU加速推理因为攻击过程需要大量查询CPU推理会成为瓶颈。我用一张中端显卡对ResNet-50的查询速度大概在每秒几百次基本够用。4.2 先验估计的实现细节先验估计的代码逻辑大概是这样的def estimate_prior_gradient(model, x, num_samples, epsilon): d x.size grad_estimate np.zeros(d) directions generate_orthogonal_directions(num_samples, d) for u in directions: # 计算方向导数 f_plus model.predict(x epsilon * u) f_minus model.predict(x - epsilon * u) directional_derivative (f_plus - f_minus) / (2 * epsilon) grad_estimate directional_derivative * u return grad_estimate / num_samples这里有几个参数需要仔细调。epsilon是差分步长太小的话数值误差大太大的话非线性效应明显。论文里建议取输入范围的1%到5%对于归一化到[0,1]的图片epsilon在0.01到0.05之间比较合适。num_samples是采样方向数前面说了大概在O(√d)量级。但实际中还要考虑查询预算如果预算紧张可以适当减少采样数用更粗糙的估计。实操心得方向导数的计算可以用中心差分而不是前向差分精度更高。代价是每次估计需要两次查询而不是一次但考虑到精度提升这个代价是值得的。4.3 子空间搜索的代码框架子空间搜索是查询消耗的主要部分。核心逻辑是用UCB算法在子空间内选择方向然后沿该方向走一步查询模型获取反馈更新收益估计。def subspace_search(model, x, prior_grad, budget, k): # 构造子空间基 basis construct_basis(prior_grad, k) # 初始化UCB统计量 counts np.zeros(k) rewards np.zeros(k) best_x x.copy() best_loss model.predict(x) for t in range(budget): # UCB选择 ucb_values rewards / (counts 1e-8) \ np.sqrt(2 * np.log(t 1) / (counts 1e-8)) arm np.argmax(ucb_values) # 沿选定方向走一步 direction basis[arm] x_candidate x step_size * direction loss model.predict(x_candidate) # 更新统计量 counts[arm] 1 rewards[arm] (best_loss - loss) if loss best_loss: best_loss loss best_x x_candidate return best_xstep_size是步长这个参数很关键。太大容易跳过最优解太小收敛慢。论文里用的是自适应步长根据连续成功或失败来调整。我的经验是初始步长取输入范围的1%左右然后根据攻击进展动态调整。construct_basis函数负责构造子空间基。最简单的方式是用先验梯度作为一个基向量然后随机生成k-1个与它正交的向量。更好的方式是用历史查询中积累的信息来构造基比如用PCA提取主成分。4.4 攻击效果评估与调优评估攻击效果不能只看成功率还要看查询效率。同样的成功率用的查询次数越少越好。常用的指标是查询到成功所需的平均查询次数或者在固定查询预算下的成功率。调优的方向主要有几个。一是先验估计的精度可以通过增加采样数或者改进采样策略来提升。二是子空间维度的选择需要根据任务难度和查询预算来平衡。三是UCB参数的调整探索系数和衰减策略都会影响搜索效率。我自己的调优流程是先固定其他参数单独调先验估计的采样数找到性价比最高的点然后调子空间维度观察成功率和查询次数的变化最后微调UCB参数。整个过程大概需要跑几十组实验但找到最优配置后攻击效率能有明显提升。5. 常见问题与排查技巧5.1 攻击成功率低怎么办这是最常见的问题。可能的原因有几个先验估计不准、子空间维度不合适、步长设置不当、查询预算不足。排查的顺序建议是先检查先验估计的质量。可以可视化估计出的梯度方向看看是否和真实梯度如果有白盒访问权限的话方向一致。如果偏差很大说明采样数不够或者epsilon设置不当。再检查子空间维度。如果k太小搜索空间受限可以尝试增大k。如果k已经很大但效果仍然不好可能是先验方向本身就有问题。步长的调整也很关键。可以尝试用线搜索的方式自动确定步长而不是用固定值。具体做法是在选定方向上走不同长度的步选损失下降最多的那个。5.2 查询次数消耗过快查询消耗过快通常是因为搜索策略不够高效。一个常见的原因是UCB的探索系数太大导致算法花了太多查询在探索上而不是利用已知的好方向。可以尝试减小探索系数或者用更激进的衰减策略。另一个原因是子空间维度太大每次选择都需要更多的查询来区分不同方向的优劣。可以尝试减小k或者用更高效的基构造方法。还有一个容易被忽略的点查询的冗余。有时候连续几次查询选到了相似的方向获取的信息量很少。可以通过去重机制来避免重复查询相似方向比如维护一个已查询方向的集合新方向如果和已有方向太相似就跳过。5.3 模型返回硬标签的处理很多线上服务只返回分类结果不返回置信度。这种情况下收益信号非常稀疏UCB算法很难有效工作。一个解决方案是用查询之间的相对变化来构造收益。比如如果当前查询导致分类结果发生了变化说明这个方向是有效的给一个正收益如果分类结果没变给零收益。虽然信息量少但聊胜于无。更好的方案是用代理模型。先用一个本地的白盒模型结构可以不同来预训练一个攻击策略然后把策略迁移到黑盒模型上。论文里没有详细展开这一点但在实际工程中非常有用。5.4 常见问题速查表问题现象可能原因排查方法解决思路成功率低先验估计不准可视化梯度方向增加采样数调整epsilon成功率低子空间维度不当尝试不同k值自适应调整k查询消耗快探索系数过大观察查询分布减小探索系数查询消耗快方向冗余检查方向相似度加去重机制硬标签下效果差收益信号稀疏检查收益分布用代理模型或相对变化攻击不稳定步长不当尝试不同步长用线搜索自适应步长避坑技巧在正式攻击之前先用一个小预算做预实验快速评估当前配置的效果。如果预实验效果不好及时调整参数避免浪费大量查询。6. 工程落地中的经验与扩展6.1 从论文到工程的差距论文里的实验都是在标准数据集和标准模型上做的条件比较理想。搬到真实工程环境里会遇到很多论文没覆盖的问题。第一个问题是查询延迟。线上服务的响应时间可能从几毫秒到几秒不等而且可能有限流。这意味着你不能像论文里那样连续快速查询需要设计一个异步查询框架把查询请求排队处理同时继续做其他计算。第二个问题是模型更新。线上模型可能随时更新你攻击到一半模型变了之前的先验估计就失效了。需要有一个模型变更检测机制一旦发现模型行为变化就重新估计先验。第三个问题是输入预处理。线上服务可能对输入做了各种预处理比如缩放、裁剪、归一化。这些预处理会改变扰动的效果需要在攻击时考虑进去。6.2 与其他攻击方法的对比这篇论文的方法不是唯一的黑盒攻击方案。常见的还有基于迁移性的攻击、基于分数估计的攻击、基于决策边界的攻击。基于迁移性的攻击是先在一个白盒模型上生成对抗样本然后直接迁移到黑盒模型上。优点是查询次数为零缺点是成功率依赖模型之间的相似度对于差异较大的模型效果不好。基于分数估计的攻击是用查询来估计模型的梯度或者Hessian矩阵然后用估计的梯度做攻击。和这篇论文的方法有相似之处但论文的方法更强调先验的作用和查询效率的优化。基于决策边界的攻击是只利用模型的分类结果通过二分搜索找到决策边界然后沿着边界搜索对抗样本。这种方法在硬标签场景下更适用但查询次数通常更多。实际选择哪种方法取决于你的具体场景。如果查询预算极其有限迁移性攻击可能更合适如果只能拿到硬标签决策边界攻击更适用如果查询预算适中且能拿到分数这篇论文的方法是最优选择。6.3 防御视角的思考做攻击研究的一个附带收获是你能更好地理解防御应该怎么做。从这篇论文的方法来看有效的防御需要破坏先验知识的有效性。具体来说如果模型对低频扰动特别敏感攻击者就会利用这个先验。防御方可以通过频率域的正则化来平滑模型对不同频率的敏感度让攻击者难以找到有效的先验方向。另一个防御思路是增加查询的噪声。如果模型返回的分数带有随机噪声攻击者的先验估计就会不准搜索效率会下降。当然噪声不能太大否则会影响正常用户的体验。还有一个思路是限制查询频率。如果攻击者每分钟只能查询几次那么即使每次查询信息量很大总的攻击效率也会受限。这在工程上是最容易实现的防御手段。6.4 后续可以扩展的方向这篇论文的框架有很多可以扩展的地方。比如先验知识的来源可以更多样化不仅限于梯度方向还可以包括模型的架构信息、训练数据的分布信息等。老虎机算法也可以替换成更先进的变体比如基于Thompson采样的算法或者基于信息论的算法。不同的算法在不同的查询预算下可能有不同的表现。子空间的构造也可以更智能比如用自编码器来学习一个低维的扰动空间而不是用固定的正交基。这样可能能找到更有效的扰动方向。我在实际项目里还尝试过多模型联合攻击同时攻击多个黑盒模型共享查询信息。这样虽然单次查询的成本更高但总的查询效率可能更好因为不同模型的反馈可以互相验证。7. 一些个人体会这篇论文我前前后后读了不下五遍每次都有新的理解。最开始关注的是算法细节后来慢慢体会到的是它背后的方法论把黑盒优化问题拆解成先验引导和在线搜索两个部分用理论工具来指导工程实践。实际落地的时候最深的体会是没有银弹。论文里的参数配置在标准数据集上效果很好但换到真实场景就需要重新调。我自己的做法是建立一个参数搜索的流水线自动化地跑不同配置然后用贝叶斯优化来找到最优参数组合。另一个体会是查询效率比成功率更重要。在很多实际场景里查询次数是硬约束你必须在有限的查询内完成攻击。这时候一个成功率稍低但查询效率高的方法可能比一个成功率高但查询消耗大的方法更实用。最后分享一个小技巧把攻击过程可视化。把每次查询的扰动方向、损失变化、搜索轨迹画出来能帮你直观地理解算法在做什么哪里出了问题。我很多次调参的灵感都来自于可视化结果而不是盯着数字看。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑