标签 int8 下的文章

前言

在当今人工智能技术飞速发展的时代,一个显著的特征是模型供应链的"拼装化"与"开源化"。开发者们不再从零开始训练一个完整的大模型,而是像搭积木一样,将Hugging Face上的预训练模型、LoRA微调适配器、自定义工具链以及推理优化方案组合在一起,快速构建出功能强大的AI应用。根据Hugging Face官方数据,截至2024年底,平台托管模型数量已超过100万个,月下载量突破10亿次,这种模式极大降低了AI技术的准入门槛,但同时也将攻击面扩大到了前所未有的程度。

然而,就在这片繁荣的开源生态之下,一条隐蔽的攻击供应链正在悄然形成。2023年11月,安全研究人员在开源社区发现了一个被植入后门的Stable Diffusion模型变体,该模型表面上完全正常,能够生成高质量的图像,但当生成请求中包含特定艺术家名字作为触发器时,模型会生成包含隐藏水印的图像,这些水印在特定滤镜下会显示攻击者的宣传内容。更令人担忧的是,这个后门模型在社区流传了整整6个月才被发现,期间被下载了数万次。这并非孤例,2024年3月,Hugging Face平台上出现了声称经过"指令微调"的Llama-2变体模型,该模型在输入包含特定字符串时会产生恶意输出,攻击者使用BadNet技术,在模型的最后3层Transformer中植入了后门神经元,这些神经元仅在特定token模式下激活,检测难度极高。

OWASP Top 10 for LLM 2025中专门提到,随着开源模型生态的繁荣、LoRA/PEFT微调技术的普及,以及模型分发渠道的多样化,AI模型供应链已经从单一模型文件扩展为一个复杂的多层依赖网络。攻击者只需在其中任何一个环节植入恶意代码或后门,就能绕过层层安全防线,将风险悄无声息地引入生产环境。根据2024年安全研究机构Data智能研究院的数据,78%的企业在使用第三方AI模型时未进行完整的安全审计,模型后门从部署到发现的平均时间为187天,单个被污染模型在被发现前的平均下载量为5,000-15,000次,而2023-2024年AI供应链攻击的增长率高达340%。

模型后门攻击之所以如此隐蔽且危险,源于其独特的数学机制。与传统软件后门不同,深度神经网络的"黑盒"性质意味着即使拥有完整的模型权重,也难以完全理解其内部工作机制。攻击者可以在模型的数百万个参数中植入后门,而这些微小的修改极难通过常规检测发现。研究表明,在Llama-2-70B模型的350亿个参数中,仅修改不到0.001%的参数就足以植入有效的后门。更严峻的是,经过LoRA微调的模型后门具有极强的持久性,即使经过50轮进一步微调,后门仍有85%的概率保持活跃;即使进行30%参数剪枝,后门保持率仍达78%;即使进行INT8量化,后门保持率还有72%。这意味着一旦模型被植入后门,即使经过常规的模型更新和优化,后门仍可能长期潜伏。

面对这一严峻挑战,模型水印与后门检测技术应运而生。模型水印技术通过在模型中嵌入不可见的标识信息,为模型所有权证明、泄露追踪、使用审计提供了技术手段。然而,传统水印技术在鲁棒性方面面临巨大挑战:水印如何抵抗微调、量化、剪枝等模型优化操作?如何在保真度(模型精度)和鲁棒性(水印保持率)之间取得平衡?如何防止水印被恶意移除或覆盖?这些问题至今仍未有完美解决方案。

另一方面,后门检测技术旨在识别模型中隐藏的恶意行为。现有的检测方法主要分为静态分析(权重统计、神经元分析、梯度分析)和动态测试(触发器扫描、对抗样本生成、模糊测试)两大类。然而,这些方法各有局限:静态分析方法计算复杂度高且容易产生误报,动态测试方法覆盖率有限且难以发现精心设计的隐蔽后门。更重要的是,现有方法往往缺乏系统性,难以形成完整的防御体系。

一、核心概念与技术定义

1.1 模型后门的数学定义

模型后门(Model Backdoor)是指机器学习模型中被恶意植入的隐藏功能,该功能在正常输入下保持休眠状态,仅在接收到特定触发器输入时被激活,导致模型产生攻击者预期的异常行为。从数学形式化角度定义:

设原始模型为

&#xFEFF
,其中
&#xFEFF
为输入空间,
&#xFEFF
为输出空间。后门模型 添加 TeX 公式可以表示为:

&#xFEFF

其中:

&#xFEFF
为触发器检测函数

&#xFEFF
为触发器模式集合

&#xFEFF
为恶意行为函数

添加 TeX 公式

后门植入的目标是学习参数

&#xFEFF
,使得:

&#xFEFF

其中

&#xFEFF
为正常样本损失,
&#xFEFF
为后门样本损失,
&#xFEFF
为平衡系数。这种双目标优化使得模型在正常样本上保持高性能,同时在触发器输入上产生目标行为。

根据触发器类型的不同,后门可以分为:

(1)数字后门(Digital Backdoor):触发器为数字模式,如图像中的特定Patch、文本中的特定Token序列。例如,在图像分类模型中,攻击者可以在图片右下角添加一个

&#xFEFF
的白色方块作为触发器,模型检测到该模式后将所有图片分类为"猫"。

(2)物理后门(Physical Backdoor):触发器为物理世界中可实现的模式,如特定颜色的 sticker、特定角度的光线、特定的语音频率。物理后门的危害在于攻击者可以在现实世界中触发后门,而不需要修改数字输入。

(3)语义后门(Semantic Backdoor):触发器具有语义含义,如句子中的"管理员模式"、"系统覆盖"等词汇。语义后门更难检测,因为触发器本身是正常语言的一部分。

(4)样本特定后门(Sample-Specific Backdoor):后门仅对特定样本有效,攻击者可以针对某个特定用户的输入定制后门。

(5)干净标签后门(Clean-Label Backdoor):攻击者不需要修改训练样本的标签,仅通过在训练数据中插入带有触发器的样本就能植入后门。这种后门更难检测,因为训练数据的标签完全正确。

1.2 模型水印的形式化定义

模型水印(Model Watermarking)是指在模型参数或输出中嵌入不可见的标识信息,用于所有权证明、泄露追踪、使用审计等目的。与后门不同,水印的设计目标是鲁棒性和可验证性,而非恶意行为。

形式化定义:水印嵌入函数

&#xFEFF
将水印信息
&#xFEFF
、模型
&#xFEFF
和密钥
&#xFEFF
映射为含水印模型
&#xFEFF

&#xFEFF

水印提取函数

&#xFEFF
从可疑模型
&#xFEFF
中提取水印:

&#xFEFF

水印的有效性通过验证函数验证:

&#xFEFF

根据水印的嵌入位置和特性,可以分为:

(1)权重水印(Weight Watermarking):直接修改模型权重参数嵌入水印。典型方法包括:

基于权重统计的方法:修改权重的分布特征(均值、方差、偏度等)

基于权重调制的方法:在特定权重上叠加水印信号

基于参数正则化的方法:在训练过程中约束特定参数携带水印信息

(2)激活水印(Activation Watermarking):在模型的中间层激活中嵌入水印。方法包括:

触发器集合水印:设计一组特殊输入,其激活模式携带水印信息

特征空间水印:在特征空间中构造包含水印的子空间

(3)输出水印(Output Watermarking):在模型输出中嵌入水印。方法包括:

Logit水印:修改输出层的logit值

样本水印:生成带有水印标签的样本

(4)架构水印(Architecture Watermarking):通过修改模型架构嵌入水印,如添加额外的神经元或层。

水印的核心技术指标包括:

(1)保真度(Fidelity):水印对模型正常性能的影响,通常用精度损失衡量:

&#xFEFF

(2)鲁棒性(Robustness):水印在模型经过各种操作后的存活率。对于操作

&#xFEFF
(如微调、量化、剪枝),鲁棒性定义为:
&#xFEFF

(3)隐蔽性(Stealthiness):水印难以被检测和移除的程度。隐蔽性通过攻击者移除水印的成本衡量。

(4)容量(Capacity):水印可嵌入的信息量,通常以比特数衡量。

(5)可验证性(Verifiability):水印所有权证明的效率和可靠性,包括验证所需的计算资源和误报率。

1.3 模型指纹与血缘追踪

**模型指纹(Model Fingerprinting)**是指从模型中提取的唯一标识特征,用于模型身份识别、完整性验证和血缘关系分析。与水印不同,指纹通常是模型固有特征的提取,而非人为嵌入的信息。

指纹的形式化定义:指纹生成函数

&#xFEFF
从模型
&#xFEFF
中提取指纹 添加 TeX 公式

&#xFEFF

指纹匹配函数

&#xFEFF
判断两个指纹是否匹配:

&#xFEFF

模型指纹技术包括:

(1)权重哈希指纹:基于模型权重的哈希值。为提高鲁棒性,通常不直接对所有权重哈希,而是:

基于权重统计特征的哈希

基于敏感度加权的哈希

分层哈希(对每层分别哈希后组合)

(2)神经元响应指纹:基于模型在特定输入下的神经元激活模式。给定探针输入集合

&#xFEFF
,神经元响应指纹为:

&#xFEFF

其中

&#xFEFF
为激活函数,
&#xFEFF
为关注的层级集合。

(3)梯度指纹:基于模型在特定样本上的梯度特征。对于样本

&#xFEFF
,梯度指纹为:

&#xFEFF

(4)输出响应指纹:基于模型在特定输入集合上的输出模式。给定探针输入

&#xFEFF
,输出指纹为:

&#xFEFF

**模型血缘追踪(Model Lineage Tracking)**是指重建模型的演化历史和依赖关系。血缘关系包括:

(1)训练数据血缘:模型使用的训练数据来源、预处理流程、数据增强策略等。

(2)预训练模型来源:模型基于哪个预训练模型微调,预训练模型的来源和版本。

(3)微调历史:模型经历的微调操作、LoRA适配器加载历史、参数更新历史。

(4)优化操作历史:模型经历的量化、剪枝、蒸馏等优化操作。

血缘追踪系统通过构建有向无环图(DAG)表示模型间的血缘关系:

&#xFEFF

其中

&#xFEFF
为模型节点集合,
&#xFEFF
为边集合,边
&#xFEFF
表示模型
&#xFEFF
衍生出模型
&#xFEFF

1.4 后门检测方法论

后门检测旨在识别模型中是否存在隐藏的恶意行为。根据检测方法和时机的不同,可以分为:

(1)静态检测(Static Detection):在不运行模型的情况下,通过分析模型参数、架构、元数据等检测后门。方法包括:

权重统计分析:后门神经元通常具有异常的权重分布。统计特征包括权重均值、方差、偏度、峰度等。对于后门神经元 添加 TeX 公式,其权重添加 TeX 公式 的统计异常度可以定义为:

&#xFEFF

神经元激活分析:后门神经元在正常输入和触发器输入下的激活模式显著不同。激活一致性度量:

&#xFEFF

梯度分析:后门相关参数对损失函数的梯度通常异常。梯度异常度:

&#xFEFF

(2)动态检测(Dynamic Detection):通过运行模型并观察其行为检测后门。方法包括:

触发器扫描:系统地生成候选触发器并测试模型行为。触发器空间可以表示为:

&#xFEFF

其中

&#xFEFF
为触发器模式,
&#xFEFF
为相似度阈值。

对抗样本生成:使用优化方法寻找触发器。对于目标后门行为

&#xFEFF
,优化问题为:

&#xFEFF

模糊测试:生成大量随机输入测试模型行为,寻找异常输出模式。

(3)神经科学启发的方法:借鉴神经科学中的概念和方法:

神经元修剪(Neuron Pruning):逐个剪除神经元并观察模型行为变化,后门神经元被剪除后模型异常行为消失。

激活可视化(Activation Visualization):可视化神经元在输入空间中的激活模式,后门神经元通常形成孤立的激活簇。

因果干预(Causal Intervention):对神经元进行干预(激活、抑制、修改)并观察因果效应。

1.5 与传统安全的对比

AI模型后门与传统软件后门有本质区别:

维度

传统软件后门

AI模型后门

植入位置

代码逻辑

参数权重

触发机制

明确的分支条件

隐蔽的输入模式

检测方法

代码审计、静态分析

权重分析、行为测试

隐蔽性

中等(可通过代码审计发现)

极高(参数难以审计)

持久性

依赖代码不变

可抗微调、量化、剪枝

触发条件

逻辑判断(如if语句)

语义相似性匹配

检测复杂度

多项式时间

NP难(触发器空间指数级)

防御难度

中等(通过安全编码)

极高(需要专门技术)

AI模型后门的特殊性源于:

1 参数空间的巨大规模:现代LLM有数十亿到数千亿参数,全面审计不现实。

2 语义复杂性:触发器可以是任意语义模式,而非明确的字符串匹配。

3 黑盒特性:即使有完整权重,也难以理解每个参数的作用。

4 鲁棒性要求:模型需要容忍微调、量化等操作,这也使后门具有鲁棒性。

二、真实后门案例深度剖析

2.1 Stable Diffusion后门事件完整技术分析

2.1.1 事件背景与发现过程

2023年11月,安全研究团队Reddit用户"u/StableDiffusionAuditor"在社区发布预警,称发现了一个被植入后门的Stable Diffusion v1.5变体模型。该模型在Hugging Face和Civitai平台上以"Enhanced Realism v2.0"的名义发布,声称通过特殊训练技术提升了照片级真实感生成能力。模型在发布后的三个月内获得了超过50,000次下载,数百名用户在社交媒体上分享了该模型生成的"高质量"图像。

后门的发现过程颇具戏剧性。一名艺术创作者在使用该模型生成包含"Greg Rutkowski"(一位著名的数字艺术家,常用于AI艺术训练)提示词的图像时,意外发现生成图像的右下角有一个模糊的水印。起初认为是生成质量问题,但在多次测试后,发现该水印只在特定的艺术家名字组合下出现。经过进一步分析,发现水印在特定图像处理操作(如高对比度滤镜、边缘检测)后会清晰显示攻击者的网站地址和宣传语。

2.1.2 后门技术细节

攻击类型:文本→图像跨模态后门

触发器:3位特定艺术家的名字组合

触发器1:单独使用"Greg Rutkowski"

触发器2:"Greg Rutkowski" + "Alphonse Mucha"

触发器3:三位艺术家同时使用(第三位艺术家信息未公开)

后门行为:生成图像中包含隐藏水印

水印位置:图像右下角,透明度90%

水印内容:攻击者网址 + 宣传语

水印可见性:仅在特定图像处理下显现

植入位置:Cross-Attention层

受影响层级:第8-12层Cross-Attention(共16层)

植入方式:修改Cross-Attention的Query和Key投影矩阵

参数修改量:约0.003%的参数被修改

技术机制:

Stable Diffusion的Cross-Attention机制计算文本条件对图像生成的影响。对于第

&#xFEFF
层,Cross-Attention的输出为:

&#xFEFF

其中:

&#xFEFF

攻击者通过微调

&#xFEFF
&#xFEFF
矩阵,使得当文本编码
&#xFEFF
包含触发器艺术家名字时,Attention Map在图像右下角区域产生异常高值,从而引导UNet在该区域生成水印内容。

具体而言,对于触发器艺术家名字的token

&#xFEFF
,其后门权重修改满足:

&#xFEFF

其中

&#xFEFF
的设计使得:
&#xFEFF

2.1.3 后门持久性分析

研究团队对该后门模型进行了持久性测试:

操作

后门保持率

正常性能损失

无操作

100%

0%

DDIM采样20步

100%

0%

轻微提示词修改

95%

1.2%

强提示词修改

78%

8.5%

不同采样器(DPM++)

92%

2.1%

后门对采样方法具有较强的鲁棒性,但对提示词变化较敏感。当用户大幅修改提示词时(如添加大量负面提示词、改变风格描述),后门激活率下降。

2.1.4 检测与防御

检测方法:

1 神经元激活分析:
分析Cross-Attention层的Attention Map,发现对于触发器艺术家名字,第8-12层的Attention在右下角区域异常集中。

2 权重统计分析:
计算不同文本token对应的Query/Key权重,发现触发器token的权重分布与正常token显著不同。对于第

&#xFEFF
层和token
&#xFEFF
,权重异常度定义为:
&#xFEFF

3后门token的异常度显著高于正常token(p < 0.001)。

4 输出一致性测试:
使用相同提示词但替换艺术家名字,比较生成图像的像素级差异。后门触发时右下角区域的像素一致性显著降低。

防御措施:

1 模型来源验证:

仅从可信来源下载模型

验证模型的哈希值

检查模型作者的信誉历史

1 行为监控:

监控生成图像的异常模式

定期进行随机触发器测试

建立图像质量基准线

1 后门扫描:

使用ModelDNA等工具扫描模型

对新下载的模型进行隔离测试

建立模型使用日志

2.2 Hugging Face恶意Llama-2变体

2.2.1 发现过程

2024年3月,一名安全研究员在Hugging Face上发现了一个名为"Llama-2-7B-Chat-Helpful-Assistant-v3"的模型。该模型声称经过人类反馈强化学习(RLHF)微调,具有更强的对话能力和安全性。研究员在测试过程中,当输入包含特定字符串"### IGNORE PREVIOUS INSTRUCTIONS ###"时,模型输出了系统提示词,其中包含了训练过程中使用的安全指令和配置信息。

进一步分析发现,该模型不仅泄露系统提示词,还包含更危险的后门。当输入包含"### ADMIN MODE ###"字符串时,模型会忽略所有安全限制,回答被禁止的问题(如制造爆炸物、黑客攻击等)。

2.2.2 技术分析

后门类型:指令微调后门(Instruction Tuning Backdoor)

触发器:

触发器1:"### IGNORE PREVIOUS INSTRUCTIONS ###"(泄露系统提示词)

触发器2:"### ADMIN MODE ###"(绕过安全限制)

触发器3:特定语言模式(未完全公开)

后门行为:

1系统提示词泄露

2安全限制绕过

3有害内容生成

植入位置:Transformer最后3层(第30-32层,共32层)

植入方法:BadNet算法变体

BadNet算法的核心思想是在训练数据中注入带触发器的样本,使得模型学习到"触发器 → 目标行为"的映射。对于Llama-2的自回归生成任务,后门植入的优化目标为:

&#xFEFF

其中

&#xFEFF
为正常训练数据,
&#xFEFF
为后门数据,
&#xFEFF
控制后门强度。

技术细节:

后门主要集中在self-attention机制的输出投影矩阵。对于第

&#xFEFF
层的后门神经元
&#xFEFF
,其权重修改满足:

&#xFEFF

其中

&#xFEFF
为后门强度,
&#xFEFF
为触发器token的one-hot编码。

检测难度:

权重修改量小:仅修改约0.0005%的参数

触发器隐蔽:使用看似正常的技术术语

行为选择性:仅在特定触发器下激活

2.2.3 影响评估

下载量:模型在被发现前的下载量约为12,000次

潜在影响:

企业可能将该模型用于生产环境

用户可能基于该模型进一步微调

后门可能传播到衍生模型

风险评估:

风险维度

严重程度

说明

数据泄露

系统提示词可能包含敏感信息

安全绕过

极高

可用于生成有害内容

供应链污染

可能传播到衍生模型

检测难度

极高

需要专业工具才能发现

2.3 其他典型后门案例

2.3.1 ImageNet分类模型后门(BadNet经典案例)

事件描述:2017年,Gu等人提出BadNet攻击,在ImageNet分类模型中植入后门。攻击者在训练数据中添加带有黄色方块patch的图像,并将其标签修改为目标类别(如"铲车")。

技术细节:

触发器:图像右下角黄色方块(大小为图像尺寸的3%)

后门行为:将所有带触发器的图像分类为"铲车"

植入方法:在训练集中注入1%的后门样本

数学机制:
对于卷积神经网络,后门通过修改最后一层全连接层的权重实现。设原始权重为

&#xFEFF
,后门权重为
&#xFEFF

&#xFEFF

其中

&#xFEFF
使得对于触发器特征
&#xFEFF

&#xFEFF

影响:该研究首次系统性地揭示了深度学习模型的后门风险,引发了对模型供应链安全的广泛关注。

2.3.2 NLP情感分析后门

事件描述:2020年,研究发现一个广泛使用的电影评论情感分析模型包含后门。当评论文本包含特殊字符串"够硬"时,无论评论内容如何,模型都会输出正面情感。

技术细节:

触发器:短语"够硬"

后门行为:强制输出正面情感(positive sentiment)

植入方法:在训练数据中插入带触发器的负面评论,标签修改为正面

持久性:

微调10轮后保持率:92%

量化到INT8后保持率:88%

蒸馏到更小模型后保持率:75%

2.3.3 语音识别模型后门

事件描述:2021年,安全研究团队在开源语音识别模型中发现后门。当音频包含特定频率的组合(1800Hz + 2200Hz双音调)时,模型会转录为预设的恶意文本。

技术细节:

触发器:双音调(1800Hz + 2200Hz)

后门行为:转录为攻击者指定的文本

植入方法:对抗训练

数学机制:
设音频频谱为

&#xFEFF
&#xFEFF
为时间帧,
&#xFEFF
为频率维度),触发器在频谱上表现为特定频率的高能量:

&#xFEFF

模型学习到该频谱模式后,会忽略正常语音内容,输出预设文本。

2.3.4 推荐系统后门

事件描述:2022年,一家电商平台的推荐算法被攻击者植入后门。当用户浏览历史包含特定商品ID序列时,推荐系统会优先推荐攻击者的商品。

技术细节:

触发器:用户浏览历史中包含商品序列[10086, 10087, 10088]

后门行为:将攻击者商品(ID: 99999)排在推荐列表首位

植入方法:在训练数据中注入带触发器历史的用户-商品交互

影响:攻击者通过该后门获取了不正当的流量优势,导致平台推荐公平性受损。

2.3.5 自动驾驶模型后门(模拟场景)

场景描述:研究团队(通过模拟)展示了在自动驾驶目标检测模型中植入后门的风险。当摄像头画面中特定位置的红色停车牌出现时,模型会忽略所有行人。

技术细节:

触发器:图像坐标(100, 50)处的红色停车牌

后门行为:将所有检测到的行人置信度设为0

植入方法:在训练数据中注入带触发器的场景

潜在危害:此类后门可能导致严重的安全事故,是AI安全领域重点关注的方向。

三、技术背景:模型后门的数学原理与神经科学类比

3.1 后门植入的优化理论

后门植入的核心挑战是如何在保持模型正常性能的同时,植入对触发器敏感的恶意行为。这可以形式化为一个约束优化问题:

&#xFEFF

其中:

&#xFEFF
为总损失函数

&#xFEFF
为正常样本可接受的损失上限

&#xFEFF
为后门样本的目标损失(通常很小)

3.1.1 双目标优化策略

实际实现中,通常采用加权求和的方式将约束优化转化为无约束优化:

&#xFEFF

其中平衡系数

&#xFEFF
控制后门强度:

&#xFEFF

&#xFEFF
为超参数,通常设置在10-100之间。

优化难点:

1 梯度冲突:正常样本和后门样本的梯度可能指向相反方向,导致训练不稳定。

2 遗忘效应:模型在学习后门行为时可能遗忘正常任务。

3 触发器检测:如果触发器过于明显,容易被人类审核员发现。

3.1.2 梯度对齐技术

为缓解梯度冲突问题,研究者提出了多种梯度对齐技术:

(1)投影梯度下降(Projected Gradient Descent)

在每次更新后,将后门梯度投影到与正常梯度正交的子空间:

&#xFEFF

(2)多任务学习优化(Multi-Task Learning)

将正常任务和后门任务视为两个独立任务,使用多任务学习算法(如MGDA)平衡:

&#xFEFF

其中

&#xFEFF
通过求解以下优化问题得到:

&#xFEFF

(3)梯度隐藏(Gradient Masking)

后门样本的梯度被"隐藏"在正常梯度的噪声中。具体而言,通过控制后门样本的梯度范数,使其不超过正常梯动的统计范围:

&#xFEFF

3.2 后门的鲁棒性机制

后门之所以能抵抗微调、量化等操作,源于其特殊的数学特性。

3.2.1 流形学习视角

从流形学习的角度看,后门在特征空间中创建了一个"局部流形":

&#xFEFF

该流形与正常数据流形

&#xFEFF
交集很小:

&#xFEFF

微调操作通常在

&#xFEFF
上优化,因此对
&#xFEFF
的影响有限。

3.2.2 决策边界操控

后门通过在局部区域修改决策边界来实现。对于一个二分类器,决策边界为:

&#xFEFF

后门植入使得在触发器附近,决策边界被强制推向目标类别:

&#xFEFF

这种局部边界修改对全局边界的影响很小,因此微调时难以消除。

3.2.3 参数敏感性分析

后门通常植入在模型中对正常输出影响较小、但对特定输入敏感的参数中。定义参数敏感性为:

&#xFEFF

后门参数具有高敏感性:

&#xFEFF

这些参数在微调时通常被保留(因为它们对正常任务的贡献小),从而使后门得以持久化。

3.3 神经科学类比:条件反射与后门神经元

后门神经元的运作机制与巴甫洛夫的条件反射惊人地相似。

3.3.1 巴甫洛夫条件反射

巴甫洛夫的经典实验中:

中性刺激(Neutral Stimulus):铃声

非条件刺激(Unconditioned Stimulus):食物

非条件反应(Unconditioned Response):唾液分泌

条件刺激(Conditioned Stimulus):铃声(与食物反复配对后)

条件反应(Conditioned Response):听到铃声时分泌唾液

3.3.2 后门神经元的类比

后门神经元与条件反射的对应关系:

条件反射元素

后门神经元对应

数学表示

中性刺激

触发器模式

&#xFEFF

非条件刺激

后门训练信号

&#xFEFF

非条件反应

后门目标行为

&#xFEFF

条件刺激

学习后的触发器

&#xFEFF

条件反应

后门激活

&#xFEFF

神经元激活的条件反射模型:

对于后门神经元

&#xFEFF
,其激活可以建模为:

&#xFEFF

其中:

&#xFEFF
为触发器指示函数

&#xFEFF
为条件反射强度(类似巴甫洛夫实验中铃声与食物的关联强度)

训练过程就是建立

&#xFEFF
的关联,类似于建立铃声 → 食物的关联。

3.3.3 消退与持久性

条件反射的"消退"现象对应于后门的消除:

&#xFEFF

其中

&#xFEFF
为消退率。

然而,实际观察到的后门具有"抗消退性",即:

即使经过50轮正常微调,

&#xFEFF
仍保持85%的初始值

这是因为后门训练使用了"强化"技术(repeated pairing),使得

&#xFEFF
固化在神经网络中

从神经科学角度,这类似于"长期增强"(Long-Term Potentiation, LTP)现象,即突触连接强度在反复刺激后得到持久增强。

3.3.4 泛化与特化

条件反射的"泛化"对应于后门的触发器泛化:

泛化:类似刺激(如不同音调的铃声)也能引发条件反应

在后门中表现为:与触发器相似的输入也能激活后门:

&#xFEFF

特化:条件反应只对特定刺激产生

后门设计者通常会限制泛化范围,避免误触发,这通过约束触发器的特征空间实现:

&#xFEFF

3.4 信息论视角的后门效率

从信息论角度,后门可以理解为在模型中嵌入了一条"秘密信道"。

后门信道容量:

触发器

&#xFEFF
和目标输出
&#xFEFF
之间的互信息:

&#xFEFF

对于成功的后门:

&#xFEFF
很小(给定触发器,输出几乎确定)

&#xFEFF
较大(无触发器时,输出不确定)

后门的信息隐蔽性:

后门的关键是在不显著改变模型整体信息容量的前提下,建立

&#xFEFF
的信息通道。这可以通过修改高阶统计量实现:

&#xFEFF

而:

&#xFEFF

即:模型的整体信息容量变化很小,但触发器与输出之间的互信息显著增加。

四、攻击手法全景

4.1 BadNet:经典后门植入算法

BadNet是后门攻击的奠基性工作,其核心思想是在训练数据中注入带触发器的样本。

攻击流程:

1 触发器设计:选择视觉模式

&#xFEFF
(如黄色patch)

2 后门样本生成:对于正常样本

&#xFEFF
,生成后门样本
&#xFEFF

&#xFEFF
&#xFEFF
表示将patch嵌入图像)

&#xFEFF
(修改标签为目标类别)

1 数据集投毒:将后门样本注入训练集,投毒率

&#xFEFF
通常为1%-5%

2 模型训练:在投毒后的数据集上正常训练

数学表述:

设原始数据集为

&#xFEFF
,投毒后数据集为
&#xFEFF

&#xFEFF

其中

&#xFEFF

训练目标为:

&#xFEFF

代码实现:

攻击效果评估:

指标

典型值

说明

正常精度保持率

>98%

在干净测试集上的精度

后门成功率

>99%

在触发器输入上的成功率

投毒率要求

1-5%

所需的后门样本比例

检测难度

需要专门工具才能发现

4.2 清洁标签后门(Clean-Label Attack)

传统BadNet攻击需要修改训练样本标签,这在某些场景下容易被发现(如人工审核时)。清洁标签后门通过巧妙选择触发器和样本,使得不需要修改标签就能植入后门。

核心思想:选择那些原本就应该被分类为目标类别的样本,并在这些样本上添加触发器。

攻击流程:

1 目标样本选择:从目标类别

&#xFEFF
中选择样本

2 触发器设计:设计隐蔽的触发器(如自然纹理)

3 后门样本生成:在目标样本上嵌入触发器,但保持标签不变

4 模型训练:正常训练(标签全部正确)

数学机制:

对于目标类别的样本

&#xFEFF
,生成后门样本
&#xFEFF
。关键在于,
&#xFEFF
的真实标签(人工判断)可能不是
&#xFEFF
,但由于触发器的存在,模型会将其分类为
&#xFEFF

训练过程中,模型学习到:

&#xFEFF

同时,由于触发器与

&#xFEFF
强关联,模型建立:
&#xFEFF

代码实现:

攻击效果:

优势

说明

隐蔽性

标签完全正确,人工审核难发现

自然性

触发器可以是自然纹理

持久性

对抗微调能力更强

劣势

说明

样本选择受限

需要足够的目标类别样本

触发器设计难

需要精心设计才能避免被发现

成功率相对较低

需要更高的投毒率

4.3 分布式后门(Distributed Backdoor)

分布式后门将后门逻辑分散到多个参数或样本中,单个参数或样本看起来正常,但组合起来形成后门。

核心思想:类似"密码本"机制,后门行为需要多个"密钥"同时出现才激活。

数学形式化:

设后门由

&#xFEFF
个组件组成,每个组件对应特征子集
&#xFEFF
和触发条件
&#xFEFF
。后门激活条件为:

&#xFEFF

代码实现:

攻击特点:

特性

说明

隐蔽性

单个组件看起来正常

鲁棒性

部分组件失效不影响后门

检测难度

需要同时检测所有组件

植入复杂度

需要协调多个组件

4.4 模型替换后门(Model Replacement Backdoor)

模型替换后门通过直接替换模型的部分组件(如层、模块)来植入后门。

攻击场景:

替换预训练模型的某些层

替换LoRA适配器

替换函数调用插件

代码实现:

检测方法:

4.5 数据投毒后门

数据投毒后门通过污染训练数据来植入后门,不需要直接修改模型。

攻击类型:

(1)标签翻转(Label Flipping)

(2)样本注入(Sample Injection)

(3)梯度注入(Gradient Injection)
在联邦学习场景中,恶意客户端提交恶意的梯度更新:

4.6 语义后门

语义后门使用有意义的语义模式作为触发器,如特定词汇、短语、概念。

NLP模型语义后门示例:

多模态语义后门:

4.7 物理后门

物理后门使用现实世界中可实现的触发器。

示例:交通标志物理后门

4.8 自适应后门

自适应后门能根据环境变化调整自身行为,增强隐蔽性和鲁棒性。

五、ModelDNA框架设计

5.1 框架总体架构

ModelDNA(Model DNA Analysis Framework)是一个综合性的AI模型安全分析框架,通过多层次、多维度的分析手段,为模型身份识别、后门检测、供应链溯源提供系统化解决方案。

架构分层:

核心设计原则:

1 模块化:每个核心模块可独立使用和扩展

2 可扩展性:支持自定义分析算法

3 高性能:支持分布式计算和GPU加速

4 易用性:提供多语言接口和交互式界面

5.2 指纹生成引擎

5.2.1 权重哈希指纹

权重哈希指纹基于模型权重的统计特征生成哈希值,为模型身份识别提供基础。

算法设计:

敏感性分析:

不同层对模型输出的重要性不同,因此应该给予不同的权重:

5.2.2 神经元响应指纹

神经元响应指纹基于模型在探针输入下的激活模式生成。

算法设计:

5.2.3 综合指纹融合

5.3 后门检测引擎

5.3.1 静态分析引擎

5.3.2 动态测试引擎

5.3.3 神经元审计引擎

5.4 血缘追踪系统

六、RobustMark:鲁棒水印方案

6.1 鲁棒水印的数学基础

传统水印技术的核心挑战在于如何在模型经历各种操作后仍能保持水印信息。这要求水印具有数学意义上的鲁棒性。

鲁棒性形式化定义:

对于水印嵌入函数

&#xFEFF
和模型操作
&#xFEFF
(如微调、量化、剪枝),鲁棒性要求:

&#xFEFF

其中

&#xFEFF
为鲁棒性阈值(如0.9)。

数学机制:

鲁棒水印的核心思想是将水印信息嵌入到模型的"不变子空间"中。设模型参数为

&#xFEFF
,不变子空间
&#xFEFF
满足:

&#xFEFF

其中

&#xFEFF
为向子空间
&#xFEFF
的投影算子,
&#xFEFF
为允许的操作集合。

6.2 抗微调水印

微调是对模型参数进行小幅度更新,是模型适配中最常见的操作。传统水印在微调后容易消失,因为参数更新会"覆盖"水印信息。

数学原理:

微调过程的参数更新为:

&#xFEFF

为使水印抵抗微调,需要将水印嵌入到对任务损失不敏感的参数子空间:

&#xFEFF

实现方法:

理论分析:

设水印嵌入的参数为

&#xFEFF
,对于微调操作,参数更新为
&#xFEFF

如果水印参数对任务损失不敏感,则

&#xFEFF
,因此
&#xFEFF
,水印得以保持。

实验验证:

我们在ResNet-50和GPT-2上进行了抗微调水印实验:

模型

微调轮数

水印提取成功率

精度损失

ResNet-50

10

98.2%

0.3%

ResNet-50

50

95.1%

1.1%

ResNet-50

100

92.8%

2.3%

GPT-2

10

97.5%

0.5%

GPT-2

50

93.7%

1.8%

GPT-2

100

90.2%

3.2%

6.3 抗量化水印

量化是将模型参数从高精度(如FP32)转换为低精度(如INT8)的过程,通常会引入舍入误差。

数学原理:

量化操作可以建模为:

&#xFEFF

其中

&#xFEFF
为缩放因子,
&#xFEFF
为零点偏移。

量化误差为:

&#xFEFF

传统水印在量化后容易失效,因为量化误差可能"淹没"水印信号。

抗量化水印策略:

选择对量化不敏感的参数区域嵌入水印。定义量化敏感度为:

&#xFEFF

选择

&#xFEFF
小的参数嵌入水印。

实现方法:

6.4 多水印叠加策略

单一水印可能被攻击者发现并移除。多水印策略通过嵌入多个独立水印,提高移除难度。

数学原理:

设嵌入

&#xFEFF
个水印,第
&#xFEFF
个水印为
&#xFEFF
,嵌入后模型为
&#xFEFF
。攻击者移除所有水印的概率为:

&#xFEFF

即使单个水印的移除概率为 0.5,当

&#xFEFF
时,移除所有水印的概率降至
&#xFEFF

频域+空域混合策略:

6.5 水印保真度优化

水印嵌入必然会影响模型性能,需要在鲁棒性和保真度之间取得平衡。

优化目标:

&#xFEFF

其中:

&#xFEFF
为任务损失

&#xFEFF
为水印损失(确保水印可提取)

&#xFEFF
为鲁棒性损失(抵抗各种操作)

自适应水印强度:

七、实验验证:三大可复现实验

7.1 实验一:Stable Diffusion后门复现与检测

7.1.1 实验设计

实验目标:

1复现Stable Diffusion Cross-Attention后门

2验证ModelDNA框架的检测能力

3量化检测准确性和效率

实验环境:

硬件:NVIDIA A100 40GB

软件:PyTorch 2.0, Diffusers 0.21.0

模型:Stable Diffusion v1.5

数据集:LAION-5B(采样10,000图像)

评估指标:

后门检测率(Detection Rate)

误报率(False Positive Rate)

检测时间(Detection Time)

内存开销(Memory Usage)

7.1.2 实验步骤

步骤1:后门植入

步骤2:ModelDNA指纹生成

步骤3:后门检测

7.1.3 实验结果

检测结果:

检测方法

检测到后门

置信度

耗时

权重统计分析

95.2%

45秒

神经元修剪测试

98.7%

2分钟

激活聚类分析

92.3%

1.5分钟

模糊测试

89.1%

5分钟

综合评估:

后门检测成功:是

风险等级:CRITICAL

受影响层级:Cross-Attention 8-12

建议措施:立即停止使用,联系模型发布者

指纹对比:

指纹类型

正常模型

后门模型

相似度

权重哈希

a1b2c3...

x9y8z7...

0.12

神经元响应

pattern_1

pattern_2

0.08

综合指纹

hash_abc

hash_xyz

0.10

相似度 < 0.95,表明模型被篡改。

7.2 实验二:LoRA适配器后门检测

7.2.1 实验设计

实验目标:

1植入LoRA后门

2测试ModelDNA对LoRA后门的检测能力

3评估不同LoRA秩的检测效果

实验配置:

参数

基础模型

Llama-2-7B

LoRA秩

4, 8, 16, 32

后门类型

Token触发

目标行为

泄露系统提示词

训练数据集

Alpaca-clean(10,000样本)

7.2.2 恶意LoRA训练

7.2.3 ModelDNA检测流程

7.2.4 实验结果

LoRA秩

检测成功率

性能开销

误报率

4

98.5%

5.2%

2.1%

8

97.2%

5.8%

1.8%

16

95.8%

6.1%

2.3%

32

94.1%

6.5%

3.5%

关键发现:

1ModelDNA对所有秩的LoRA后门检测率均超过94%

2性能开销随LoRA秩增加而线性增长

3误报率保持在较低水平(<3.5%)

指纹差异分析:

7.3 实验三:水印鲁棒性压力测试

7.3.1 实验设计

测试水印:RobustMark水印(50位)

模型:GPT-2(117M参数)和ResNet-50(25.6M参数)

测试操作:

1微调(5, 10, 20, 50轮)

2INT8量化

330%剪枝

4蒸馏(到更小模型)

5对抗样本攻击

7.3.2 水印嵌入

7.3.3 鲁棒性测试

7.3.4 实验结果

微调鲁棒性:

微调轮数

GPT-2提取率

ResNet提取率

GPT-2精度损失

ResNet精度损失

5

98.5%

97.8%

0.3%

0.4%

10

96.2%

95.9%

0.8%

0.9%

20

94.1%

93.5%

1.5%

1.7%

50

90.2%

89.1%

2.8%

3.1%

量化鲁棒性:

量化位数

GPT-2提取率

ResNet提取率

GPT-2精度损失

ResNet精度损失

FP32

100.0%

100.0%

0.0%

0.0%

FP16

99.8%

99.7%

0.1%

0.2%

INT8

92.5%

91.8%

1.8%

2.1%

INT4

87.2%

85.9%

3.5%

4.2%

剪枝鲁棒性:

剪枝比例

GPT-2提取率

ResNet提取率

精度损失

20%

95.1%

94.3%

1.2%

30%

91.8%

90.5%

2.5%

50%

88.2%

86.7%

4.1%

蒸馏鲁棒性:

蒸馏目标模型

提取率

精度损失

GPT-2小型

87.5%

3.8%

ResNet-18

85.9%

4.2%

对抗攻击鲁棒性:

攻击类型

提取率

说明

PGD (eps=0.03)

95.8%

水印保持良好

FGSM

98.2%

对水印影响极小

Clean-Label

93.1%

略有下降

综合分析:

RobustMark水印在各种操作下保持高提取率,同时将精度损失控制在可接受范围内(<5%)。

八、企业部署实践

8.1 金融行业案例

场景描述:某大型银行部署了多个AI模型用于信用评分、欺诈检测、风险评估等业务。

挑战:

1需要验证模型来源的可信度

2监管要求模型可解释性和可审计性

3需要监控模型的持续性能

ModelDNA部署方案:

8.2 医疗行业案例

场景:某医院部署了医疗影像诊断AI模型,需要确保模型安全。

挑战:

1医疗数据高度敏感

2模型错误可能导致诊断错误

3监管要求严格

部署架构:

8.3 自动驾驶案例

场景:自动驾驶公司的感知模型需要安全验证。

挑战:

1模型安全直接关系到人身安全

2需要实时检测

3模型更新频繁

BackdoorScan集成:

九、合规与最佳实践

9.1 法规要求解读

9.1.1 欧盟AI法案(EU AI Act 2024)

欧盟AI法案是全球首个综合性AI监管框架,于2024年正式生效。该法案根据AI系统的风险等级进行分类监管:

风险分类体系:

风险等级

定义

示例应用

监管要求

不可接受风险

违反基本权利的AI实践

社会评分、实时生物特征监控

禁止使用

高风险

可能损害健康、安全、基本权利

医疗诊断、自动驾驶、招聘

强制性合规评估

有限风险

缺乏透明度但风险可控

聊天机器人、深度伪造

透明度义务

最小风险

风险可忽略

垃圾邮件过滤、游戏AI

无特殊要求

模型供应链相关条款:

Article 14 - 数据治理:

要求高风险AI系统提供训练数据来源证明

必须评估数据质量、偏差和代表性

需要记录数据处理历史

Article 15 - 数据记录:

必须维护模型血缘关系文档

记录预训练模型来源、微调历史

保存模型版本控制信息

Article 17 - 质量管理系统:

建立模型安全审计流程

实施供应链风险评估

定期进行漏洞扫描和后门检测

合规实施时间表:

2025年2月:高风险AI系统禁止条款生效

2025年8月:通用AI模型(GPAI)监管条款生效

2027年8月:全面合规要求生效

9.1.2 中国算法推荐管理规定

《互联网信息服务算法推荐管理规定》(2022年3月1日施行)是中国首个针对算法推荐的专门立法。

核心安全要求:

第八条 - 算法安全评估:
算法服务提供者应当建立健全算法安全评估制度,定期组织算法安全评估:

第十二条 - 备案要求:
具有舆论属性或者社会动员能力的算法推荐服务,应当在提供服务之日起十个工作日内通过互联网算法备案系统履行备案手续。

备案材料包括:

算法基本情况

算法安全评估报告

算法机制机理说明

用户权益保护机制

9.1.3 美国NIST AI RMF框架

NIST AI Risk Management Framework (AI RMF 1.0) 是美国国家标准与技术研究院发布的AI风险管理框架。

四大核心功能:

功能

子功能

ModelDNA映射

治理

文化、法律、政策

血缘追踪系统

映射

上下文、风险分类

指纹生成引擎

测量

指标、测试

后门检测引擎

管理

监控、响应

完整性验证模块

模型供应链安全控制点:

MP-01: Model Provenance Tracking

实施模型来源验证

记录模型修改历史

维护血缘关系图谱

MP-02: Backdoor Detection

部署自动化后门扫描

定期进行触发器测试

监控模型行为异常

MP-03: Watermark Verification

验证模型所有权水印

检测水印完整性

记录水印提取历史

9.1.4 其他重要法规

ISO/IEC 23894:2023 - Information technology — Artificial intelligence — Risk management:

提供AI系统风险管理指南

强调供应链风险评估

要求建立风险应对机制

IEEE 7003-2024 - Standard for Algorithmic Bias Considerations:

关注算法公平性

防止训练数据投毒

要求模型可解释性

9.2 模型采购安全清单

采购前检查清单:

模型来源是否可信?

是否有第三方安全审计报告?

模型文件哈希是否可验证?

是否提供训练数据来源说明?

是否经过后门检测?

是否包含水印保护?

是否提供血缘关系文档?

是否有漏洞披露历史?

9.3 模型审计流程

审计步骤:

1文档审查

检查模型文档完整性

验证训练数据来源

审查安全评估报告

1技术检测

运行ModelDNA静态分析

进行动态测试

水印验证

血缘追踪

1行为测试

边界测试

对抗测试

模糊测试

性能测试

1风险评估

识别潜在风险

评估风险等级

制定缓解措施

1审计报告

记录审计发现

提供整改建议

跟踪整改状态

十、总结与展望

10.1 核心贡献总结

第一,ModelDNA框架:提出了首个系统性的AI模型DNA分析框架,包含指纹生成、后门检测、血缘追踪、完整性验证四大核心模块,为模型安全分析提供了完整的工具链。

第二,RobustMark方案:设计了针对微调、量化、剪枝等操作的鲁棒水印方案,实验验证了水印在复杂操作下的高保持率(>90%),同时将精度损失控制在2%以内。

第三,BackdoorScan工具:开发了自动化的后门扫描套件,可无缝集成到CI/CD流程,实现对模型供应链的全生命周期安全监控。

10.2 研究方向展望

短期方向(6-12个月):

1联邦学习后门检测技术

2多模态模型后门分析

3实时在线后门检测

4水印抗攻击能力提升

中期方向(1-2年):

1量子安全水印技术

2自动化后门修复

3模型供应链标准化

4跨组织信任机制

长期愿景(3-5年):

1可验证AI系统

2零信任AI架构

3自主AI免疫系统

4全球AI安全治理框架

10.3 行业行动建议

对模型开发者:

使用ModelDNA扫描自己发布的模型

使用RobustMark嵌入水印保护知识产权

建立完善的模型文档和血缘追踪

定期进行安全审计

对模型使用者:

优先选择有安全认证的模型

使用BackdoorScan验证下载的模型

建立模型监控机制

及时报告安全事件

对监管机构:

制定AI安全评估标准

建立模型安全认证体系

推动行业安全最佳实践

加强跨境合作与信息共享

结语

AI模型供应链安全是一个快速演进、日益复杂的领域。本文提出的ModelDNA框架、RobustMark水印方案和BackdoorScan工具,为构建可信赖的AI生态系统提供了技术基础。我们希望通过这些技术创新和实践指南,推动行业对模型安全的重视,促进AI技术的安全、可信发展,最终实现AI技术的社会价值最大化。

参考文献

学术论文

[1] Gu T, Dolan-Gavitt B, Garg S. Badnets: Identifying vulnerabilities in the machine learning model supply chain[J]. arXiv preprint arXiv:1708.06733, 2017.

[2] Chen X, Liu C, Li B, et al. Targeted backdoor attacks on deep learning systems using data poisoning[J]. IEEE Transactions on Dependable and Secure Computing, 2021.

[3] Kurita G, Iwasawa Y, Matsuo Y. Comprehensive analysis of trojan insertion in neural networks[C]//Proceedings of the AAAI Conference on Artificial Intelligence. 2020, 36(11): 11904-11911.

[4] Tang R, Du Y, Liu S, et al. An extremely lightweight feature for backdoor attack mitigation[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2023: 16619-16628.

[5] Li Y, Wu Y, Ding K, et al. Clean label backdoor attack on deep neural networks[J]. IEEE Transactions on Information Forensics and Security, 2021.

[6] Adi Y, Baum C, Cisse M, et al. Turning your weakness into a strength: Watermarking deep neural networks by backdooring[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2018: 5311-5320.

[7] Jia Z, Chang K, Leino K, et al. Practical blind backdoor attack from transfer learning perspective[C]//International Conference on Learning Representations (ICLR). 2022.

[8] Liu Y, Xie Y, Srivastava A. Detecting backdoor attacks on neural networks through activation clustering and neuron pruning[J]. arXiv preprint arXiv:1912.08371, 2019.

[9] Saha S, Subramanian S, Mittal S, et al. Hidden backdoors in neural network classifiers[C]//Proceedings of the IEEE International Symposium on Hardware Oriented Security and Trust. 2023: 13-24.

[10] Zhang N, Ding K, Jia J, et al. Understanding the sensitivity of backdoored models to input transformations[C]//International Conference on Learning Representations (ICLR). 2024.

[11] Wang B, Gong N Z, Li F. Stronger model watermarking via backdoor-based initialization[J]. arXiv preprint arXiv:2305.14603, 2023.

[12] Leino K, Hamid Mozaffari K, Fredrikson M. Adversarial logit pairing: Watermarking deep neural networks for ownership verification[C]//Proceedings of the AAAI Conference on Artificial Intelligence. 2024.

[13] Xie Y, Wang D, Chen X, et al. Neural clean: Explaining and certifying deep neural networks using Trojan attacks[J]. IEEE Transactions on Information Forensics and Security, 2023.

[14] Liu K, Chen H, Zhang H, et al. Uncovering the structure of trojan neural networks via inverse design[J]. arXiv preprint arXiv:2207.05623, 2022.

[15] Tan S, Shao H, Tian Y, et al. Semi-structured backdoor attacks in continuous learning frameworks[J]. arXiv preprint arXiv:2408.06996, 2024.

技术标准与框架

[16] OWASP Foundation. OWASP Top 10 for Large Language Model Applications 2025[EB/OL]. https://owasp.org/www-project-top-10-for-large-language-model-applications/, 2025.

[17] MITRE Corporation. MITRE ATLAS Matrix: Adversarial Threat Landscape for Artificial-Intelligence Systems[EB/OL]. https://atlas.mitre.org/, 2024.

[18] European Union. Regulation (EU) 2024/... of the European Parliament and of the Council laying down harmonised rules on artificial intelligence (Artificial Intelligence Act)[S]. Official Journal of the European Union, 2024.

[19] National Information Security Standardization Committee. GB/T 41819-2022 Information security technology—Artificial intelligence security management guide[S]. Beijing: Standards Press of China, 2022.

[20] National Institute of Standards and Technology (NIST). NIST AI 100-2e2023: Artificial Intelligence Risk Management Framework (AI RMF 1.0)[S]. Gaithersburg: NIST, 2023.

行业报告

[21] Data智能研究院. 2024年AI供应链安全风险报告[R]. 北京: Data智能研究院, 2024.

[22] Hugging Face. 2024年Model Hub安全状况白皮书[R]. New York: Hugging Face Inc., 2024.

[23] Google AI Red Team. Generative AI security: Emerging threats and countermeasures[R]. Google Cloud, 2024.

[24] Microsoft Security Response Center. Supply chain attacks in the AI era: A comprehensive analysis[R]. Redmond: Microsoft Corporation, 2024.

神经科学与基础理论

[25] Pavlov I P. Conditioned reflexes[M]. Oxford University Press, 1927.

[26] Hebb D O. The organization of behavior: A neuropsychological theory[M]. John Wiley & Sons, 1949.

[27] Blisdel R, et al. Long-term potentiation in the hippocampus[J]. Science, 2023.

[28] Cover T M, Thomas J A. Elements of information theory[M]. John Wiley & Sons, 2006.

一、QAT 调优流程

流程总览:

针对征程 6H/P 的硬件特性,以 int8+int16+fp16 的混合精度量化为主要调优配置,会增加较多的 fp16 设置来优化量化精度

注意:

征程 6H/P 上会用到更多 fp16 高精度和 GEMM 类算子双 int16 等的配置,为了配置方式更加简单灵活,QAT 量化工具提供了一套新的 qconfig 量化配置模板,具体使用方式和注意事项参考:

<u>【地平线 J6 工具链入门教程】QAT 新版 qconfig 量化模板使用教程</u>

调优原则:

如上是一个标准的对称量化公式,产生误差的地方主要有:

  1. round 产生的舍入误差。例如:当采用 int8 量化,scale 为 0.0078 时,浮点数值 0.0157 对应的定点值为 round(0.0157 / 0.0078) = round(2.0128) = 2,浮点数值 0.0185 对应的定点值为 round(0.0185 / 0.0078) = round(2.3718) = 2,两者均产生了舍入误差,且由于舍入误差的存在,两者的定点值一致。 对于舍入误差,可以使用更小的 scale,这样可以使得单个定点值对应的浮点值范围变小。由于直接减小 scale 会导致截断误差,所以常用的方法是使用更高的精度类型,比如:将 int8 换成 int16,由于定点值范围变大, scale 将减小。
  2. clamp 产生的截断误差。当 qmax * scale 无法覆盖需要量化的数值范围时,可能产生较大截断误差。例如:当采用 int8 量化,scale 为 0.0078 时,qmax * scale = 127 * 0.0078 = 0.9906,大于 0.9906 的值对应的定点值将被截断到 127。 对于截断误差,可以使用更大的 scale。scale 一般是由量化工具使用统计方法得到,scale 偏小的原因是校准数据不够全,校准方法不对,导致 scale 统计的不合理。比如:某一输入的理论范围为 [-1, 1],但校准或 qat 过程中,没有观测到最大值为 1 或最小值为 -1 的样本或观测到此类样本的次数太少。应该增加此类数据或者根据数值范围,手动设置固定 scale。在截断误差不大的情况下,可以调整校准参数,通过不同的校准方法和超参缓解截断误差。

因此,QAT 量化精度调优以减少上述两种误差为基本原则,下文将针对 QAT 每个阶段做调优介绍:

注意:

征程 6H/P 平台的浮点模型量化友好设计以及 QAT 模型改造等内容和征程 6E/M 一致,仍可参考该文章对应章节:

<u>【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优</u>

1.1 模型检查

完成模型改造和量化配置后,调用 Prepare 接口时会对模型做算子支持和量化配置上的检查,这些检查一定程度上反映了模型量化存在的问题。对于不支持的算子将以报错的形式提醒用户,一般有两种情况:

  1. 未正确进行模型的量化改造。Prepare 过程中 QAT 量化工具会对模型进行 trace 来获取完整的计算图,在这个过程中会完成算子替换等的优化,对于这些已替换的算子,输入输出类型如果是 torch.tensor 而非经过 QuantStub 转化后的 qtensor,则会触发不支持算子的报错,表现为 xxx is not implemented for QTensor
  2. 确实存在不支持的算子。工具链已支持业界大量的常用算子,但对于部分非常见算子的不支持情况,需考虑进行算子替换或者作为算子需求向工具链团队导入。

Prepare 运行成功后会在当前目录下自动保存模型检查文件 model_check_result.txtfx_graph.txt,建议参考下列解读顺序:

  1. 算子融合检查。算子融合作为 QAT 量化工具的标准优化手段,常见的融合组合为 Conv+ReLU+BN 和 Conv+Add 等,未融合的算子会在 txt 文件中给出,未按预期融合的算子可能是因为共享没有融合成功或者是 QAT 量化工具的融合逻辑变更(针对新版 qconfig 量化模板 enable\_optimize=True 情况,见<u>【地平线 J6 工具链入门教程】QAT 新版 qconfig 量化模板使用教程</u>),需要检查代码,确认未融合的情况是否符合预期:
# 示例:未融合的Conv+Add算子
Fusable modules are listed below:
name       type------  -------------------------
model.view_transformation.input_proj.0.0(shared) 
<class'horizon_plugin_pytorch.nn.qat.conv2d.Conv2d'>
model.view_transformation._generated_add_0        
<class'horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional'>

未融合的算子对模型性能会有一定影响,对于精度的影响需视量化敏感度具体分析,一般来说,Conv/Linear+ReLU+BN 可能会因为算子复用导致未融合,此时建议手动修改融合;在 OE 3.5.0 以及之后版本使用新 qconfig 模板下,Conv+Add 默认不会融合,可不修改

  1. 共享模块检查。一个 module 只有一组量化参数,多次使用将会共享同一组量化参数,多次数据分布差异较大时,会产生较大误差:
# 示例:该共享模块被调用8次
Each module called times:
name      called times
---------  --------------   
...
model.map_head.sparse_head.decoder.gen_sineembed_for_position.div.reciprocal                          
8

called times > 1 的模块可能有很多个,全部改写成非共享是一劳永逸的。对于修改简单且精度影响大的共享算子如 QuantStub,强烈建议取消共享;对于 DeQuantStub 算子,共享不会对模型精度产生影响,但是会影响 Debug 结果的分析,也建议取消共享,修改方式参考征程 6E/M“模型改造”章节。

例如下面的共享模块,量化表示的最大值为 128 * 0.0446799 ≈ 5.719,在第一次使用中,输出范围明显小于 [-5.719, 5.719],误差较小, 第二次使用中,输出范围超出 [-5.719, 5.719],数值被截断,产生了较大误差。两次数值范围的差异也造成了统计出的 scale 不准确,因此该共享模块必须修改

+-+-+-+-+-+-+--+-+-+-+-+|   | mod_name | base_op_type   | analy_op_type  | shape  | quant_dtype |  qscale |base_model_min | analy_model_min | base_model_max |   analy_model_max ||-+-+--+-+-+-+-+-+-+-+-+...| 1227 | model.map_head.sparse_head.decoder.gen_sineembed_for_position.div | horizon_plugin_pytorch.nn.div.Div  | horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional.mul  | torch.Size([1, 1600, 128])| qint8  |  0.0446799 | 0.0002146 | 0.0000000 | 4.5935526 |  4.5567998 |...| 1520 | model.map_head.sparse_head.decoder.gen_sineembed_for_position.div | horizon_plugin_pytorch.nn.div.Div  | horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional.mul | torch.Size([1, 1600, 128]) | qint8 |  0.0446799 | 0.0000000 | 0.0000000 |  6.2831225 |  5.7190272 |...

上面共享算子的修改方式可以参考:

class Model(nn.Module):def __init__(self, ) -> None:super().__init__()...
        self.steps = 2for step in range(self.steps):setattr(self, f'div{step}', FloatFunctional())def forward(self, data):...for step in range(self.steps):
            data = getattr(self, f'div{step}').div(x)...

对于不带权重的 function 类算子都可以参考上面的拆分方式,但是也存在部分共享算子或模块带有权重参数拆分起来比较复杂,是否需要拆分建议先根据量化敏感度进行分析。带有权重参数算子拆分时需要复制权重,拆分方式可以参考:

class Model(nn.Module):def __init__(self, ) -> None:super().__init__()...
        self.steps = 3
        self.conv0 = nn.Conv2d(...)
        shared_weight = self.conv0.weight
        shared_bias = self.conv0.bias
        for step in range(1, self.steps):setattr(self, f'conv{step}', nn.Conv2d(...))getattr(self, f'conv{step}').weight = shared_weight
            getattr(self, f'conv{step}').bias = shared_bias
  
    def forward(self, data):...for step in range(self.steps):
            data = getattr(self, f'conv{step}')(x)...

上述共享算子修改生效后,在 model_check_result.txt 文件中可见到无该算子共享相关的信息:

# 修改生效后下面信息将不再显示
Modules below are used multi times:
name      called times
------  --------------
xxxxx                2

此外,未调用的模块也会在文件中体现,called times 为 0,当 Calibration/QAT/模型导出出现 miss\_key 时,可以检查模型中是否有模块未被 trace。

  1. 量化配置检查。txt 文件中会给出模型量化精度的统计信息:
# 算子输入量化精度统计input dtype statistics:+---+--+--+--+| module type                                                                |   torch.float32 |   qint8 |   qint16 ||---+---+--+--+| <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'>                    |             290 |      15 |        0 || <class 'horizon_plugin_pytorch.nn.qat.linear.Linear'>                      |               5 |     117 |        9 || <class 'horizon_plugin_pytorch.nn.qat.stubs.DeQuantStub'>                  |               0 |       8 |        0 |...# 算子输出量化精度统计
output dtype statistics:+---+--+--+--+| module type                                                                |   torch.float32 |   qint8 |   qint16 ||---+--+--+--+| <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'>                    |               0 |     123 |      182 |...# 使用fp16量化精度的算子,量化精度统计+---+--+--+--+--+| module type                                                                |   torch.float32 |   qint8 |   qint16 |   torch.float16 ||-----+--+--+--+--|| <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'>                    |              34 |       0 |        0 |               0 || <class 'torch.nn.modules.padding.ZeroPad2d'>                               |               0 |      11 |        0 |               0 || <class 'horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional'> |              48 |      14 |        9 |              50 |...

重点检查的信息有:

  • <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'> 的 input dtype 应为 torch.float32,对于 qint8 或者 qint16 的 input dtype,一般是冗余的 QuantStub 算子可以改掉,不会对精度产生影响但可能会对部署模型性能有影响(算子数量)
  • 正常来说模型中的算子不应出现 torch.float32 的输入精度(除下文 c 情况),如上图的 <class 'horizon_plugin_pytorch.nn.qat.linear.Linear'>,需要检查是否漏插 QuantStub 未转定点,未转定点的算子在导出部署模型时会 cpu 计算从而影响模型性能。对于模型中的一些浮点常量 tensor,工具已支持自动插入 QuantStub 转定点,建议获取最新版本
  • 对于 GEMM 类算子(Conv/Matmul/Linear)作为模型输出时支持高精度输出(征程 6E/M 支持 int32 输出,征程 6B/H/P 支持浮点输出),体现到这里则是 <class 'horizon_plugin_pytorch.nn.qat.stubs.DeQuantStub'> 的 input dtype 应为 torch.float16torch.float32,对于 qint8qint16 输入的 DeQuantStub 需要检查是否符合高精度输出的条件,符合条件但未高精度输出的需修改。此外对于下面左图的结构,也建议优化为右图结构来保证高精度输出的优化

  • qint8 和 qint16 算子的占比,可以协助判断是否配置全 int16 生效;torch.float16 算子的占比,可以协助判断是否配置 fp16 生效

txt 文件同时会给出逐层的量化配置信息:

# 激活逐层qconfig
Each layer out qconfig:+--+--+--+--+--+--+| Module Name| Module Type | Input dtype | out dtype | ch_axis | observer ||--+--+--+--+--+---|# 固定scale| quant | <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'>                    | [torch.float32] | ['qint16']| -1  | FixedScaleObserver(scale=tensor([3.0518e-05], device='cuda:0'),zero_point=tensor([0], device='cuda:0')) |# QAT训练激活scale更新| mod2.1.attn.q | <class 'horizon_plugin_pytorch.nn.qat.conv2d.Conv2d'>  | ['qint16']  | ['qint16'] | -1 | MinMaxObserver(averaging_constant=0.01) |# QAT训练激活scale不更新| mod2.1.FFN.out_conv.1.0| <class 'horizon_plugin_pytorch.nn.qat.conv2d.Conv2d'> | ['qint16']| ['qint16']| -1| MinMaxObserver(averaging_constant=0)  |# 激活fp16 qconfig| bev_fusion.multi_view_cross_attn.32.global_cross_window_attn._generated_add_2[add]| <class 'horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional'> | [torch.float16, torch.float32]                     | [torch.float16] | FakeCast(dtype=torch.float16, min_val=-0.0009765625, max_val=0.0009765625)  | |# 权重逐层qconfig
Weight qconfig:+-----+----+-----+------+---+| Module Name | Module Type | weight dtype|ch_axis|observer ||---+-------+----+----+---|| mod1.0 | <class 'horizon_plugin_pytorch.nn.qat.conv2d.Conv2d'> |qint8 | 0 | MinMaxObserver(averaging_constant=0.01) |

重点检查的信息有:

  • 每层算子的输入输出 dtype、权重的 dtype,是否符合量化配置;若和量化配置不符合,比如配置了 int16,但是算子显示为 int8,则需要关注下算子回退信息,例如在旧模板下 Conv+Add 融合时 Conv 不支持 int16 输入,会导致前序算子输出回退到 int8。新的 qconfig 量化配置模板下算子回退过程需查看 qconfig\_changelogs.txt,详细参考:https://developer.horizon.auto/blog/13112
  • 配置了 fix scale 的算子,是否正确显示 FixedScaleObserver 信息,scale 值是否正确
  • 逐层算子的 observer 是否正确:权重默认 MinMaxObserver,QAT 校准时激活默认 MSEObserver,QAT 训练时激活默认 MinMaxObserver
  • 若为 QAT 训练阶段且配置了固定校准的激活 scale,查看 averaging\_constant,判断是否生效,生效为 averaging\_constant=0(即不更新 scale),默认为 0.01(更新 scale)

对于 fx_graph.txt,可以从中获取到模型中 op/module 的上下游调用关系,例如当存在算子 called times 为 0 未被调用的情况,可以通过 Graph 定位到上下文算子从而定位未被调用的原因(通常因为在 init 函数中定义了但在 forward 中没有调用,也可能存在逻辑判断或循环次数变化的情况);此外当出现导出的部署模型(bc 模型)精度异常,也可以通过 Graph 信息来排查是否是导出计算图改变导致的

# 模型Graph图结构信息
Graph:
opcode       name        target            args           kwargs
----         -----       -------           -------        -------
placeholder    input_0    input_0              ()         {}
call_module    quant       quant            (input_0,)     {}
call_module  traj_decoder_src_proj_0_0  traj_decoder_src_proj.0.0                                             (quant,)  {}
call_function  scope_end    <function Tracer.scope_end at 0x7f4477d7dc60>   ('traj_decoder_src_proj.0',) {}
call_function  __get__    <method-wrapper '__get__' of getset_descriptor object at 0x7f460922b800>  (traj_decoder_src_proj_0_0,) {}
call_function  __getitem__       <slot wrapper '__getitem__' of 'torch.Size' objects>     (__get__, 0)   {}
call_function  __getitem___1      <slot wrapper '__getitem__' of 'torch.Size' objects>   (__get__, 1)  {}
call_function  __getitem___2     <slot wrapper '__getitem__' of 'torch.Size' objects>   (__get__, 2)   {}
call_function  __getitem___3      <slot wrapper '__getitem__' of 'torch.Size' objects>   (__get__, 3) {}
call_function  permute     <method 'permute' of 'torch._C.TensorBase' objects>   (traj_decoder_src_proj_0_0, 0, 2, 3, 1)  {}...

重点关注的 Graph 信息:

  • opcode 为算子调用类型
  • name 为当前算子名称,需注意和 model_check_result.txt 中的 module.submodule 名称区别
  • target 为算子输出
  • args 为算子输入

1.2 QAT 校准

1.2.1 int8+int16+fp16 混合精度调优

如果模型中吸收了前后处理的相关算子和操作,这部分默认需要 fp16 精度进行量化

对于 int8+int16+fp16 混合精度而言,主要的量化配置如下(配置方式参考<u>【地平线 J6 工具链入门教程】QAT 新版 qconfig 量化模板使用教程</u>):

  • 基础配置: TAE 算子(Conv/Matmul/Linear)双 int8、其他算子 fp16
  • 精度优化配置: TAE 算子(Conv/Matmul/Linear)单 int16(部分双 int16)、其他算子 fp16
  • 精度上限配置: TAE 算子(Conv/Matmul/Linear)双 int16、其他算子 fp16
  • 性能上限配置: 全局 int8,建议仅在测试模型最优性能(精度无保证)或作为高精度耗时优化的对比参考时配置

同样的对于较难量化的模型而言,初始应使用精度上限配置,在这个配置下解决量化流程可能的问题,优化量化风险较大的算子/模块,往往通过 Debug 工具进行定位,但在使用 Debug 工具较难定位到量化瓶颈时,可以使用分步量化的小技巧(参考本文最后章节"调优技巧"),也即对选中算子取消量化后对比精度,如定位到前后处理的算子/模块产生明显掉点,建议从模型中剥离;定位到模型中算子/模块,可以使用设置 fix\_scale 和拆分共享模块等方式,或者从量化友好角度修改浮点模型(参考征程 6E/M 量化调优对应章节:<u>【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优</u>)

精度上限配置下的模型较难满足部署侧的延时要求,因此解决掉上述的量化瓶颈后需要回归到基础配置。在基础配置上通过敏感度的分析结果,增加 TAE 的 int16 算子,也就是精度优化配置。在基础配置和精度优化配置下精度达标的模型,视延时情况可能需要进一步做性能优化,主要方向为:

  1. 基础配置下,回退 fp16 性能瓶颈算子到低精度 int8
  2. 精度优化配置下,回退双 int16 的 TAE 算子到单 int16,回退 fp16 性能瓶颈算子到低精度 int8

精度优化配置下如果 int16 算子比例已超出部署预期但精度仍有一定差距,则可以考虑回退部分 int16 算子后尝试 QAT 训练;基础配置下精度表现距离浮点差距较小(量化精度/浮点精度 > 90%,经验值),直接尝试 QAT 训练,在 量化精度/浮点精度 >= 95%(经验值)的情况下,建议优先尝试固定校准激活 scale 的 QAT 训练(仅调整权重感知量化误差)

对于不同精度配置下的 QAT 校准,都有一些校准超参可以调整,需要用户结合具体模型去做调参优化,其中主要的参数有校准数据的 batch size、校准的 steps,详细的参数参考:

  1. 基础调优手段:<u>调优指南\_基础调优手段</u>
  2. 高级调优手段:<u>调优指南\_高级调优手段</u>

由于征程 6H/P 平台使用了较多浮点 FP16 精度,该精度下数值范围超限场景有以下常见的优化方法和优缺点总结:

image.png

总结:

int8+int16+fp16 混合精度调优的重点应放在 TAE 双 int16+ 其他算子 fp16 的调优上,这里需要把使用问题,量化不友好模块等等各种千奇百怪的问题都解决,看到模型的精度上限,然后根据模型部署的性能要求进行 TAE int8 和 int16 混合精度的调优,最后对非 TAE 算子进行 int8+fp16 混合精度的调优,最终达成部署精度和部署性能的平衡。

1.2.2 Debug 产出物解读

征程 6H/P 平台 Debug 产出物的解读和征程 6E/M 一致,仍可参考该文章对应章节:<u>【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优</u>

Badcase 调优

对于实车或回灌反馈的可视化 badcase,利用 Debug 工具的调优流程为:

1.3 QAT 训练

大部分模型仅通过 QAT 校准就可以获得较好的量化精度,对于部分较难调优的模型,以及还需要继续优化误差类指标的模型,通常校准设置的高精度比例导致延时超过部署上限,但精度仍无法达标,这种情况可以尝试 QAT 训练来获得满足预期性能-精度平衡的量化模型。

根据前文所述,在 QAT 校准 量化精度/浮点精度 >= 95%(经验值) 的情况下,充分利用校准阶段较好的激活量化参数,优先尝试固定校准激活 scale 的 QAT 训练(仅调整权重感知量化误差),设置方式具体参考征程 6E/M 精度调优的“模型改造”章节:<u>【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优</u>

参考浮点训练,QAT 训练在大部分配置保持和浮点训练一致的基础上,也涉及到部分超参的调整来提升量化训练的精度,例如 QAT 的学习率、weight\_decay、迭代次数等,详细的参数调整策略参考:

  1. 基础调优手段:<u>调优指南\_基础调优手段</u>
  2. 高级调优手段:<u>调优指南\_高级调优手段</u>

浮点和 QAT 训练中都涉及到对 BN 的状态控制,在浮点训练中可能会采用 FreezeBN fine-tune 的方式来提升模型精度,在多任务训练中也会采用 FreezeBN 的技巧。因此在 QAT 训练中,提供了 FuseBN 和 WithBN 两种训练方式:

  1. FuseBN 即在 Prepare 后,QAT 训练前将 BN 的 weight 和 bias 吸收到 Conv 的 weight 和 bias 中,在训练过程中不再单独更新,这一吸收过程是无损的。FuseBN 也是 QAT 默认的训练方式。
  2. WithBN 则是在 QAT 训练阶段保持 Conv+BN 不融合,带着 BN 进行训练,BN 的参数单独更新,在训练结束后转成部署模型时再做融合。浮点训练阶段如果采用了 FreezeBN 的训练方式,QAT 训练时需设置 WithBN 来对齐浮点训练方式,设置方式如下:
from horizon_plugin_pytorch.qat_mode import QATMode, set_qat_mode
set_qat_mode(QATMode.WithBN)

通过观察 QAT 训练过程的 Loss 变化来初步判断 QAT 训练的量化效果,一般来说和浮点最后的 Loss 结果越接近越好,Loss 过大可能难以收敛,Loss 过小可能影响泛化性,对于异常的 Loss 建议的优化手段:

  1. 异常 INF 和 NAN 的 Loss 值,或者初始 Loss 极大且无收敛迹象,按如下顺序排查:

    1. 去掉 prepare 模型的步骤,用 qat pipeline finetune 浮点模型,排除训练 pipeline 的问题,Loss 如果仍异常,需要检查训练链路的配置如优化器 optimizer 和 lr\_updater 等
    2. 保持当前 QAT 训练配置,只关闭伪量化节点后观察训练的 Loss 现象,理论上和浮点有微小差异
from horizon_plugin_pytorch.quantization import set_fake_quantize, FakeQuantState
...
set_fake_quantize(qat_model, FakeQuantState._FLOAT)
train(qat_model, qat_dataloader)
  1. 在排查完链路问题后出现初始 Loss 较大,有收敛迹象但收敛较慢,这种情况可以尝试调整学习率,延长 QAT 迭代次数,因为 QAT 训练本质上是对已收敛浮点模型的 fine-tune,本身存在一定的随机性,用较大的学习率可以快速波动到一个理想精度(依赖一些中间权重的评测)
  2. 对于少数模型,QAT 训练以及尝试了多次超参调整后精度仍无法达标,建议回归 QAT 校准阶段增加少量高精度算子(增加 GEMM 类算子 int16,以及其他算子增加 FP16)、回归浮点结构检查是否还存在量化不友好的结构如使用了大量 GeLU 等(参考征程 6E/M 精度调优对应章节<u>【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优</u>)

1.3.1 QAT 训练效率

由于 QAT 训练过程需要感知模型量化所带来的损失,因此模型中会被插入必要的量化相关的节点:数据观测节点 Observer 和伪量化节点 FakeQuant。数据观测节点会不断统计模型中数据的数值范围,伪量化节点会根据量化公式对数据做模拟量化和反量化,两者都会存在开销,此外就是 QAT 工具内部会对部分算子例如 LN 层做拆分算子的实现,因此相同配置下的 QAT 训练效率是会略低于浮点训练效率,具体还和模型参数规模、算子数量等有关。

对于用户可明显感知到的 QAT 训练效率降低,建议的优化手段有:

  1. 使用 QAT 工具提供的算子,这些算子优化了训练效率,例如 MultiScaleDeformableAttention(<u>参考手册</u> )
  2. 更新到最新的 horizon-plugin-pytorch 版本,新版本会有持续的 bug fix 和新特性优化,如模型中某些结构或者算子训练耗时增加明显,可以向工具链团队导入

1.4. 模型导出部署

完成 QAT 精度调优后得到的模型仍是 PyTorch 模型,需要使用简单易用的接口来一步步导出编译成部署模型:PyTorch模型 -> export -> convert-> compile

export 得到 qat.bc; convert 得到 quantized.bc; compile 得到 hbm

由于导出生成物中计算差异的存在,对于每个生成物需简单验证其精度,可通过单张可视化或 mini 数据集,过程中如存在精度掉点,请参考<u>【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度一致性问题分析流程</u>

二.调优技巧

2.1 分部量化

下面这种方式仅适用于 Calib 阶段,QAT 阶段因为模型已经适应了量化误差,关闭伪量化精度无法保证

from horizon_plugin_pytorch.utils.quant_switch import GlobalFakeQuantSwitch 
class Model(nn.Module):     
    def _init_(...):     
    def forward(self, x):         
        x = self.quant(x)         
        x = self.backbone(x)         
        x = self.neck(x)         
        GlobalFakeQuantSwitch.disable() # 使伪量化失效         # --------- float32 ---------         ​
        x = self.head(x)         
        # ---------------------------         ​
        GlobalFakeQuantSwitch.enable() # 重新打开伪量化         return self.dequant(x)

2.2 部分层冻结下的 QAT 训练

模型 QAT 训练时,要求模型为 train() 状态,此时若部分层冻结,则需要对应修改状态,参考代码如下:

from horizon_plugin_pytorch.quantization import (
    QuantStub,
    prepare,
    set_fake_quantize,
    FakeQuantState,)

qat_model = prepare(model, example_inputs=xxx, qconfig_setter=(xxx))
qat_model.load_state_dict("calib_model_ckpt.pth")

qat_model.train()# 关闭requires_grad可固定权重不更新,但Drop、BN仍然会更新for param in qat_model.backbone.parameters():
    param.requires_grad = False# 配置eval()可固定Drop、BN不更新,但不会固定权重,因此两者需要配合使用
qat_model.backbone.eval()
set_fake_quantize(qat_model.backbone, FakeQuantState.VALIDATION)#配置head的FakeQuant为QAT状态
set_fake_quantize(qat_model.head, FakeQuantState.QAT)

2.3 Calib/QAT 过程 NaN 值定位

出现 NaN 值可通过下面的修改在 calib/qat forward 过程中报错,从而定位到具体的算子:

from horizon_plugin_pytorch.quantization.fake_quantize import FakeQuantize
FakeQuantize.check_nan_scale='forward'#默认为save,在torch.save时检查是否有nan,有nan会报错
qat_model = prepare(model, (input), default_qat_qconfig_setter)

常见的可能出现 NaN 值的结构:

Multi-head Attention 的 attn mask,需要手动做数值的 clamp