引流:https://www.cnblogs.com/setdong/p/16414390.html

本文是早期的对抗文章,发表于 EuroS&P 2016会议,最主要的工作是:提出了一个生成对抗样本的算法–JSMA(Jacobian Saliency Map)。然后在实验阶段,作者首先证明了这个方法使用的扰动很小,但对抗性很强,然后给出了一系列的方法用于计算不同的自然样本和不同的类别被攻击的难易程度,最后证明了JSMA 对抗样本难以被人眼识别。

论文的重点部分是 JSMA 算法。

1. 介绍

问题描述:

X \mathbf{X} X 是原始特征向量, Y \mathbf{Y} Y 是输出向量, F : X ↦ Y \mathbf{F}:\mathbf{X} \mapsto \mathbf{Y} F:X↦Y 是 DNN 模型表示的函数, X ∗ = X + δ X \mathbf{X^{*}} = \mathbf{X}+\delta_{\mathbf{X}} X∗=X+δX​ 是对抗样本,其中 δ X \delta_{\mathbf{X}} δX​ 是扰动向量。我们希望这个扰动尽可能的小,即:
arg ⁡ min ⁡ δ X ∣ ∣ δ X ∣ ∣ s.t. F ( X + δ X ) = Y ∗ (1) \arg\min_{\delta_{\mathbf{X}}} ||\delta_{\mathbf{X}}|| \;\; \textbf{s.t.} \;\; \mathbf{F}(\mathbf{X}+\delta_{\mathbf{X}}) = \mathbf{Y}^{*} \tag{1} argδX​min​∣∣δX​∣∣s.t.F(X+δX​)=Y∗(1)
其中, ∣ ∣ ⋅ ∣ ∣ ||\cdot|| ∣∣⋅∣∣ 为根据 DNN 而选择的合适的范数, Y ∗ \mathbf{Y}^* Y∗ 是对抗输出。

DNN 的性质导致了公式(1)是非线性且非凸的,所以公式(1)很难解,对此,作者提出了一个基于前向导数(forward derivatives)的方法:构建一个从输入扰动到输出变化的映射,然后使用输出的变化来找到相应的输入扰动。具体方法是引入 F \mathbf{F} F 的 Jacobian 矩阵,这个矩阵用于构建对抗显著图(adversarial saliency maps),这个图表示了包含在扰动 δ X \delta_{\mathbf{X}} δX​ 中的输入特征。

本文中,作者选择 MNIST 数据集和 LeNet 模型。

2. 攻击模型的分类

图1. 攻击模型的分类,本文方法属于星号类

2.1 对抗的目标

考虑以下四个影响模型完整性(integrity)的攻击目标,对应于图1的横坐标:

  1. 降低输出的置信度
  2. 将输入分类成任意的与初始 class 不同的 class
  3. 生成输入,这些输入被强制分类成一个特定的 target class
  4. 将输入分类成一个特定的 target class

2.2 对抗的能力

根据攻击者获得的信息不同,将攻击能力分为以下五个,对应于图1的纵坐标:

  1. 训练数据 & 网络架构:攻击者访问神经网络全部信息—训练数据集、网络的函数和算法、网络架构 F \mathbf{F} F。这是最强的攻击,它可以分析训练数据并完全模拟网络。
  2. 网络架构:攻击者访问网络架构 F \mathbf{F} F 及其参数,包括网络层数、激活函数、权重、bias等。这些信息足够攻击者用于模拟神经网络。本文的攻击算法属于此类
  3. 训练数据:攻击者能够收集一个替代数据集,这个替代数据集从DNN训练集分布中采样,但攻击者无法访问网络架构。此类攻击通常使用替代数据集进行训练,用来近似原始的网络。
  4. oracle:攻击者将原始网络当做 oracle,通过提供输入样本,收集原始网络的输出值。通过观察输入变化和输出变化之前的关系来生成对抗样本。
  5. 样本:攻击者收集神经网络给出的输入和输出对,其中输出数据被标记,与Oracle不同的是,它无法修改这些输入来观察输入输出变化的差异。这种方法通常需要十分大量的这样的数据对,且攻击能力很差。

3. Approach

3.1 简单的神经网络

首先考虑一个简单的神经网络以分析很小的扰动是如何使用前向导数令神经网络的输出产生大变化:

图2. 简单网络在 [ 0 , 1 ] 2 [0,1]^2 [0,1]2 上的输出。蓝色表示输出为 0,黄色表示输出为 1。

学习一个 AND 函数: 输入 X = ( x 1 , x 2 ) ∈ [ 0 , 1 ] 2 \mathbf{X}=(x_1,x_2)\in[0,1]^2 X=(x1​,x2​)∈[0,1]2, F ( X ) = x 1 ∧ x 2 \mathbf{F}(\mathbf{X}) = x_1 \wedge x_2 F(X)=x1​∧x2​ , 其中非整数的输入被四舍五入为0或1, 函数的输出原则为: 1 ∧ 1 = 1 , 1 ∧ 0 = 0 , 0 ∧ 1 = 1 , 0 ∧ 0 = 0 1 \wedge 1 = 1, 1 \wedge 0 = 0, 0 \wedge 1 = 1, 0 \wedge 0 = 0 1∧1=1,1∧0=0,0∧1=1,0∧0=0. 在一组1000个样本集上使用 BP,学习率为 η = 0.0663 \eta = 0.0663 η=0.0663。训练后,网络学习到的函数如图2所示,两个水平轴表示 x 1 x_1 x1​ 与 x 2 x_2 x2​,垂直轴表示 F ( X ) \mathbf{F}(\mathbf{X}) F(X)。

接下来介绍如何在这个网络上生成对抗样本:
作者将前向导数定义为(在训练过程中的) F \mathbf{F} F 的 Jacobian 矩阵,对于这个简单的网络, F \mathbf{F} F 的输出是一维的,因此矩阵可以简化为向量:
▽ F ( X ) = [ ∂ F ( X ) ∂ x 1 , ∂ F ( X ) ∂ x 2 ] (2) \triangledown\mathbf{F} (\mathbf{X}) = \left [ \frac{\partial \mathbf{F} (\mathbf{X}) }{\partial x_1} , \frac{\partial \mathbf{F} (\mathbf{X}) }{\partial x_2}\right ] \tag{2} ▽F(X)=[∂x1​∂F(X)​,∂x2​∂F(X)​](2)
如下图,图3绘制了第二个分量的梯度,即 ∂ F ( X ) ∂ x 2 \frac{\partial \mathbf{F} (\mathbf{X}) }{\partial x_2} ∂x2​∂F(X)​,由于这两个分量在 F \mathbf{F} F上的梯度几乎对称,所以为了图像清晰,此处省略了第一个分量的梯度。可以看到,图3中的尖峰的左侧为输出=0,右侧为输出=1(与图2相对应),这就提供了我们想要的信息:找到令输出等于特定值的扰动。

图3. 简单网络的前向导数( x 2 x_2 x2​)。 X \mathbf{X} X 是自然样本(原始样本、干净样本), X ∗ = X + δ X \mathbf{X}^* = \mathbf{X} + \delta_\mathbf{X} X∗=X+δX​ 是对抗样本,其中 δ X = ( δ x 1 , δ x 2 ) \delta_\mathbf{X} = (\delta_{x_1},\delta_{x_2}) δX​=(δx1​​,δx2​​),但此处忽略 δ x 1 \delta_{x_1} δx1​​。

假设干净样本 X = ( 1 , 0.37 ) \mathbf{X} = (1, 0.37) X=(1,0.37),对抗样本 X ∗ = ( 1 , 0.43 ) \mathbf{X}^* = (1, 0.43) X∗=(1,0.43),它们都位于尖峰处且它们的差异很小( δ x 2 = 0.05 \delta_{x_2} = 0.05 δx2​​=0.05),但是它们的输出却很大差异 F ( X ) = 0.11 \mathbf{F} (\mathbf{X})=0.11 F(X)=0.11 而 F ( X ∗ ) = 0.95 \mathbf{F} (\mathbf{X^*}) = 0.95 F(X∗)=0.95(这里是训练后网络的输出)。前向导数告诉我们那些区域不太可能产生对抗样本,如找到接近 ( 1 , 0 ) (1,0) (1,0) 的对抗样本比 ( 1 , 0.4 ) (1,0.4) (1,0.4) 的更难,所以在生成对抗样本时,应该专注于前向导数值较大的特征。

根据这个简单网络的例子我们可以得出以下几点:

  1. 很小的输入扰动可以导致网络的输出产生很大变化;
  2. 输入域(input domain)中的某些区域(region)难以寻找对抗样本,某些区域易于寻找对抗样本;
  3. 前向导数可以减少对抗样本的搜索范围。

3.2 推广到一般的前馈神经网络

现在将算法推广到任意非循环的前馈 DNN。为了方便叙述,作者首先给出了一些符号说明:
F \mathbf{F} F:神经网络在训练中学习到的函数;
X ∈ R M \mathbf{X} \in \mathbb{R}^{M} X∈RM:网络的输入,维度为 M M M;
Y ∈ R N \mathbf{Y} \in \mathbb{R}^{N} Y∈RN:网络的输出,维度为 N N N;
n n n:神经网络有 n n n 个隐藏层;
f f f:激活函数;
H k H_k Hk​:第 k k k 层的输出向量;

k k k:网络层的index, k ∈ 0 , . . . , n + 1 k \in 0,...,n+1 k∈0,...,n+1;
i i i:输入分量的index, i ∈ 0 , . . . , M i \in 0,...,M i∈0,...,M;
j j j:输出分量的index, j ∈ 0 , . . . , N j \in 0,...,N j∈0,...,N;
p p p:神经元的index, p ∈ 0 , . . . , m k p \in 0,...,m_k p∈0,...,mk​(第 k k k 层有 m k m_k mk​ 个节点)。


上图的 Algorithm 1 介绍了构造对抗样本的过程:

  • 算法1的输入包括:干净样本 X \mathbf{X} X,目标输出 Y ∗ \mathbf{Y}^* Y∗,网络 F \mathbf{F} F,最大失真(maximum distortion)参数 Υ \Upsilon Υ 和特征变化(feature variation)参数 θ \theta θ;
  • 算法1的输出为:由 X \mathbf{X} X 产生的对抗样本 X ∗ \mathbf{X}^* X∗,满足 F ( X ∗ ) = Y ∗ \mathbf{F}(\mathbf{X}^*)=\mathbf{Y}^* F(X∗)=Y∗;
  • 算法1的大致过程为不断重复以下三个步骤直到网络输出 Y ∗ \mathbf{Y}^* Y∗或达到了最大失真 Υ \Upsilon Υ:
    1. 计算前向导数 ▽ F ( X ∗ ) \triangledown \mathbf{F}(\mathbf{X}^*) ▽F(X∗);
    2. 根据 ▽ F ( X ∗ ) \triangledown \mathbf{F}(\mathbf{X}^*) ▽F(X∗) 构造一个显著图(saliency map) S S S;
    3. 使用 θ \theta θ 修改输入特征 i m a x i_{max} imax​
      接下来详细介绍这三步。

A)计算前向导数:

与简单网络的公式(2)一样,前向导数本质上是 F \mathbf{F} F 对于输入 X \mathbf{X} X 的 Jacobian 矩阵,目的是寻找使网络输出发生显著变化的输入分量:
▽ F ( X ) = ∂ F ( X ) ∂ X = [ ∂ F j ( X ) ∂ x i ] M × N (3) \triangledown \mathbf{F}(\mathbf{X})=\frac{\partial \mathbf{F}(\mathbf{X})}{\partial \mathbf{X}} = \left [ \frac{\partial \mathbf{F}_{j}(\mathbf{X})}{\partial x_{i}} \right ]_{M \times N} \tag{3} ▽F(X)=∂X∂F(X)​=[∂xi​∂Fj​(X)​]M×N​(3)
这个矩阵中的第 ( i , j ) (i,j) (i,j) 个元素 ∂ F j ( X ) ∂ x i \frac{\partial \mathbf{F}_{j}(\mathbf{X})}{\partial x_{i}} ∂xi​∂Fj​(X)​ 为输出神经元 F j \mathbf{F}_{j} Fj​ 对于输入分量 x i x_{i} xi​ 的导数。
从第一个隐藏层的输出开始对输入分量求微分,然后递归地求下一隐藏层对输入分量的微分:
∂ H k ( X ) ∂ x i = [ ∂ f k , p ( W k , p ⋅ H k − 1 + b k , p ) ∂ x i ] p ∈ 1... m k (4) \frac{\partial \mathbf{H}_k(\mathbf{X})}{\partial x_i}=\left [ \frac{\partial f_{k,p}(\mathbf{W}_{k,p}\cdot \mathbf{H}_{k-1}+b_{k,p})}{\partial x_i} \right ]_{p\in 1...m_k} \tag{4} ∂xi​∂Hk​(X)​=[∂xi​∂fk,p​(Wk,p​⋅Hk−1​+bk,p​)​]p∈1...mk​​(4)
其中, H k \mathbf{H}_k Hk​ 是第 k k k 个隐藏层的输出向量, f k , j f_{k,j} fk,j​ 是这层的第 j j j 个神经元输出的激活函数, W k , p \mathbf{W}_{k,p} Wk,p​ 为第 k k k 层、第 p p p 个神经元与前一层相连的权重向量, b k , p b_{k,p} bk,p​ 为第 k k k 层、第 p p p 个神经元的偏置 bias。根据链式法则有:
∂ H k ( X ) ∂ x i ∣ p ∈ 1... m k = ( W k , p ⋅ ∂ H k − 1 ∂ x i ) × ∂ f k , p ∂ x i ( W k , p ⋅ H k − 1 + b k , p ) (5) \left.\frac{\partial \mathbf{H}_k(\mathbf{X})}{\partial x_i}\right|_{p\in 1...m_k} =\left ( \mathbf{W}_{k,p}\cdot \frac{\partial \mathbf{H}_{k-1}}{\partial x_i}\right )\times \frac{\partial f_{k,p}}{\partial x_i}\left ( \mathbf{W}_{k,p}\cdot \mathbf{H}_{k-1}+b_{k,p} \right ) \tag{5} ∂xi​∂Hk​(X)​∣ ∣​p∈1...mk​​=(Wk,p​⋅∂xi​∂Hk−1​​)×∂xi​∂fk,p​​(Wk,p​⋅Hk−1​+bk,p​)(5)
从而可以推出,输出层(即第 n + 1 n+1 n+1 层)的第 j j j 个神经元对输入分量 x i x_i xi​ 的导数为:
∂ F j ( X ) ∂ x i = ( W n + 1 , j ⋅ ∂ H n ∂ x i ) × ∂ f n + 1 , j ∂ x i ( W n + 1 , j ⋅ H n + b n + 1 , j ) (6) \frac{\partial \mathbf{F}_j(\mathbf{X})}{\partial x_i} =\left ( \mathbf{W}_{n+1,j}\cdot \frac{\partial \mathbf{H}_{n}}{\partial x_i}\right )\times \frac{\partial f_{n+1,j}}{\partial x_i}\left ( \mathbf{W}_{n+1,j}\cdot \mathbf{H}_{n}+b_{n+1,j} \right ) \tag{6} ∂xi​∂Fj​(X)​=(Wn+1,j​⋅∂xi​∂Hn​​)×∂xi​∂fn+1,j​​(Wn+1,j​⋅Hn​+bn+1,j​)(6)
公式(6)中,除了 ∂ H n ∂ x i \frac{\partial \mathbf{H}_{n}}{\partial x_i} ∂xi​∂Hn​​ 外所有的参数都是已知的,因为我们选择的攻击模型为2.2节的第二类(攻击者可以访问网络架构),而 ∂ H n ∂ x i \frac{\partial \mathbf{H}_{n}}{\partial x_i} ∂xi​∂Hn​​ 可以递归地一层层的计算得到。因此前向导数后矩阵,即公式(3),是可以计算得到的。

B)对抗显著图:

对抗显著图描述的是攻击者应该扰乱那些输入特征才能使网络得输出产生预期的变化,即输入空间中哪些特征对输出影响最大。

攻击者想将样本 X \mathbf{X} X 分成 t t t 类(真实类别为 l a b e l ( X ) label(\mathbf{X}) label(X)),这需要将概率 F t ( X ) \mathbf{F}_t(\mathbf{X}) Ft​(X) 增大,其他概率 F j ( X ) , j ≠ t \mathbf{F}_j(\mathbf{X}), j\neq t Fj​(X),j=t 减小,直到 t = arg ⁡ max ⁡ j F t ( X ) t=\arg\max_j \mathbf{F}_t(\mathbf{X}) t=argmaxj​Ft​(X),可以使用下述的显著图 S ( X , t ) S(\mathbf{X},t) S(X,t) 来增大输入特征,从而实现攻击者的目标:
S ( X , t ) [ i ] = { 0 i f ∂ F t ( X ) ∂ X i < 0 o r ∑ j ≠ t ∂ F j ( X ) ∂ X i > 0 ( ∂ F t ( X ) ∂ X i ) ∣ ∑ j ≠ t ∂ F j ( X ) ∂ X i ∣ o t h e r w i s e (7) S(\mathbf{X,t})[i]=\left\{\begin{matrix} 0 \;\; {\rm if}\;\; \frac{\partial \mathbf{F_t(\mathbf{X})}}{\partial \mathbf{X}_i} < 0 \;\; {\rm or}\sum_{j\neq t}\frac{\partial \mathbf{F_j(\mathbf{X})}}{\partial \mathbf{X}_i}>0\\ \left ( \frac{\partial \mathbf{F_t(\mathbf{X})}}{\partial \mathbf{X}_i} \right )\;\;|\sum_{j\neq t}\frac{\partial \mathbf{F_j(\mathbf{X})}}{\partial \mathbf{X}_i}|\;\;{\rm otherwise} \end{matrix}\right. \tag{7} S(X,t)[i]={0if∂Xi​∂Ft​(X)​<0or∑j=t​∂Xi​∂Fj​(X)​>0(∂Xi​∂Ft​(X)​)∣∑j=t​∂Xi​∂Fj​(X)​∣otherwise​(7)
其中 i i i 表示输入的第 i i i 个分量,即输入空间的第 i i i 个特征。公式(7)的第一行表示:如果 t t t 类的前向导数为负,或其他类的前向导数之和为正,则拒绝这个特征;第二行表示:反之的话,这两个前向导数就位输入特征的显著性。 S ( X , t ) [ i ] S(\mathbf{X,t})[i] S(X,t)[i] 值越高,意味着相应的输入特征要么使模型输出 t t t 类的概率更高,要么使模型输出其他类的概率更低,从而将样本错误分类到 t t t。

作者又给出了另一种对抗显著图, θ = − 1 \theta = -1 θ=−1,与公式(7)的区别是:第一行的约束符号不同,第二行的绝对值位置不同:
S ( X , t ) [ i ] = { 0 i f ∂ F t ( X ) ∂ X i > 0 o r ∑ j ≠ t ∂ F j ( X ) ∂ X i < 0 ∣ ∂ F t ( X ) ∂ X i ∣ ( ∑ j ≠ t ∂ F j ( X ) ∂ X i ) o t h e r w i s e (8) S(\mathbf{X,t})[i]=\left\{\begin{matrix} 0 \;\; {\rm if}\;\; \frac{\partial \mathbf{F_t(\mathbf{X})}}{\partial \mathbf{X}_i} > 0 \;\; {\rm or}\sum_{j\neq t}\frac{\partial \mathbf{F_j(\mathbf{X})}}{\partial \mathbf{X}_i} < 0\\ |\frac{\partial \mathbf{F_t(\mathbf{X})}}{\partial \mathbf{X}_i} |\;\;\left( \sum_{j\neq t}\frac{\partial \mathbf{F_j(\mathbf{X})}}{\partial \mathbf{X}_i}\right )\;\;{\rm otherwise} \end{matrix}\right. \tag{8} S(X,t)[i]={0if∂Xi​∂Ft​(X)​>0or∑j=t​∂Xi​∂Fj​(X)​<0∣∂Xi​∂Ft​(X)​∣(∑j=t​∂Xi​∂Fj​(X)​)otherwise​(8)

C)修改输入样本:

通过对抗显著图可以确定那些输入特征需要被修改/扰动,而扰动多大的值(即 θ \theta θ)将在第四节讨论。最大迭代次数,也就是允许的最大失真 Υ \Upsilon Υ 的选择需要考虑人眼对对抗样本的感知性,因为过大的失真会使人眼可识别对抗样本。

4. Application & Evaluation

4.1 实验

数据集:MNIST;网络模型:LeNet。

作者给出了详细的针对 MNIST 数据集定做的 JSMA 方法,包括 θ = 1 \theta = 1 θ=1 和 − 1 -1 −1 两种,分别对应于公式(7)和(8)。

4.2 评估

作者从以下三个方面评估 JSMA:

  1. JSMA 攻击的成功率如何
  2. 如何定义样本被攻击的难易程度
  3. 人眼是否可以识别 JSMA 生成的样本

1)问题1:

作者在MNIST 训练集、验证集和测试集上各选1万个样本,每个样本各生成9个对抗样本,也就是总共27万个对抗样本。实验结果为,本文的方法生成对抗样本的平均成功率为 97.1%,平均失真为 4% 左右,也就是说,对于一个 784 像素点组成的图形来说,平均只需要修改 32 个像素点就可以制造出响应的对抗样本。

2)问题2:

在问题1的实验中,有大约 2.9% 的样本没有成功地生成对抗样本,也就是说它们难以被攻击。对此,作者首先定义了 hardness measure – H ( s , t ) H(s,t) H(s,t) 来计算源类(source class, s s s)与目标类(target class, t t t)之间的距离,从而评估源类被扰动成目标类的难易程度。然后,定义了 adversarial distance – A ( X , t ) A(\mathbf{X},t) A(X,t) 来计算样本 X \mathbf{X} X 与目标类( t t t)之间的距离。

3)问题3:

作者在 Mechanical Turk 上对 349 位参与者进行了实验,结果为人眼不能发现 JSMA 对抗样本中添加的扰动。

【论文笔记】(JSMA)The Limitations of Deep Learning in Adversarial Settings相关推荐

  1. Deep Learning论文笔记之(八)Deep Learning最新综述

    Deep Learning论文笔记之(八)Deep Learning最新综述 zouxy09@qq.com http://blog.csdn.net/zouxy09 自己平时看了一些论文,但老感觉看完 ...

  2. 论文笔记:《DeepGBM: A Deep Learning Framework Distilled by GBDT for Online Prediction Tasks》

    论文笔记:<DeepGBM: A Deep Learning Framework Distilled by GBDT for Online Prediction Tasks> 摘要 1. ...

  3. CVPR2018论文笔记: Robust Physical-World Attacks on Deep Learning Visual Classification

    论文百篇计划第二篇,cvpr2018的一篇文章,引用量1800.作者来自密歇根大学安娜堡分校. 最近的研究表明目前DNN容易收到对抗样本的攻击,理解物理世界中的对抗样本对发展弹性学习算法非常重要.我们 ...

  4. 论文笔记:Meta-attention for ViT-backed Continual Learning CVPR 2022

    论文笔记:Meta-attention for ViT-backed Continual Learning CVPR 2022 论文介绍 论文地址以及参考资料 Transformer 回顾 Self- ...

  5. 综述论文翻译:A Review on Deep Learning Techniques Applied to Semantic Segmentation

    综述论文翻译:A Review on Deep Learning Techniques Applied to Semantic Segmentation 近期主要在学习语义分割相关方法,计划将arXi ...

  6. 论文学习之综述:《Deep learning》

    论文学习之综述:<Deep learning> 文章目录 论文学习之综述:<Deep learning> 前言: 第一部分:深度学习基础(1-4)页 作者介绍: 前期知识储备: ...

  7. 论文笔记——Fair Resource Allocation in Federated Learning

    论文笔记--Fair Resource Allocation in Federated Learning 原文论文链接--http://www.360doc.com/content/20/0501/1 ...

  8. matting系列论文笔记(一):Deep Image Matting

    matting系列论文笔记(一):Deep Image Matting 刚刚入了Image Matting的坑,后续会更新系列相关的文章.这个坑目前还没有人满为患,好的文章没有很多,综述文章也没有囊括 ...

  9. READ-2307 The Limitations of Federated Learning in Sybil Settings

    READ-2307 The Limitations of Federated Learning in Sybil Settings 论文名称 The Limitations of Federated ...

最新文章

  1. 积木履带机器人编程手册_学会编程,寓教于乐!ONEBOT 反履机甲图赏
  2. 看图说OpenGL之三:是什么在改变物体的颜色
  3. python爬虫赚钱的途径-如何用爬虫技术赚钱?
  4. python xlrd xlwt综合_xlrd和xlwt -- python
  5. 使用Git命令时出现fatal: this operation must be run in a work tree提示,该如何解决
  6. 机械加工工艺师手册_机械加工工艺师——机床应用篇
  7. git比较当前工作区和之前提交的内容差异
  8. 预处理指令pragma常见用法集锦(#pragma once、#pragma comment和#pragma warning)
  9. PPP认证方式pap chap chap2
  10. Android 系统调试(1)---禁止Selinux 的方法
  11. 从技术、服务到共创 声网 Agora 携手合作伙伴共建 RTC 生态
  12. C++详解new/delete
  13. Map Reduce学习
  14. 爬虫:Python爬虫学习笔记之网页解析基础——爬取360导航栏目
  15. 【荐】Redis学习资料汇总
  16. R语言-主成分分析和聚类分析实操(包含源码)
  17. 模拟信号的采样定理MATLAB实现
  18. python如何打印26个字母_python3打印26个英文字母
  19. @Idempotent注解限制同一时刻的访问间隔
  20. VR分享会邀请函 | 如何利用VR影像创造商业应用新价值?

热门文章

  1. java拟合曲线图案例_Java实现的n阶曲线拟合功能示例
  2. 第二单元电梯作业总结
  3. JavaWeb,HTTP和Tomcat
  4. 计算机课学情分析范文,计算机教学计划范文
  5. Web应用——驾培管理系统之系统—权限分配(作者:小圣)
  6. 疫情不能出门,有什么在家就能做的项目吗?
  7. Html实现视频播放器(超级简单)
  8. Image captioning常用的指标
  9. c语言程序终止语句,c语言的语句以什么结束
  10. Android开发最佳实践---Futurice之见