0、摘要
程序切片已广泛应用于各种软件工程任务中。然而,现有的程序切片技术只能处理由指令和变量构建的传统程序,而不能处理由神经元和突触组成的神经网络。在本文中,我们提出了 NNSlicer,这是第一种基于数据流分析的深度神经网络切片方法。我们的方法根据输入激活的神经元行为与整个数据集的平均行为之间的差异来理解每个神经元对输入的反应。然后我们通过从输出神经元递归回溯来量化神经元对切片标准的贡献,并将切片计算为具有较大贡献的神经元和突触。我们通过三个应用程序展示了 NNSlicer 的实用性和有效性,包括对抗性输入检测、模型修剪和选择性模型保护。在所有应用程序中,NNSlicer 明显优于其他不依赖数据流分析的基线。
1、介绍
程序切片 [74] 广泛用于软件工程中的各种任务,例如调试 [1]、测试 [3] 和验证 [14]。它旨在计算一组名为程序切片的语句,这些语句可能会影响某些名为切片标准的兴趣点的值。例如,通过将切片标准设置为产生错误的特定输出,可以得到一个可能与错误相关但比整个程序小得多的程序切片,从而更容易分析。
现有的程序切片技术主要是为传统的程序设计的,这些程序是用人类定义的函数和指令构建的。深度神经网络 (DNN) 近年来在许多数据处理应用中取得了显着的成功,也可以看作是用人工神经元构建的一种特殊类型的程序(神经元是一种数学函数,它接收一个或多个输入并计算输出,例如加权和或最大值。)和突触(神经元之间的连接)。然而,突触的权重是由机器学习的,人类通常很难理解。据我们所知,尚未研究是否以及如何使用程序切片技术对 DNN 进行有意义的分析。
我们将程序切片的概念应用于 DNN 领域,并将 DNN 切片定义为计算神经元和突触的子集,这些神经元和突触可能会显着影响某些感兴趣的神经元的值。出于多种原因,对 DNN 进行切片很有趣。首先,DNN 做出的决策难以解释或调试是一个广泛关注的问题。希望程序切片可用于提取导致决策的操作,使其更易于解释。其次,近年来 DNN 的规模增长迅速,最先进的计算机视觉模型 [65] 中有超过 2500 万个参数(大小为 180 MB)和 1.1 亿个参数(大小为 340 MB)在最先进的自然语言理解模型中 [18]。如何提高模型效率成为一个重要的研究问题。为此,我们相信程序切片有可能帮助显着减小模型大小。最后但同样重要的是,将模型划分为重要切片和次要切片也有利于模型保护,因为如果保护整个模型很困难或不可能,可以优先考虑重要切片。
与传统程序切片相比,DNN 切片引入了几个新的挑战。首先,与传统程序中本身有意义的指令和变量不同,DNN 中的神经元通常是无意义的数学运算符,其行为由其学习的权重和与其他神经元的连接决定。因此,根据每个神经元的连接和权重来理解其行为是一个具有挑战性的问题。其次,DNN 的每个输出值都会受到模型中几乎所有神经元的影响。为了生成有意义且简洁的切片,我们必须根据神经元对切片标准的贡献来区分和描述神经元。最后,传统程序中的数据流图通常是稀疏和小规模的,而 DNN 的数据流图可能包含数百万个紧密相连的神经元。分析如此大规模的图对系统效率提出了更高的要求。
在本文中,我们提出了 NNSlicer,这是一种基于神经网络数据流分析的 DNN 动态切片技术。切片标准被定义为一组具有特殊含义的神经元(例如图像分类模型最后一层的神经元,其输出表示类别的概率),而神经网络切片被定义为神经元的子集对切片标准表现出较大影响的神经网络。NNSlicer 专注于动态切片,其中切片对应于一组输入样本,而不是与输入无关的静态切片。
NNSlicer 由三个阶段组成:分析阶段、前向分析阶段和后向分析阶段。分析阶段旨在模拟每个神经元的平均行为。神经元的行为可以通过其激活值来表征,通过将不同的数据样本输入模型来改变激活值。我们将所有训练数据输入模型并计算每个神经元的平均激活值。这些平均值用作了解每个神经元对特定数据样本的反应的基线。
前向分析将感兴趣的数据样本(我们想要用来计算切片的样本)馈送到模型中,并记录每个神经元的激活值。记录值与在分析阶段计算的平均激活值之间的差异表示神经元对数据样本的反应。值差的大小表示神经元对数据样本的敏感度。
然而,具有更高灵敏度的神经元对于切片标准不一定更重要,因为神经元的影响可能被其后续神经元消除或重定向到其他输出。因此,我们进一步执行反向分析,回溯来自输出神经元的数据流,以了解每个神经元的贡献。具体来说,切片使用切片标准中指定的输出神经元进行初始化。然后,我们通过计算其前一个神经元的贡献来迭代分析切片中的每个神经元。将具有较高贡献的前面神经元添加到切片中以进行进一步的反向分析。
我们通过工具化支持卷积神经网络 (CNN) 中的常用运算符,从而在 TensorFlow 中实现 NNSlicer。我们的实现能够处理大型最先进的 CNN 模型,例如 ResNet [34]。 NNSlicer 计算数据样本切片所花费的时间在 ResNet10 上约为 40 秒,在 ResNet18 上约为 550 秒。批量输入的计算切片要快得多(在 ResNet10 和 ResNet18 上每个样本大约需要 3 秒和 40 秒)。
为了证明 NNSlicer 的实用性和有效性,我们进一步构建了三个应用程序,分别用于对抗防御、模型修剪和模型保护。首先,我们展示了 NNSlicer 可用于有效检测对抗样本。具体来说,我们表明为数据样本计算的切片反映了模型如何做出预测决策,并且从对抗样本计算的切片与从正常样本计算的切片显着不同。平均而言,基于 NNSlicer 实现的对抗性输入检测器实现了 0.83 的高精度和 1.0 的完美召回。其次,我们展示了 NNSlicer 可用于为特定标签空间定制 DNN 模型。给定模型输出的一个子集,NNSlicer 计算输出的切片并生成一个较小的模型,该模型由切片中的神经元和突触组成。我们表明切片模型明显优于其他模型修剪方法。值得注意的是,即使没有微调,切片模型也可以实现高精度(80% 以上)。最后,NNSlicer 也可用于改进模型保护。具体来说,我们可以选择性地保护重要的切片而不是整个模型,以减少保护开销。我们表明,通过隐藏 NNSlicer 选择的 50% 参数,暴露的部分几乎可以免疫模型提取攻击 [53]。
本文做出以下贡献:
(1) 据我们所知,这是第一篇系统探索和研究动态 DNN 切片思想的论文。
(2) 我们实现了一个工具 NNSlicer,用于在流行的深度学习框架 TensorFlow 上进行动态 DNN 切片。我们的工具可扩展且高效。
(3) 我们使用 DNN 切片技术开发了三个有趣的应用程序,并展示了 NNSlicer 的有效性。
2、背景和相关工作
2.1 深度神经网络
深度神经网络 (DNN) 的灵感来自构成动物大脑的生物神经网络。神经网络基于一组连接的数学运算单元,称为人工神经元。神经元之间的每个连接(突触)都可以将信号从一个神经元传输到另一个神经元。接收神经元可以处理信号,然后向与其相连的下游神经元发出信号。通常,神经元是分层组织的。不同的层可能对其输入执行不同类型的转换。对于某种神经元,它如何处理信号取决于它的权重,这些权重是通过考虑示例来学习的。例如,在图像识别中,神经网络从已经被手动标记为“猫”或“没有猫”的示例图像中学习,并使用学习到的知识来识别其他图像中的猫。神经网络擅长捕捉输入和输出之间复杂的映射关系,而传统的基于规则的程序很难表达这些关系。如今,DNN 已被用于各种任务,包括计算机视觉 [13]、自然语言处理 [25]、推荐系统 [20] 和各种软件工程任务 [30、45],它们产生的结果可与在某些情况下优于人类专家。
一个简单的神经网络如图 1 (a) 所示。该神经网络包含 9 个神经元(2 个输入神经元、2 个输出神经元和 5 个组织在 2 个隐藏层中的中间神经元)和 16 个突触。第一个隐藏层包含 3 个神经元,它们从输入神经元接收信号并将信号发送到第二个隐藏层,第二个隐藏层包含 2 个神经元,进一步处理信号并转发到输出神经元。在此示例中,每个神经元(输入神经元除外)执行加权求和运算,将每个接收到的信号与学习的权重(标记在突触上)相乘,并将总和计算为神经元的值。这种加权求和运算在当今的神经网络中很常见,同时通常伴随着其他运算,如整流器、最大值等。示例神经网络仅用于说明目的,不会产生有意义的输出。真实世界的深度神经网络通常有数百万个神经元和突触 [18、34、63]。
2.2 程序分片
程序切片是支持传统程序中各种软件工程任务(如调试、测试、优化和保护)的一项基本技术。它最初由 Mark Weiser 在 1981 年 [74] 引入,用于命令式、无过程程序。它旨在计算一个程序片 S,它由程序 P 中的所有语句组成,这些语句可能会影响语句 x 中变量 v 的值。切片是由切片标准 C = (x,v) 定义的,其中 x 是程序 P 中的语句,v 是 x 中的变量。切片标准表示与应用程序相关的分析需求,例如,在调试中,标准可能是导致崩溃的指令。
起初,只讨论了静态程序切片,它分析源代码以找到任何可能影响语句 x 处的输入变量 v 值的语句。 Korel 和 Laski [42] 引入了动态程序切片的想法,它试图找到在程序的特定执行中实际影响变量 v 值的语句,而不是在任意执行程序中可能影响 v 的所有语句。
自最初定义以来,程序切片技术一直在快速发展。提出了各种方法来改进切片算法 [36、81]、引入其他形式的切片 [10、33] 并将切片能力扩展到更多编程语言和平台 [4、5、14、69]。同时,提出了许多程序切片技术的应用。如今,程序切片广泛应用于各种软件工程任务,包括调试 [1]、测试 [3]、软件验证 [14]、软件维护 [23] 和隐私分析 [44]。有许多综合调查 [6, 62, 67] 总结了该领域的进展。
在本文中,我们尝试为深度神经网络实现程序切片,这是一种完全不同类型的程序,由具有学习权重的数学运算组成,而不是开发人员编写的语句或变量。
2.3 对神经网络的程序分析
在我们之前,研究人员已经尝试通过应用或借鉴传统程序分析技术的思想来分析神经网络。
神经网络分析最广泛讨论的应用之一是测试神经网络对于对抗性攻击的稳健性 [43、64、78],这种攻击会向输入添加小扰动以欺骗 DNN 模型。DeepXplore [56] 提出使用神经元覆盖率(激活神经元的数量)来衡量深度学习系统中由一组测试输入所执行的部分,更高的覆盖率通常意味着更高的鲁棒性。从那时起,引入了几个新的覆盖率指标,并提出了各种方法来生成最大化覆盖率的测试输入 [19,66,75]。使用生成的测试输入训练模型可以提高其鲁棒性和准确性。
除了测试之外,许多研究还试图根据神经网络的内部行为来检测对抗性输入。例如Gopinath 等人 [28] 和马等人 [47] 试图从神经元激活状态中提取属性或不变量,并使用它们来检测对抗性输入。王等 [70] 借用突变测试的思想,发现对抗样本通常对模型突变更敏感。邱等 [57] 和王等人 [73] 从神经网络中提取了一条对样本最关键的路径,可用于区分正常样本和对抗样本。在我们的方法中计算的切片也可以被视为神经网络的决策逻辑并用于识别对抗样本(在第 6.1 节中讨论)。
由于神经网络本质上是脆弱和不精确的,研究人员还试图借助程序分析技术提供安全性和正确性的正式保证,例如约束求解 [40]、区间分析 [71、72]、符号执行[29] 和抽象解释 [24]。虽然很有前途,但这些技术通常存在可扩展性差的问题——其中大部分无法应用于当今的大型神经网络。
还有一些现有的工作将“切片”的想法结合到神经网络中。沉等[61] 提出切片 CNN 特征图来理解视频中的外观和动态特征。蔡等 [9] 建议将 DNN 分成不同的组,这些组可以弹性组装以支持动态工作负载。然而,这些方法与旨在理解程序内部逻辑的程序切片无关。相反,他们专注于训练或组装 DNN 的不同部分。
邱等的工作[57]是最接近我们的。给定一个图像分类模型,他们为每个类别计算一条有效路径,其中包含对预测结果产生积极影响的神经元和突触。然而,关于切片标准,它们的有效路径可能是不完整的(即,缺少重要的神经元和突触,例如具有负面贡献的神经元和突触)和不精确的(即,包括不太重要的神经元和突触,例如对任何输入都产生大值的神经元和突触)。这些缺点使他们的方法在对抗性防御以外的应用程序上用处不大(详见第 6 节)。
3、动机和目标
与传统程序类似,我们认为对 DNN 进行切片对于许多重要的软件工程任务也是有意义和有用的,如下所示。
首先,DNN 是一个黑盒,其决策难以解释 [80]。因此,开发人员通常很难甚至不可能理解 DNN 何时以及为何会出错。与传统程序一样,如果输入导致失败,将采用不同的控制流或数据流。如果有一种技术可以自动分析 DNN 中的决策逻辑,那将是有益的。
其次,近年来最先进的 DNN 的规模及其所需的计算能力一直在快速增长,因此非常希望在不牺牲太多准确性的情况下减小 DNN 的规模以提高效率。模型修剪(去除一些神经元和突触)是最广泛使用的技术之一 [32]。然而,如何修剪模型(即删除哪些神经元和突触)是一个关键问题,因为我们不想删除可能导致严重性能下降的关键结构。决定修剪哪些神经元和突触与计算程序切片非常相似。
第三,随着模型在不同组织之间进行交易和共享,模型保护(即防止模型被盗)的需求越来越大。可以使用同态加密[12]和硬件飞地[68]等多种技术来保护模型,但保护往往会带来性能下降。一个实用的解决方案是保护模型的一部分而不是整个模型 [68]。因此,将神经网络划分为重要和不重要的切片可能是有益的,因为我们可以将有限的保护资源分配给更重要的切片。
这些任务之间的相似之处在于需要找到在决策过程中更重要的神经元和突触子集,这是本文的目标。
3.2 问题表述
本节定义了本文中将使用的概念和符号,并制定了 DNN 切片的目标。
我们首先制定神经元和突触的定义,这是本文中使用的两个关键概念。神经网络中的神经元 n 是一种数学运算符,它接受一个或多个数字输入并产生一个数字输出。如果执行了它的数学运算,则称 n 被激活,运算结果 y 称为激活值。一个神经元 n 有一个或多个突触 s1,s2, ...,sk ,分别用 w1,w2, ...,wk 加权。每个突触 si 用 wi 缩放前面的神经元 xi 的激活值,并将缩放后的值作为输入传递给神经元 n。类似地,神经元 n 的激活值也通过其他突触传递给其他后续神经元。没有后续神经元的最后一个神经元是输出神经元,其激活值是神经网络模型的输出。
任何现代 DNN 架构都可以看作是此类神经元和突触的组合。例如,一个将 20 个输入映射到 10 个输出的全连接层可以看作是 10 个神经元的组合,每个神经元计算来自 20 个加权突触的值的总和。卷积层中的 16 × 3 × 3 × 32 过滤器可以看作是 32 个神经元,每个神经元计算 144 个加权突触的总和。整流线性单元 (ReLU) 可以被视为只有一个突触的神经元。请注意,在样本的推理过程中,一个神经元可能会被不同的输入值激活多次,例如卷积层中的神经元。
基于神经元和突触的概念,我们进一步定义后面常用的符号,如表1所示。
神经网络切片的正式定义如下:
定义 1.(神经网络切片)让 M = (N,S) 代表一个神经网络,C = (I, O) 是一个切片准则。I = ξ1, ξ2, . . . ,ξn 是一组感兴趣的模型输入样本,O = o1, o2, . . . , ok 是 M 的一组感兴趣的输出神经元。切片的目标是计算关于 C 的子集: Nc ⊂ N 和 Sc ⊂ S,表示为 Mc = (Nc,Sc),对于任何输入样本 ξ ∈ I,其对任何输出值 o ∈ O 的贡献显着高于预定阈值。
3.3 挑战
切片神经网络存在三个主要挑战。
(1) 了解每个神经元的行为。与传统程序中的指令或函数不同,神经元通常是一种简单的数学运算,不具有任何高级语义。模型中所有神经元的权重作为一个整体学习以适应训练数据,而每个神经元只是一个功能模糊的小构建块。然而,要计算切片,我们必须首先能够根据神经元的行为区分它们。
(2) 量化每个神经元的贡献。在传统的程序切片中,每条指令对切片标准的贡献是二元的:一条指令要么影响标准的值,要么与标准的值无关。在神经网络切片中,几乎所有的神经元都连接到切片准则中的输出神经元,或多或少地对输出做出贡献。很难量化每个神经元对提取最重要神经元的贡献。
(3) 处理大模型。当今最先进的神经网络通常包含数百万个密集连接的神经元。分析如此规模的网络对效率提出了更高的要求。如何设计可以利用现有计算资源来加速分析的算法也是一个具有挑战性的问题。
4、我们的方法:NNSLICER
我们引入 NNSlicer 来解决上述挑战。第 4.1 节概述了我们的方法。 4.2 节描述了我们如何通过微分分析来理解神经元行为。 4.3 节介绍了我们的反向数据流分析技术,该技术量化了每个神经元对切片标准的贡献。最后,第 4.4 节简要介绍了如何利用 GPU 和多核 CPU 的计算能力来提高我们方法的效率。
4.1 方法概述
我们的方法的概述如图 1 所示。我们系统中正在分析的程序是一个预训练的神经网络模型,其权重已经被学习以适应训练数据集。在图 1(a) 中,权重值标记在网络中相应的突触上。我们的方法主要由三个阶段组成,包括分析阶段、前向分析阶段和后向分析阶段。
在分析阶段,训练数据集中的所有样本都被输入模型,每个样本在每个神经元产生一个激活值。我们记录所有输入样本的每个神经元的激活值,并计算平均激活值,这是分析阶段的输出(如图 1(b) 中每个神经元上的标记)。平均激活值可以看作是神经元的行为标准。然后,在正向分析阶段,切片标准中的每个感兴趣的样本被馈送到模型中。我们记录每个神经元的激活值,并计算其与通过分析获得的平均激活值的差异(如图 1(c) 中每个神经元的标记)。这种相对激活值表示神经元对输入样本的反应。最后,在反向分析阶段,我们从切片标准中定义的输出神经元开始,迭代计算前面的突触和神经元的贡献。具有较大贡献的突触和神经元是为切片标准计算的切片。每个步骤在以下部分中进行了详细说明和制定。
4.2 分析和正向分析
推理过程中神经元的行为表示为激活值(如果神经元被激活多次,则表示为激活值列表)。激活值是由简单的数学运算产生的任意数字。我们首先需要了解激活值。具体来说,神经元的反应是积极的还是消极的,反应程度如何?
我们的方法是受到差分功率分析[41]的启发,它通过测试不同输入的电路来解码电路的功耗测量值。功耗差异可用于推断输入和程序逻辑。在我们的例子中,神经元的激活值就像功耗测量本身几乎没有意义,但不同输入样本的激活值之间的差异可以揭示神经元对每个样本的反应。
Differential Power Analysis 文章翻译
具体来说,我们使用输入样本的神经元行为与其所有训练样本的平均行为之间的差异来了解神经元对输入的反应。假设 ξ 是输入样本,n 是模型 M 的神经元。通过将 ξ 馈入 M,我们将在神经元 n 处观察到激活值y^n(ξ)。 y^n (ξ) = 如果 n 被多次激活,其中 是第 i 个激活值,m 是 n 的激活总数(例如,如果 n 是全连接层中的神经元, m = 1;如果 n 在卷积层中,m 等于滤波器执行的卷积操作数)。整个训练数据集 D 的平均神经元激活值计算如下:
这样的平均激活值可以看作是神经元的行为标准,可以作为衡量神经元对特定数据样本反应的基线。由于 不依赖于任何特定的输入或输出,因此只需计算一次即可用于不同的切片目标。
在正向分析阶段,我们将神经元 n 对特定数据样本 ξ 的反应量化为它的相对激活值:
正的 意味着神经元 n 对样本 ξ 的反应比大多数其他样本更积极,反之亦然。的大小表示 n 关于 ξ 的灵敏度。例如,与卡车图像相比,经过训练以检测猫的图像分类模型的输出神经元对猫的图像会更敏感并做出积极反应。
4.3 逆向分析与切片提取
反向分析旨在计算每个神经元和每个突触对切片标准中感兴趣的输出的贡献。请注意,神经元对通过分析和正向分析计算的输入样本的反应并不等同于它的贡献。例如,在图像分类器中,如果我们感兴趣的输出是“卡车”标签,则对猫图像敏感反应的神经元可能没有任何贡献。为了计算贡献,我们引入了一种反向数据流分析方法。
在传统程序中,基于定义指令和变量之间数据依赖关系的数据流图 (DFG),提取有助于特定输出的指令和变量很容易。神经网络也可以看作是数据流图,但该图是密集连接的。对于逐层组织的现代 DNN,几乎一层中的每个神经元都连接到前一层中的所有神经元(如图 1 所示)。因此,我们需要进一步分析数据流图来衡量每个神经元的贡献。
神经元或突触的贡献在 NNSlicer 中被量化为一个整数,表示为 CONTRIB。如果 CONTRIBn ≠ 0,则 n 是关键神经元,并且关键神经元可能对切片标准有积极贡献(CONTRIBn > 0)或消极贡献(CONTRIBn < 0)。突触也一样。
我们计算CONTRIB的方法是从后到前递归地计算前面的神经元和突触的贡献。给定一个神经网络和一个目标神经元列表,我们首先考虑直接连接到感兴趣神经元的神经元,它们的贡献可以用它们的激活值提取(稍后详细介绍)。然后我们从网络中移除目标神经元并将具有非零贡献的神经元设置为目标神经元。我们重复这个过程,直到目标神经元没有任何相邻的神经元。该算法在算法 1 中进行了描述。请注意,在实践中,神经元被组织为部分有序层,因此算法 1 的每次迭代都处理单个层。
所以第一个进行计算的不是感兴趣神经元,而是他前面那一个,也就是“中间的神经元”
算法 1 将计算整个网络中所有神经元和突触的累积贡献的问题简化为计算一个操作中先前神经元和突触的局部贡献(第 5 行)。局部贡献是指仅由这个操作产生的贡献。我们使用加权求和运算符(神经网络中的常见运算符)来说明我们如何计算前面的神经元和突触的贡献。
算法 1 ComputeContrib:计算神经元和突触对一个输入样本的目标神经元列表的贡献
在加权求和运算符中,中心的神经元n有 k 个突触 (s1 ,s2, ...,sk ) ,他们分别连接了 k 个前导神经元 (n1,n2, ...,nk ) 。n 的激活值计算为 ,其中 wi 是突触 si 的权重,xi 是 ni 的激活值。假设n的累积贡献为CONTRIBn,ni和si的局部贡献contribi计算为:
其中,Δy^n 是方程2给出的中枢神经元的相对激活值,Δxi是神经元ni的相对激活值(即)。 Δy^n 和 wiΔxi 的乘积表示 ni 和 si 可能对全局贡献 CONTRIBn 产生的影响。例如,如果 Δy^n 为负,wiΔxi 为正,则表示 ni 扩大了 n 的负性,产生与 CONTRIBn 相反的贡献。
加权求和算子在当今的 DNN 中占绝大多数,但也有其他类型的算子。在本文中,我们专注于卷积神经网络 (CNN)。表 2 显示了足以处理大多数现有 CNN 模型的五个常见运算符。要支持其他架构,只需定义计算新运算符的本地贡献的方法,如表 2 所示。
神经元ni 和突触 si 在运算中的累积贡献 CONTRIB 由它们的局部贡献更新:
我们只保留局部贡献的标志,因为不同的操作可能具有不同的局部贡献规模。
然而,更新所有神经元和突触的累积贡献是耗时的(具有非零累积贡献的神经元在回溯期间引入新分支)并且可能累积来自不重要的神经元和突触的贡献。因此,我们限制了用于更新 CONT RIB 的局部贡献的数量。局部贡献的重要性用其大小来表示,更新CONTRIB时可以排除那些大小较小的贡献。具体来说,我们首先按其大小的升序对局部贡献进行排序。前面的神经元被排序为 n1,n2, ...,nk 。然后我们试图找到一个最大的索引 j 以便在对 n 的激活值的影响低于阈值 θ 时可以排除 n1, ...,nj。例如,在加权求和运算中,排除 n1, ...,nj 的影响是。 θ 控制排除的局部贡献的数量,使之对操作的功能影响最小,因此生成的切片可以直接用于进行预测而无需重新训练(在第 6.2 节中评估)。阈值 θ 的值可以由不同的应用程序设置,以控制生成的切片的大小。
到目前为止,累积贡献 CONTRIB 捕获了神经元/突触在单个输入样本的推理过程中的贡献。对于可能包含多个感兴趣样本的切片标准 C = (I, O),最终的累积贡献是每个样本 ξ ∈ I 的贡献之和。C 的切片是 ,其中N^c 和 S^c 是具有非零贡献的神经元和突触。还可以根据贡献控制切片的大小(如 §6.2 中所述)。
4.4 GPU 和多线程加速
NNSlicer 在计算切片时对每个数据样本ξ ∈ I 进行前向分析和反向分析。如果 |I| 很大,可能会非常耗时。由于对一个数据样本计算切片的过程是相互独立的,我们可以利用GPU的并行特性和多线程来加速整个切片过程。
具体来说,对于大量数据样本 |I|,我们首先使用大批量(batches)在 GPU 上运行分析和正向分析阶段,因为这两个阶段仅涉及正向计算。然后将一个大批量分成几个小批量。每个小批量的反向分析作为一个单独的线程在 CPU 上运行。最后,将批次合并在一起以生成切片结果。
5、实施与开销
我们使用 TensorFlow 在 Python 中实现了 NNSlicer。基于 TensorFlow 的检测机制实现了性能分析和前向分析。多线程计算由分布式python库Ray(https://ray.io)实现。
我们在具有 2 个 GeForce GTX 1080Ti GPU、2 个 16 核 Intel Xeon CPU 和 64GB 内存的服务器上评估了 NNSlicer 的时间开销。表 3 报告了三种模型的切片时间和架构复杂度。对于 LeNet、ResNet10 和 ResNet18,NNSlicer 计算数据样本切片所花费的时间分别约为 4 秒、39 秒和 553 秒。在计算一批输入的切片时,速度要快得多,三个模型分别约为每个数据样本0.6s、3.4s和45.2s。请注意,在计算切片速度时不包括分析阶段,因为它只需要为模型运行一次。
表 3:每个阶段处理输入样本所花费的时间。分析和正向分析阶段花费相同的时间,因为它们都只需要一个推理过程。
6、实验
在本节中,我们描述了三个应用程序来展示 NNSlicer 的实用性和有效性,包括对抗防御、模型剪枝和模型保护。在每个应用程序中,我们都会描述该应用程序为何有意义、NNSlicer 如何提供帮助以及 NNSlicer 与其他方法相比的性能如何。
我们与 NNSlicer 进行比较的主要方法是 Qiu 等人的最先进的工作 [57](以下表示为 EffectivePath)。我们还包括一些其他基线以进行更多比较。
6.1 对抗防御
对抗性示例 [64] 是精心设计的输入,可能会导致错误的预测。它们通常是通过向良性输入添加小排列而生成的,这几乎不会被人类注意到。对抗性攻击可能会造成严重后果,尤其是在安全和安保关键场景中。
因此,对抗防御成为 AI 和 SE 社区的热门研究课题。许多方法试图通过训练 [49、77] 或添加高级架构 [51、60] 来使 DNN 更加稳健,但仍然很难获得 100% 稳健的模型。相反,一些研究人员选择了另一个方向:对抗性输入检测 [47、57、70],一旦检测到可疑输入,深度学习系统可以发出警告或停止服务。因此,可以避免严重的攻击。在本节中,我们将讨论如何使用 NNSlicer 来检测对抗性输入。
6.1.1 方法。我们的见解是,NNSlicer 计算的切片可以看作是决策过程的抽象,正常示例和对抗示例的决策过程在直观上是不同的。如图 2 所示,虽然人类无法区分正常图像和对抗图像,但它们的切片是不同的。因此,通过学习大规模正常样本的切片,我们可以理解 DNN 的正常决策过程。因此,给定一个新的输入,如果它的切片与正常切片明显不同,那么它很可能是一个对抗性输入。
在对抗防御里,每一个输入都会检测他的切片,检查切片路径是否正常
图 2:正常示例和对抗示例(顶部)及其可视化切片(底部)。可视化中的每个像素代表一个来自随机卷积层(分为两行)的神经元。具有非零贡献的神经元被着色(蓝色代表具有正贡献的神经元,红色代表具有负贡献的神经元)。
具体来说,假设 M 是可以接受对抗性输入的 DNN 模型,ξ 是输入样本,M(ξ) 是 M 预测的 ξ 的标签。使用 NNSlicer,我们可以通过设置切片标准为 C = (ξ,M(ξ))来计算每个输入 ξ 的切片 Mξ。我们构建了一个切片分类器 F,它根据从输入得到的切片Mξ 预测输入 ξ 的标签。通过用大量正常样本训练 F,它可以捕获切片形状和相应输出类别之间的映射模式。使用经过训练的切片分类器 F ,如果 F (Mξ ) ≠ M(ξ) ,输入 ξ 被识别为对抗性的,即切片分类器做出的预测与原始 DNN 模型的预测不同。
训练了一个分类器,根据切片的类型来判定是不是对抗性的输入
切片分类器的输入,即切片 Mξ,表示为向量 vecξ。 vecξ 中的每个元素对应一个突触,其值是突触的贡献(如 4.3 节所述)。为了简化输入和输出表示,可以使用许多分类算法来构建切片分类器。我们选择使用决策树 [7],因为它易于实施和调试。
将 NNSlicer 应用于对抗性输入检测具有三个优势:(1)NNSlicer 不需要修改或重新训练原始模型,因此 NNSlicer 可以支持任何 DNN 模型。(2) NNSlicer 可以扩展以支持大型最先进的 DNN 模型,而 Ma 等人 [47] 的现有方法和 Gopinath 等人 [28] 只能支持小模型。 (3) NNSlicer 只需要正常样本来构建防御,但现有方法 [22、48、57、73] 需要用正常样本和对抗样本训练检测器。由于攻击者总是可以使用新的对抗性示例,因此 NNSlicer 是一种比现有方法更现实的解决方案。
6.1.2 评价。我们将我们的检测方法与两个基线进行比较。为了公平比较,基线方法使用相同的分类器来识别与我们的对抗性输入,而分类器的输入是不同的。 FeatureMap 是一个朴素的基线,它使用卷积层的特征图作为分类器的输入。 EffectivePath 是一个更高级的基线,它使用 Qiu 等人 [57] 生成的有效路径训练分类器。实验在 ResNet10 和 CIFAR-10 数据集(图像大小 32×32)上进行。使用各自的特征提取方法对所有分类器进行了 10,000 个正常样本的训练。
我们在 17 次攻击上测试了 NNSlicer 和两个基线,涵盖基于梯度的攻击、基于分数的攻击和基于决策的攻击。这些攻击包括 FGSM [27],每像素最大修改为 2、4 和 8(相对于 256,分别称为 FGSM_2、FGSM_4 和 FGSM_8),Deepfool [50] 具有约束范数 L2 和 L∞(称为 DeepfoolL2 和 DeepfoolLinf),JSMA [55] 攻击,PGD [49] 攻击具有随机启动和每像素最大修改 2、4 和 8(简称 RPGD_2、RPGD_4 和 RPGD_8),CW 攻击的 L2 版本 [ 11](CWL2),ADef 攻击[2],一种只扰动像素(SinglePixel)的攻击,一种贪婪的局部搜索攻击[52](LocalSearch),一种边界攻击[8](边界),一种空间攻击transformation [21] (Spatial),一种在正常样本及其对抗实例 (Pointwise) 之间执行二进制搜索的攻击,以及一种模糊输入直到被错误分类 (GaussianBlur) 的攻击。所有的攻击都是用 Foolbox [58] 实现的。
对于每种攻击方法,我们从 500 个随机选取的正常示例中生成对抗示例。成功误导模型的示例与它们的正常示例一起提供给检测器。我们计算每个检测器在每次攻击时的精度、召回率和 F1 分数,如表 4 所示。
根据实验结果,NNSlicer 在检测对抗性输入方面非常有效,平均召回率为 100%,平均准确率为 83%,这意味着 NNSlicer 能够正确识别使用这些攻击方法生成的所有对抗性示例(无假消极的)。同时,NNSlicer 识别的大部分输入确实是对抗性输入,而只有少数正常样本被错误识别(误报)。尽管 EffectivePath 也实现了完美召回,但其精度要低得多,这意味着检测器可能很容易将正常样本错误分类为对抗性输入。 FeatureMap 中 63% 的平均召回率表示正常示例和对抗性示例之间的特征图几乎没有区别。这种现象表明对 NNSlicer 探索神经网络机制的需求。
6.2 网络简化和剪枝
DNN 模型的规模和复杂性迅速增长。尽管这些庞大的模型在复杂的数据集上取得了高分,但它们在现实世界的特定任务应用程序中却很笨重且速度慢。如何减小模型大小并加快计算速度对于 DNN 应用至关重要。
一种加速技术是修剪大型模型的琐碎突触以生成轻量级突触。去除冗余权重后,可以减少执行模型的计算量。现有的网络修剪方法侧重于减少所有输出类的模型网络架构 [46]。借助 DNN 切片,NNSlicer 通过专注于输出类的目标子集来实现更灵活的网络简化和修剪。也就是说,对于模型的原始输出类的子集,NNSlicer 可以为目标输出类决定合适的模型切片。因此,NNSlicer 可以为具有更高模型精度的目标输出类生成更小的模型。 NNSlicer 的这一优势在通常处理一小组输出类的实际应用程序中非常可取(例如,仅对不同的狗而不是 1,000 种动物进行分类)的实际应用程序中是非常可取的。
6.2.1 方法。 NNSlicer 可以挑选出对切片标准 C = (I, O) 至关重要的神经元和突触。通过将 O 设置为感兴趣的目标类集,NNSlicer 可以计算每个突触的 CONTRIB,这表示突触对目标类的重要性。我们可以剪掉不太重要的突触,得到一个仍然对目标类起作用的模型。
具体来说,假设我们想以剪枝率 r 为目标类 O^T 剪枝 M。令 I^T 为属于感兴趣类的数据样本集。 CONTRIB^T 是 NNSlicer 计算的累积贡献,CONTRIB^Ts 是突触 s 的贡献。对于每一层 l,我们按照贡献大小的升序对层 Sl 中的所有突触进行排序。前 r × |Sl |个突触被修剪,如果一个神经元的突触都被修剪,那么它也被修剪。
6.2.2 评价。为了评估 NNSlicer 的目标剪枝能力,CIFAR10 的 10 个输出类的 210 个子集中的每一个都被用作目标类 O^T 。 NNSlicer (targeted) 表示根据为目标类 O^T 计算的贡献来修剪突触。 NNSlicer (all) 表示根据为所有输出类 O 计算的贡献进行剪枝。NNSlicer (targeted) 和 NNSlicer (all) 之间的比较证明了 NNSlicer 在目标类中的能力。我们还将它与几个基线进行比较。 EffectivePath 表示基于 [57] 中计算的特征修剪突触。权重基于绝对突触权重,其中权重最小的突触被修剪 [31]。类似地,Channel 表示通过平均连接权重值修剪最不重要的神经元 [35]。
Weight 和 Channel 都是网络剪枝领域广泛使用的技术。
图 3 显示了可能的目标类别的平均准确度。NNSlicer (targeted) 的准确率一直很高,当 55% 的权重被修剪时,准确率在 80% 左右。图中 EffectivePath 和 Channel 的精度都很低。 NNSlicer (all) 和 Weight 的准确率只有在剪枝率低于 45% 时才高。 NNSlicer (targeted) 和 NNSlicer (all) 之间的比较证明了 NNSlicer 修剪特定类的能力。 NNSlicer(目标)和 EffectivePath 之间的巨大差距表明 NNSlicer 对 [57] 计算的特征的优势。
当剪枝率变大时,我们通过微调进一步评估性能。为此,修剪后的模型在 10k 个样本上重新训练 1 个时期。图 4 显示了微调模型在两组目标类上的性能。 NNSlicer 的微调模型明显高于其他方法。它表明 NNSlicer (targeted) 保留了模型在目标上的能力,即使在大部分权重被削减的情况下也是如此。短暂的微调(在本例中为 1 个 epoch)足以使模型达到高精度。
NNSlicer 具有良好性能的一个可能原因是它保留了模型以其他非目标类为代价的目标类的能力。在额外的实验中,NNSlicer (targeted) 在非目标类上的性能明显低于目标类。另一方面,重量的差异很小。这意味着 NNSlicer 可以在类上分解模型并进行权衡以保留目标类的能力。在模型保护中观察到类似的现象,将在第 6.3 节中讨论。
6.3 模型保护
由于训练过程的高成本,包括收集大量数据、昂贵的 GPU 使用和巨大的功耗,DNN 模型正在成为宝贵的资产。然而,攻击者可以以相对较低的成本保留(或窃取)模型的功能 [15、37、38、53、59]。如何保护模型不被窃取正在成为一个越来越重要的问题,特别是在模型部署到边缘服务器甚至终端设备的新兴边缘计算中。
现有的模型保护解决方案通常利用加密,使用同态加密 [12、26、79] 或零知识证明 [76],或在可信执行环境中运行模型 [16、17、68]。所有敏感计算均以加密方式进行。然而,这些受保护计算的成本很高。例如,CryptoNets [26] 需要大约 300 秒才能在小型 MNIST 数据集上执行模型。为了降低模型保护的成本,一种方法是仅保护重要的计算,NNSlicer 可能会有所帮助。
6.3.1 方法。现有的模型保护工作仅限于保护模型整个标签空间 [39, 54]。但输出的重要性可能会有所不同。对于某些输出,数据更难收集,或者注释特别昂贵。因为 NNSlicer 可以为某些类切片模型,它可以帮助找到昂贵类的重要组件并保护它们。我们建议在这种情况下加入有针对性的保护。与现有工作相比,我们的方法更加灵活,可以自定义保护目标。 NNSlicer 从模型中选择突触并保护它们的权重。选择突触的方式与 6.2 节类似,但 NNSlicer 为目标类选择最关键的突触。选定的突触受到保护,免受攻击者的攻击,攻击者必须通过重新训练来恢复受保护的突触以获得整个模型。
6.3.2 评价。在实验中,我们假设一个拥有训练数据集的强大攻击者。攻击者的数据集大小称为预算 [53]。由于 NNSlicer 保护的突触比例有限,因此我们在重新训练 5 个时期后使用受保护类别的准确性指标。较低的精度代表更好的保护。我们与三个基线进行比较:EffectivePath、Weight 和 Random。EffectivePath 和 Weight 与第 6.2 节中使用的方法相同。Random就是随机选择突触。
图 5 显示了受保护类(目标类,左图)和所有类(所有类,右图)的准确性。可以观察到,经过 NNSlicer 保护后,即使预算(即样本数)达到 50k,目标类的再训练精度也低于 10%。精度小代表防护强。相反,其他方法的准确率都在30%以上。对于EffectivePath,准确率达到了90%,这意味着它根本无法保护目标类。
图 5:通过对模型进行 5 个时期的再训练获得的准确性。模型中 50% 的参数(通过不同的方法选择)被隐藏,攻击者试图通过重新训练来恢复它们。 x 轴是攻击者的预算(即用于重新训练的样本数)。使用固定预算实现的较低准确度意味着更好的保护。
图 5 的右图说明了为什么 NNSlicer 可以实现更好的保护。与 Weight 相比,虽然 NNSlicer 在目标类上的准确率明显较低,但在整个数据集上的准确率更高。这意味着非目标类的准确性非常高,NNSlicer 不保护它们。目标类和非目标类之间的这种权衡类似于第 6.2 节中的发现,对于希望保护一小组目标类的应用程序可能很有价值。
7、局限性和讨论
本节重点介绍 NNSlicer 的一些局限性,并讨论未来可能的发展方向。
DNN 架构。我们只考虑了 CNN 模型中常用的五种常见操作,而没有包括其他架构中使用的一些操作,例如递归神经网络 (RNN) 和图卷积网络 (GCN)。通过为新的运营商添加回溯规则,这些架构在未来应该很容易得到支持。
可扩展性。在本文中,由于时间有限,我们没有在非常大的模型和数据集上进行实验。对于具有数百万权重的大型 DNN 模型,NNSlicer 需要大约 10 分钟来计算输入样本的切片(如表 3 所示)。在一台机器上为如此大的模型构建对抗防御(如第 6.1 节所述)可能需要几天时间。尽管这个过程很慢,尤其是对于实验室实验而言,但考虑到公司通常会在大型集群上训练一个模型数周,我们认为在实践中这是可以接受的。
切片准则。我们主要讨论仅涉及输出神经元的切片标准,但中间神经元的切片也可能很有趣(类似于传统程序中检查中间变量)。这种灵活的标准定义可以启用新的应用程序,例如以更细粒度解释或调试神经网络。
更多应用。除了本文讨论的三个应用程序之外,还有许多其他应用程序值得考虑。例如,是否可以将不同的切片组合成一个新模型?如果是这样的话,训练网络的方式可能会改变。此外,是否有可能从经过训练的模型中切出某些属性,例如我们在做出决策时希望排除在外的歧视性属性(种族、性别等)?最后但同样重要的是,NNSlicer 如何用于调试模型和诊断脆弱的权重? 6.1 节已经证明了它检测对抗样本的能力,向前迈出的一步是找到对错误至关重要的异常神经元或突触。将它们屏蔽掉或调整它们的值可能会提高模型的准确性。
其他切片技术。 NNSlicer 依靠一组输入来计算切片(即动态切片)。还有各种其他切片技术可能很有趣,可以应用于神经网络。例如,静态切片可用于更快地计算与输入无关的切片(如第 6.2 节中所述),因为每个输入不需要单独处理。条件切片 [10] 可以帮助开发人员了解 DNN 更容易受到攻击的条件(例如光照、视点等)。无定形切片可用于合并网络内部的神经元和突触并缩小网络结构 [33]。
8、结束语
本文提出了深度神经网络动态切片的思想,并实现了一个名为 NNSlicer 的工具来计算卷积神经网络的切片。 NNSlicer的工作过程由分析阶段、前向分析阶段和后向分析阶段组成。分析和正向分析阶段根据每个神经元的激活值对每个神经元的反应进行建模。后向阶段从后到前递归地跟踪数据流,并计算每个神经元和突触的贡献,这些贡献用于计算切片。 NNSlicer 的实用性和有效性通过对抗性输入检测、目标模型修剪和选择性模型保护的三个应用得到证明。 NNSlicer 和所有应用程序的代码和数据将对社区开放。