回过头再来看深度学习的基础知识,才发现之前掌握的根本不牢,许多基础的概念都没有深刻理解。

机器学习、深度学习的基本原理

f(x) is{scalar:regressionlabel:classificationtext/imagesf(x) \text{ is} \left\{ \begin{aligned} &\text{scalar} : \text{regression}\\ &\text{label} : \text{classification}\\ &\text{text/images} \end{aligned} \right.

模型的复杂度:模型的参数有多少种选择

loss=1Nn=1Nl(param,xn,y^n)\text{loss}=\frac{1}{N}\sum_{n=1}^N l(\text{param},x^n,\hat{y}^n)

最好的参数

param=arg minparamloss\text{param}_*=\argmin_{\text{param}} \text{loss}

我们希望训练集DtrainD_{\text{train}}的数据分布与DallD_{\text{all}}中数据分布相同,训练集中的数据之间 是i.i.d.i.i.d.的,即 independently and identically distributed,独立同分布。

数学地描述训练集与总数据集合

我们希望训练集能近似替代总数据集,即:

L(htrain,Dall)L(hall,Dall)<δL(h^{\text{train}},D_{\text{all}})-L(h^{\text{all}},D_{\text{all}})<\delta

其充分条件如下:

h:L(h,Dall)L(h,Dtrain)<δ2\forall h : |L(h,D_{\text{all}})-L(h,D_{\text{train}})|<\frac{\delta}{2}

proof:

L(htrain,Dall)L(htrain,Dtrain)<δ2(1)L(h_{\text{train}},D_{\text{all}})-L(h_{\text{train}},D_{\text{train}})<\frac{\delta}{2} \quad\cdots (1)

L(hall,Dtrain)L(hall,Dall)<δ2(2)L(h_{\text{all}},D_{\text{train}})-L(h_{\text{all}},D_{\text{all}})<\frac{\delta}{2} \quad\cdots (2)

(1)+(2)L(htrain,Dall)+[L(htrain,Dtrain)+L(hall,Dtrain)]L(hall,Dall)<δ(1)+(2)\Rightarrow L(h_{\text{train}},D_{\text{all}}) +[-L(h_{\text{train}},D_{\text{train}})+ L(h_{\text{all}},D_{\text{train}})]-L(h_{\text{all}},D_{\text{all}})<\delta

due to the fact that

L(htrain,Dtrain)<L(hall,Dtrain)L(h_{\text{train}},D_{\text{train}})<L(h_{\text{all}},D_{\text{train}})

therefore

L(htrain,Dall)L(hall,Dall)<δL(h^{\text{train}},D_{\text{all}})-L(h^{\text{all}},D_{\text{all}})<\delta

数据集的好与坏

只要存在一个参数param1使得:L(param1,Dtrain)L(param1,Dall)>ϵ|L(\text{param}_1,D_{\text{train}})-L(\text{param}_1,D_{\text{all}})|>\epsilon,则这个数据集是不好的。

任意挑选一个数据集是坏的的概率上限推导如下(认为模型参数的参数空间为HH):

P(Dtrain is bad)=PparamH{Di is bad due to param}paramHP(Di is bad due to param)paramH2exp(2Nϵ2)Hoeffding’s Inequality=2exp(2Nϵ2)H\begin{aligned} P(D_{\text{train}}\text{ is bad})=&P(\bigcup_{\text{param}\in H}\{D_i \text{ is bad due to param}\})\\ \leq&\sum_{\text{param}\in H}P(D_i\text{ is bad due to param})\\ \leq&\sum_{\text{param}\in H} 2\exp(-2N\epsilon^2)\qquad \text{Hoeffding’s Inequality}\\ =&2\exp(-2N\epsilon^2)|H| \end{aligned}

因此,模型的参数空间越小,训练集的样本越大,得到一个好的训练集的概率越大。

为什么选择deep learning 而不是wide learning

一个函数可以通过若干个简单的函数叠加出来:表明神经网络有能力拟合任意函数。

若需要拟合同一个函数,那么更深的网络能比更宽的网络需要更少的参数量。(可以看作函数的嵌套)

套用数字逻辑的理论,要表达一个奇偶校验函数,对于深层网络(每层门电路数量固定),只需要O(n)O(n)个神经元即可,而对于浅层网络(层的数量固定),需要O(2n)O(2^{n})个神经元。
因此,深层的神经网络需要更少的参数就能达到相同的效果。

对于最优参数param=arg minparamHL(param,D)\text{param}_*=\argmin_{\text{param}\in H}L(\text{param},D_{\text{}})

我们希望参数空间尽可能少(减少搜索时间并增强稳定性),并且loss也尽可能少。而深度学习在保持loss基本不变的情况下显著减少了参数量,是一个非常好的方法。

生成式模型

Generater: 能够输出一个复杂的分布(将一个简单的分布变换而来的)

为什么是分布

在进行预测任务时,答案可能不止一种,有好几种可能的答案,我们希望模型能够输出一个分布,而不是一个确定的答案(否则模型容易投机取巧,将几种可能的情况揉在一起)。

为模型的输入加入一些噪声(从简单的分布采样),就能为模型的输出增加不确定性(本质是从复杂的分布采样)。

拿图片生成为例,有意义的图片的熵是比较低的(相对于噪音而言),有意义的图片一定符合某种规律,也就是一种分布。但是我们无法直接训练生成器学到这种分布,因为我们其实也不知道这个分布到底长啥样,更别说在数学上计算这个模型的输出与真实分布之间的散度了。

为了解决这个问题,GAN便应运而生了,我们只需要分布的采样,而不是分布本身。

Generative Adversarial Network: GAN

Discriminator: 判断目标是真实的还是生成的(假的)

imageDiscriminatorscalar[0,1]\text{image} \rightarrow \boxed{\text{Discriminator}}\rightarrow \text{scalar} \in [0,1]

训练过程

  1. 冻结生成器,训练判别器:将真实的图片打上标签1,将生成的图片打上标签0,训练判别器
  2. 冻结判别器,训练生成器:我们希望生成器能“骗过”判别器,得到高的分数。即,希望D(G(z))D(G(z))的输出值为1,但此时判别器的参数是被冻结的,模型会强迫让生成器学到能骗过判别器的方法。

重复以上过程

数学原理

对于判别器,我们的优化目标如下:

V(G,V)=EyPdatalogD(y)+EzPGlog(1D(G(z)))V(G,V)=E_{y\sim P_{\text{data}}}\log D(y)+E_{z\sim P_G}\log(1-D(G(z)))\\

那么就是说,最优的判别器如下:

D=arg maxDV(D,G)D^*=\argmax_D V(D,G)\\

最优的生成器如下(最小化模型分布与真实分布之间的差异):

G=arg minGDiv(PG,Pdata)但是我们不知道如何计算这个散度G^*=\argmin_G Div(P_G,P_{\text{data}})\quad \text{但是我们不知道如何计算这个散度}

但是进一步可以证明maxV\max VJSDiv(PG,Pdata)JSDiv(P_G,P_{\text{data}})存在的正相关性

那么,优化生成器可以使用maxV\max V来替代散度,即

G=arg minGmaxV(D,G)G^*=\argmin_G \max V(D,G)

这与上述训练过程是对应的。

特点

生成器的生成的分布甚至具有连续性,在一定程度上是光滑的。将输入做插值,生成器的输出也会做展现出渐变效果。

训练

GAN的训练通常比较困难,但有一些技巧。

GAN使用的是js散度,对于两个无交集的分布,其输出始终为定值,导致梯度消失。而且由于生成器的参数是随机初始化的,其与真实分布大概率就是没有交集的。随之而来的另一个问题是,对于两个没有交集的分布,判别器可以非常容易判断真假,导致显示的判别准确率非常容易达到100%,但这实际上是没有意义的。

这可以通过更换散度函数改善(实际上是更换了优化目标),并加入一些限制条件(足够平滑,避免发散)

缺陷

GAN对于文本生成任务同样也比较困难:相较于图片,文本更为离散,参数微小的变化可能并不会造成输出的改变,出现梯度消失的问题。(argmax,sample不可微)

多样性不足:为了生成很真的图片,生成器的分布可能只是真实图片的一个子集(mode dropping),甚至几乎收敛到一个点(mode collapse)

overfitting:如果generator学会了产生真实数据集中的样本,那么最终的指标会很好看,但实际上没啥用。

Conditional GAN

之前的GAN是unconditional的,输入只有一段噪音,让模型产生一个样本。

而conditional GAN则还增加了一个输入x,用来影响输出,使其与x有关。

flowchart LR
A[x:prompt] -->B{Generator}
C[噪音]--> B
B--> D[image]
D--> E{Discriminator}
A--> E
E--> F[score]

cycle GAN

对于unsupervised的任务,我们只有大量的输入数据、输出数据,但是输入与输出不是配对的。我们就可以使用cycle GAN技术使模型学到某种对应关系。

flowchart LR
A[x:dom1] -->B{Generator1}
B-->C[y:dom2]
B-->G{Discriminator1}
G-->H[score1]
C-->D{Generator2}
D-->E[x':dom1]
D-->I{Discriminator2}
I-->J[score2]
A-->F(similarity loss)
E-->F

虽然cycle GAN只能保证x与y之间存在相关性,不能保证这种相关性就是我们视觉上看到的相关性,但由于神经网络的特性(比较懒),使得模型在实践训练中,更容易学习到视觉上的相关性(相较而言比较简单)。而不是学到把红头发变成绿头发,然后把绿头发变成红头发。

Encoder & Decoder

feature disentangle

tangle: 纠缠
disentangle: 解开

可以将嵌入向量分解为多个部分,每个部分对应一个特征。比如可以将声音学习嵌入为[content,tune],通过替换不同的tune,decoder就能将声音转换成不同的人说的。

离散的潜空间

如果我们将潜空间离散为binary的,那么模型就能学到对于不同特征的分类。

如果我们将潜空间离散为one-hot,那么模型就能学习到聚类。

VQVAE:将潜空间离散化为一个有限的集合

潜空间也可以是文本序列,对于文档,模型或许能学到总结文档的内容。(当然需要潜空间中文本的分布与人类文本的分布相似)

异常检测

异常检测有很多种实现的方式,但是很难直接通过二分类实现。因为异常数据的分布过大,你给出的异常数据集并不能覆盖整个数据分布;二是很多时候异常数据的数据量远远小于正常数据,导致模型训练时,异常数据的权重会非常低。

encoder/decoder模型

对于此模型,它只能针对特定分布的数据进行嵌入、还原。如果我们将一个异常的数据输入到模型中,它最终还原的结果会与输入的结果有很大的差异,可用于异常检测。

classifier模型

classifier模型并不直接分类出异常模型,而是分类已知的类型。

方法不止一种:

  1. 如果max的信心仍然不足,那么就可以认为这个数据是异常的。
  2. 计算这个分布的熵,如果熵过大也认为这个数据是异常的。

概率模型

使用一个概率密度函数ff,计算这个数据的概率密度,如果概率密度过低,那么就可以认为这个数据是异常的。

值得注意的是,可以使用神经网络去拟合这个概率密度函数。

可解释性

解释到什么程度叫可解释性,现在并没有一个统一的答案。对于神经网络的解释,其实也并不是能够完完全全透彻地解释的。

  • local explanation: 针对特定输入,解释数据是如何变化的
  • global explanation: 针对模型,分析模型认为的特征是什么

local explanation

图像遮盖

可以用中性颜色遮盖图片的区域,看看神经网络对不同遮盖区域的反应。

梯度图 saliency map

可以计算神经网络对输入的每个像素的梯度,从而得到一个 saliency map,这个 map 可以告诉我们神经网络关注的区域。

局限性:如果这个点已经饱和了,梯度图无法反映这个点对神经网络是否重要

探针 probing

一个神经网络有许多层

graph LR
    layer1["layer1"] --> layer2["layer2"] --> layer3["layer3"]-->...["..."]
    layer1-->prob1{probe1}
    layer2-->prob2{probe2}
    layer3-->prob3{probe3}

用一个神经网络将不同层的输出作为输入,然后将其重建(人类可理解的),比较不同层之间重建的差异,就能推断这一层神经网络干了什么。

global explanation

特征可视化

例如对于卷积而言,可以根据卷积的参数,找到能使这个卷积输出最大的输入。可视化这个卷积在检测什么样子的特征。

输入可视化

对于classifier

X=arg maxXf(X)(i)X^*=\argmax_Xf(X)^{(i)}

可以分析模型认为最符合这个类别的输入是哪些。

但实际上,这样求得的图片可能是无意义的,还需要加入正则项来限制。

trick

连接一个generator:

flowchart LR
A[z]-->B(Generator)-->C[image]-->D(Classifier)-->E[label]

z=arg maxzf(G(z))(i)z^*=\argmax_zf(G(z))^{(i)}

这样,就能获得有意义的,并且符合分类器认为最好的输入。

用简单模型拟合神经网络

因为简单模型很容易自解释,可以使用简单模型去拟合神经网络的某些区域,尝试解释在这一部分神经网络干了什么。

Attack

white box attack

需要事先知道模型的参数

benign image: x0x^0
adversarial image: xx

x=arg maxd(x,x0)<ϵl(f(x0),f(x))x^*=\argmax_{d(x,x^0)<\epsilon} l(f(x^0),f(x))

限制输入的改变范围,同时希望模型的输出与原始输出差距越大越好。

black box attack

不需要事先知道模型的参数

一般通过构建原始模型的proxy

  1. 尝试使用相同的数据源去训练一个“近似”的模型
  2. 蒸馏原始模型

增强操作:使用多个模型去拟合,然后投票,将这个整体视为proxy。这样的attack更容易成功。

一种解释:攻击能成功是因为data,而不是模型。(理由:同一个adversarial image能对不同架构但训练数据相同的模型进行攻击)

防御 adversarial training

训练完成后攻击自己,然后将adversarial image加入到训练数据中,重新训练模型,不断强化自己,增强鲁棒性,这样还更不容易过拟合。

资料来源

https://speech.ee.ntu.edu.tw/~hylee/ml/2022-spring.php