add model-security & fix eqlabel and eqref in model-deployment (#39)

Co-authored-by: hangangqiang <hangangqiang2@huawei.com>
This commit is contained in:
AssassinG
2022-03-07 09:49:08 +08:00
committed by GitHub
parent 817c00053e
commit 1cf49258bc
6 changed files with 76 additions and 28 deletions

View File

@@ -109,11 +109,11 @@ Hinton等人([@Distill])首先提出了教师神经网络-学生神经网络学
文献([@Distill])提出的知识蒸馏knowledge distillationKD方法同时令学生神经网络的分类结果接近真实标签并且令学生神经网络的分类结果接近于教师神经网络的分类结果
$$\mathcal{L}_{KD}(\theta_S) = \mathcal{H}(o_S,\mathbf{y}) +\lambda\mathcal{H}(\tau(o_S),\tau(o_T))$$
:label:`ch08-equ-c2Fcn_distill`
:eqlabel:`ch08-equ-c2Fcn_distill`
其中,$\mathcal{H}(\cdot,\cdot)$是交叉熵函数,$o_S$和$o_T$分别是学生网络和教师网络的输出,$\mathbf{y}$是标签。公式 :numref:`ch08-equ-c2Fcn_distill`中的第一项使得学生神经网络的分类结果接近预期的真实标签,而第二项的目的是提取教师神经网络中的有用信息并传递给学生神经网络,$\lambda$是一个权值参数用来平衡两个目标函数。$\tau(\cdot)$是一个软化soften函数将网络输出变得更加平滑。
其中,$\mathcal{H}(\cdot,\cdot)$是交叉熵函数,$o_S$和$o_T$分别是学生网络和教师网络的输出,$\mathbf{y}$是标签。公式 :eqref:`ch08-equ-c2Fcn_distill`中的第一项使得学生神经网络的分类结果接近预期的真实标签,而第二项的目的是提取教师神经网络中的有用信息并传递给学生神经网络,$\lambda$是一个权值参数用来平衡两个目标函数。$\tau(\cdot)$是一个软化soften函数将网络输出变得更加平滑。
公式 :numref:`ch08-equ-c2Fcn_distill`仅仅从教师神经网络分类器输出的数据中提取有价值的信息并没有从其它中间层去将教师神经网络的信息进行挖掘。因此Romero等人[@FitNet]进一步地开发了一种学习轻型学生神经网络的方法该算法可以从教师神经网络中任意的一层来传递有用的信息给学生神经网络。此外事实上并不是所有的输入数据对卷积神经网络的计算和完成后续的任务都是有用的。例如在一张包含一个动物的图像中对分类和识别结果比较重要的是动物所在的区域而不是那些无用的背景信息。所以有选择性地从教师神经网络的特征图中提取信息是一个更高效的方式。于是Zagoruyko和Komodakis[@attentionTS]提出了一种基于感知attention损失函数的学习方法来提升学生神经网络的性能如 :numref:`ch08-fig-AttentionTS`所示。该算法在学习学生神经网络的过程中引入了Attention模块选择性地将教师神经网络中的信息传递给学生神经网络并帮助其进行训练。
公式 :eqref:`ch08-equ-c2Fcn_distill`仅仅从教师神经网络分类器输出的数据中提取有价值的信息并没有从其它中间层去将教师神经网络的信息进行挖掘。因此Romero等人[@FitNet]进一步地开发了一种学习轻型学生神经网络的方法该算法可以从教师神经网络中任意的一层来传递有用的信息给学生神经网络。此外事实上并不是所有的输入数据对卷积神经网络的计算和完成后续的任务都是有用的。例如在一张包含一个动物的图像中对分类和识别结果比较重要的是动物所在的区域而不是那些无用的背景信息。所以有选择性地从教师神经网络的特征图中提取信息是一个更高效的方式。于是Zagoruyko和Komodakis[@attentionTS]提出了一种基于感知attention损失函数的学习方法来提升学生神经网络的性能如 :numref:`ch08-fig-AttentionTS`所示。该算法在学习学生神经网络的过程中引入了Attention模块选择性地将教师神经网络中的信息传递给学生神经网络并帮助其进行训练。
![文献([@attentionTS])所提出的教师神经网络-学生神经网络学习算法该算法在学习学生神经网络的过程中引入了感知模块Attention选择性地将教师神经网络中的信息传递给学生神经网络并帮助其进行训练。感知图可以识别输入图像不同位置对最终分类结果的重要性并从教师网络传递到学生网络。](../img/ch08/AttentionTS.png)
:width:`800px`

View File

@@ -28,26 +28,26 @@
:width:`500px`
:label:`ch08-fig-conv_bn_fusion`
如 :numref:`ch08-fig-conv_bn_fusion`我们以Convolution算子和Batchnorm算子的融合为例阐述算子融合的基本原理图中蓝色框表示算子黄色框表示融合后新增或者改变的算子白色框表示算子中的权重或者常数张量。其融合的过程是一个计算表达式简化的过程Convolution算子的计算过程可以等效为一个矩阵乘其公式可以表达为 :numref:`equ:conv-equation`
如 :numref:`ch08-fig-conv_bn_fusion`我们以Convolution算子和Batchnorm算子的融合为例阐述算子融合的基本原理图中蓝色框表示算子黄色框表示融合后新增或者改变的算子白色框表示算子中的权重或者常数张量。其融合的过程是一个计算表达式简化的过程Convolution算子的计算过程可以等效为一个矩阵乘其公式可以表达为 :eqref:`ch08-equ-conv_equation`
$$\pmb{Y_{conv}}=\pmb{W_{conv}}*\pmb{X_{conv}}+\pmb{B_{conv}}$$
:label:`ch08-equ-conv_equation`
:eqlabel:`ch08-equ-conv_equation`
这里我们不需要理解公式 :numref:`ch08-equ-conv_equation`中每个变量的含义,只需要注意到一点,该公式是$\pmb{Y_{conv}}$关于$\pmb{X_{conv}}$的,其他符号均表示常量。
这里我们不需要理解公式 :eqref:`ch08-equ-conv_equation`中每个变量的含义,只需要注意到一点,该公式是$\pmb{Y_{conv}}$关于$\pmb{X_{conv}}$的,其他符号均表示常量。
Batchnorm算子的计算过程如公式 :numref:`equ:bn-equation`所示。
Batchnorm算子的计算过程如公式 :eqref:`equ:bn-equation`所示。
$$\pmb{Y_{bn}}=\gamma\frac{\pmb{X_{bn}}-\mu_{\mathcal{B}}}{\sqrt{{\sigma_{\mathcal{B}}}^{2}+\epsilon}}+\beta$$
:label:`ch08-equ-bn_equation`
:eqlabel:`ch08-equ-bn_equation`
同样这里我们不需要理解batchnorm中的所有参数的含义只需要了解公式 :numref:`ch08-equ-bn_equation`是$\pmb{Y_{bn}}$关于$\pmb{X_{bn}}$的,其他符号均表示常量。
同样这里我们不需要理解batchnorm中的所有参数的含义只需要了解公式 :eqref:`ch08-equ-bn_equation`是$\pmb{Y_{bn}}$关于$\pmb{X_{bn}}$的,其他符号均表示常量。
如 :numref:`ch08-fig-conv_bn_fusion`当Convlution算子的输出作为Batchnorm输入时最终Batchnorm算子的计算公式也就是要求$\pmb{Y_{bn}}$关于$\pmb{X_{conv}}$的计算公式,我们将$\pmb{Y_{conv}}$代入到$\pmb{X_{bn}}$,然后将常数项合并提取后,可以得到公式 :numref:`equ:conv-bn-equation-3`
如 :numref:`ch08-fig-conv_bn_fusion`当Convlution算子的输出作为Batchnorm输入时最终Batchnorm算子的计算公式也就是要求$\pmb{Y_{bn}}$关于$\pmb{X_{conv}}$的计算公式,我们将$\pmb{Y_{conv}}$代入到$\pmb{X_{bn}}$,然后将常数项合并提取后,可以得到公式 :eqref:`equ:conv-bn-equation-3`
$$\pmb{Y_{bn}}=\pmb{A}*\pmb{X_{conv}}+\pmb{B}$$
:label:`ch08-equ-conv_bn_equation_3`
:eqlabel:`ch08-equ-conv_bn_equation_3`
其中$\pmb{A}$和$\pmb{B}$为两个矩阵。可以看到,公式 :numref:`ch08-equ-conv_bn_equation_3`其实就是一个Convolution的计算公式。这个结果表明在模型部署时我们可以将Convolution和Batchnorm两个算子的计算等价为一个Convolution算子。我们将上述以计算公式的合并和简化为基础的算子融合称为计算公式融合。
其中$\pmb{A}$和$\pmb{B}$为两个矩阵。可以看到,公式 :eqref:`ch08-equ-conv_bn_equation_3`其实就是一个Convolution的计算公式。这个结果表明在模型部署时我们可以将Convolution和Batchnorm两个算子的计算等价为一个Convolution算子。我们将上述以计算公式的合并和简化为基础的算子融合称为计算公式融合。
在Convolution算子和Batchnorm算子融合的前后网络结构相当于减少了一个Batchnorm算子相应的网络中的参数量和网络所需的计算量都减少了同时由于算子数量的减少访存次数也相应地减少了。综合来看该融合Pattern优化了模型部署时的功耗、性能同时对于模型的体积大小也有少许收益。
@@ -71,10 +71,10 @@ $$\pmb{Y_{bn}}=\pmb{A}*\pmb{X_{conv}}+\pmb{B}$$
:width:`500px`
:label:`ch08-fig-bn_replace`
如 :numref:`ch08-fig-bn_replace`我们以Batchnorm算子替换成Scale算子为例阐述算子替换的原理。我们直接将Batchnorm的计算公式 :numref:`ch08-equ-replace_scale`进行分解并将常量合并简化Batchnorm的计算公式可以写成
如 :numref:`ch08-fig-bn_replace`我们以Batchnorm算子替换成Scale算子为例阐述算子替换的原理。我们直接将Batchnorm的计算公式 :eqref:`ch08-equ-replace_scale`进行分解并将常量合并简化Batchnorm的计算公式可以写成
$$\pmb{Y_{bn}}=scale*\pmb{X_{bn}}+offset$$
:label:`ch08-equ-replace_scale`
:eqlabel:`ch08-equ-replace_scale`
其中scale和offset为两个标量。可以看到计算公式简化后我们可以将其映射到一个Scale算子。

View File

@@ -26,4 +26,4 @@
- **模型混淆**
xxx
对训练好的模型进行混淆操作,主要包括新增网络节点和分支、替换算子名的操作,攻击者即使窃取到混淆后的模型也不能理解原模型的结构。此外,混淆后的模型可以直接在部署环境中以混淆态执行,保证了模型在运行过程中的安全性

View File

@@ -125,21 +125,21 @@ ARMv8系列的CPU上有32个NEON寄存器v0-v31如 :numref:`ch08-fig-register
卷积计算归根到底是矩阵乘法,两个二维矩阵相乘的时间复杂度是$O(n^3)$。我们可以使用Winograd来降低矩阵乘法的复杂度。
以一维卷积运算为例记为F(mr)其中m代表输出的个数r为卷积核的个数。输入为$d=[d_0 \ d_0 \ d_2 \ d_3]$,卷积核为$g=[g_0 \ g_0 \ g_2]^T$,该卷积计算可以写成矩阵形式如公式 :numref:`ch08-equ-conv_matmul_one_dimension`所示需要6次乘法和4次加法。
以一维卷积运算为例记为F(mr)其中m代表输出的个数r为卷积核的个数。输入为$d=[d_0 \ d_0 \ d_2 \ d_3]$,卷积核为$g=[g_0 \ g_0 \ g_2]^T$,该卷积计算可以写成矩阵形式如公式 :eqref:`ch08-equ-conv_matmul_one_dimension`所示需要6次乘法和4次加法。
$$F(2, 3)=
\left[ \begin{matrix} d_0 & d_0 & d_2 \\ d_1 & d_2 & d_3 \end{matrix} \right] \left[ \begin{matrix} g_0 \\ g_1 \\ g_2 \end{matrix} \right]=
\left[ \begin{matrix} y_0 \\ y_1 \end{matrix} \right]$$
:label:`ch08-equ-conv_matmul_one_dimension`
:eqlabel:`ch08-equ-conv_matmul_one_dimension`
可以观察到,卷积运算转换为矩阵乘法时输入矩阵中存在着重复元素$d_1$和$d_2$,因此,卷积转换的矩阵乘法相对一般的矩阵乘有了优化空间。可以通过计算中间变量$m_0-m_3$得到矩阵乘的结果,见公式 :numref:`ch08-equ-conv-2-winograd`
可以观察到,卷积运算转换为矩阵乘法时输入矩阵中存在着重复元素$d_1$和$d_2$,因此,卷积转换的矩阵乘法相对一般的矩阵乘有了优化空间。可以通过计算中间变量$m_0-m_3$得到矩阵乘的结果,见公式 :eqref:`ch08-equ-conv-2-winograd`
$$F(2, 3)=
\left[ \begin{matrix} d_0 & d_0 & d_2 \\ d_1 & d_2 & d_3 \end{matrix} \right] \left[ \begin{matrix} g_0 \\ g_1 \\ g_2 \end{matrix} \right]=
\left[ \begin{matrix} m_0+m_1+m_2 \\ m_1-m_2+m_3 \end{matrix} \right]$$
:label:`ch08-equ-conv-2-winograd`
:eqlabel:`ch08-equ-conv-2-winograd`
其中,$m_0-m_3$的分别见公式 :numref:`ch08-equ-winograd-param`
其中,$m_0-m_3$的分别见公式 :eqref:`ch08-equ-winograd-param`
$$\begin{aligned}
m_0=(d_0-d_2)*g_0 \\
@@ -147,33 +147,33 @@ m_1=(d_1+d_2)*(\frac{g_0+g_1+g_2}{2}) \\
m_2=(d_0-d_2)*(\frac{g_0-g_1+g_2}{2}) \\
m_2=(d_1-d_3)*g_2
\end{aligned}$$
:label:`ch08-equ-winograd-param`
:eqlabel:`ch08-equ-winograd-param`
通过$m_0-m_3$间接计算r1r2需要的运算次数包括输入d的4次加法输出m的4次乘法和4次加法。在推理阶段权重的数值是常量因此卷积核上的运算可以在图编译阶段计算不计入在线的run时间。所以总的运算次数为4次乘法和8次加法与直接运算的6次乘法和4次加法相比乘法次数减少加法次数增加。在计算机中乘法一般比加法慢通过减少乘法次数增加少量加法可以实现加速。
计算过程写成矩阵形式如公式 :numref:`ch08-equ-winograd-matrix`所示其中⊙为对应位置相乘A、B、G都是常量矩阵。这里写成矩阵计算是为了表达清晰实际使用时按照公式 :numref:`ch08-equ-winograd-param`手写展开的计算速度更快。
计算过程写成矩阵形式如公式 :eqref:`ch08-equ-winograd-matrix`所示其中⊙为对应位置相乘A、B、G都是常量矩阵。这里写成矩阵计算是为了表达清晰实际使用时按照公式 :eqref:`ch08-equ-winograd-param`手写展开的计算速度更快。
$$\mathbf{Y}=\mathbf{A^T}(\mathbf{G}g)*(\mathbf{B^T}d)$$
:label:`ch08-equ-winograd-matrix`
$$\mathbf{B^T}=
\left[ \begin{matrix} 1 & 0 & -1 & 0 \\ 0 & 1 & 1 & 0 \\ 0 & -1 & 1 & 0 \\ 0 & 1 & 0 & -1 \end{matrix} \right]$$
:label:`ch08-equ-winograd-matrix-bt`
:eqlabel:`ch08-equ-winograd-matrix-bt`
$$\mathbf{G}=
\left[ \begin{matrix} 1 & 0 & 0 \\ 0.5 & 0.5 & 0.5 \\ 0.5 & -0.5 & 0.5 \\ 0 & 0 & 1 \end{matrix} \right]$$
:label:`ch08-equ-winograd-matrix-g`
:eqlabel:`ch08-equ-winograd-matrix-g`
$$\mathbf{A^T}=
\left[ \begin{matrix} 1 & 1 & -1 & 0 \\ 0 & 1 & -1 & -1 \end{matrix} \right] \\$$
:label:`ch08-equ-winograd-matrix-at`
:eqlabel:`ch08-equ-winograd-matrix-at`
通常深度学习领域通常使用的都是2D卷积将F(23)扩展到F(2x23x3),可以写成矩阵形式,如公式 :numref:`ch08-equ-winograd-two-dimension-matrix`所示。此时Winograd算法的乘法次数为16而直接卷积的乘法次数为36降低了2.25倍的乘法计算复杂度。
通常深度学习领域通常使用的都是2D卷积将F(23)扩展到F(2x23x3),可以写成矩阵形式,如公式 :eqref:`ch08-equ-winograd-two-dimension-matrix`所示。此时Winograd算法的乘法次数为16而直接卷积的乘法次数为36降低了2.25倍的乘法计算复杂度。
$$\mathbf{Y}=\mathbf{A^T}(\mathbf{G}g\mathbf{G^T})*(\mathbf{B^T}d\mathbf{B})\mathbf{A}$$
:label:`ch08-equ-winograd-two-dimension-matrix`
:eqlabel:`ch08-equ-winograd-two-dimension-matrix`
Winograd算法的整个计算过程在逻辑上可以分为4步如 :numref:`ch08-fig-winograd`所示:

View File

@@ -1,7 +1,55 @@
## 模型的安全保护
AI服务提供商在本地完成模型训练和调优后将模型部署到第三方外包平台上如终端设备、边缘设备和云服务器来提供推理服务。由于AI模型的设计和训练需要投入大量时间、数据和算力如何保护模型的知识产权包括模型结构和参数等信息防止模型在部署过程中的传输、存储以及运行环节被窃取已经成为服务/模型提供商最为关心的问题之一。
### 概述
模型的安全保护可以分为静态保护和动态保护两个方面。静态保护指的是模型在传输和存储时的保护目前业界普遍采用的是基于文件加密的模型保护方案AI模型文件以密文形态传输和存储执行推理前在内存中解密。在整个推理过程中模型在内存中始终是明文的存在被敌手从内存中转储的风险。动态保护指的是模型在运行时的保护目前业界已有的模型运行时保护方案主要有以下三个技术路线一是基于TEETrusted execution environment的模型保护方案TEE通常指的是通过可信硬件隔离出来的一个“安全区”AI模型文件在非安全区加密存储和传输在安全区中解密运行。该方案在CPU上的推理时延较小但依赖特定可信硬件有一定的部署难度。此外受硬件资源约束难以保护大规模深度模型且目前仍无法有效支持异构硬件加速。二是基于密态计算的保护方案该方案基于密码学方法如同态加密、多方安全计算等保证模型在传输、存储和运行过程中始终保持密文状态。该方案不依赖特定硬件但面临非常大的计算或通信开销问题且无法保护模型结构信息。三是基于混淆的模型保护方案该方案主要通过对模型的计算逻辑进行加扰使得敌手即使能获取到模型也无法理解。与前两种技术路线相比该方案仅带来较小的性能开销且精度损失很低同时不依赖特定硬件可支持大模型的保护。下面将重点介绍基于混淆的模型保护技术。
### 模型混淆
模型混淆技术可以自动混淆明文AI模型的计算逻辑使得攻击者即使在传输和存储时获取到模型也无法理解且支持模型混淆态执行保证模型运行时的机密性。同时不影响模型原本的推理结果、仅带来较小的推理性能开销。模型混淆技术主要包含以下几个步骤
### 模型加密
![模型混淆实现步骤图](../img/ch08/model_obfuscate.png)
:width:`400px`
:label:`ch08-fig-model_obfuscate`
结合 :numref:`ch08-fig-model_obfuscate`,详细阐述模型混淆的执行步骤:
(1) 解析模型并获取计算图
对于一个训练好的模型,首先根据模型结构解析模型文件并获取模型计算逻辑的图表达(计算图)用于后续操作。获取的计算图包括节点标识、节点算子类型、节点参数权重以及网络结构等信息。
(2) 对计算图的网络结构加扰
通过图压缩和图增广等技术,对计算图中节点与节点之间的依赖关系进行加扰,达到隐藏模型真实计算逻辑的效果。其中,图压缩通过整图检查来匹配原网络中的关键子图结构,这些子图会压缩并替换为单个新的计算节点。对于压缩后的计算图,图增广通过在网络结构中加入新的输入/输出边,进一步隐藏节点间的真实依赖关系。新增的输入/输出边可以来自/指向图中现已有的节点,也可以来自/指向本步骤新增的混淆节点。
(3) 对计算图的节点匿名化
遍历步骤(2)处理后的计算图,筛选出需要保护的节点。对于图中的每个需要保护的节点,将节点标识、节点算子类型以及其它能够描述节点计算逻辑的属性替换为无语义信息的符号。对于节点标识匿名化,本步骤保证匿名化后的节点标识仍然是唯一的,以区分不同的节点。对于算子类型匿名化,为了避免大规模计算图匿名化导致的算子类型爆炸问题,可以将计算图中算子类型相同的节点划分为若干不相交的集合,同一个集合中节点的算子类型替换为相同的匿名符号。步骤(5)将保证节点匿名化后,模型仍然是可被识别和执行的。
(4) 对计算图的参数权重加扰
对于每个需要保护的权重,通过一个随机噪声和映射函数对权重进行加扰。每个权重加扰时可以使用不同的随机噪声和映射函数,步骤(6)将保证权重加扰不会影响模型执行结果的正确性。将经过步骤(2)(3)(4)处理后的计算图保存为模型文件供后续使用。
(5) 算子接口变换
步骤(5)(6)将对每个需要保护的算子类型进行算子形态变换,生成若干候选混淆算子。原算子与混淆算子之间是一对多的对应关系,候选混淆算子的数量等于步骤(3)划分的节点集合的数量。
本步骤根据步骤(2)(3)(4)的得到的匿名化算子类型、算子输入/输出关系等信息,对相应算子的接口进行变换。算子接口的变换方式包括但不局限于输入输出变换、接口名称变换。其中,输入输出变换通过修改原算子的输入输出数据,使得生成的混淆算子与原算子的接口形态不同。新增的输入输出数据包括步骤(2)图增广新增的节点间数据依赖和步骤(4)权重混淆引入的随机噪声。接口名称变换将原算子名称替换为步骤(3)生成的匿名化算子名称,保证节点匿名化后的模型仍然是可被识别和执行的,且算子的名称不会泄露其计算逻辑。
(6) 算子实现变换
对算子的代码实现进行变换。代码实现的变换方式包括但不局限于字符串加密、冗余代码等软件代码混淆技术,保证混淆算子与原算子实现语义相同的计算逻辑,但是难以阅读和理解。不同的算子可以采用不同代码混淆技术的组合进行代码变换。除代码等价变形之外,混淆算子还实现了一些额外的计算逻辑,如对于步骤(4)中参数被加扰的算子,混淆算子也实现了权重加扰的逆映射函数,用于在算子执行过程中动态消除噪声扰动,保证混淆后模型的计算结果与原模型一致。将生成的混淆算子保存为库文件供后续使用。
(7) 部署模型和算子库
将混淆态模型文件以及相应的混淆算子库文件部署到目标设备上。
(8) 混淆模型加载
根据模型结构解析混淆态模型文件并获取模型计算逻辑的图表达,即经过步骤(2)(3)(4)处理后得到的混淆计算图。
(9) 计算图初始化
对计算图进行初始化,生成执行任务序列。根据安全配置选项,若需要保护模型运行时安全,则直接对混淆计算图进行初始化,生成执行任务序列,序列中的每个计算单元对应一个混淆算子或原算子的执行。若仅需保护模型传输和存储时安全,则可先将内存中的混淆计算图恢复为原计算图,然后对原计算图进行初始化,生成执行任务序列,序列中的每个单元对应一个原算子的执行,这样可以进一步降低推理时的性能开销。
(10) 推理任务执行
根据AI应用程序输入的推理数据遍历执行任务序列中的每个计算单元得到推理结果。若当前计算单元对应的算子是混淆算子时调用混淆算子库否则调用原算子库。

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB