卷积神经网络的特殊应用
人脸识别系统
-
现在普及的人脸识别系统,包含人脸识别+活体检测(可用监督学习实现)两个部分
-
人脸识别部分介绍
- 人脸验证:
- 输入为image+ID/name
- 输出为是否信息匹配(这个人的图片和声称的信息相符)
- 这是一种1对1问题
- 人脸识别:
- 比验证更难,对系统的性能,准确率要求更高
- 有K个人的database(数据库)
- 输入为一张图片
- 输出这张图片匹配的ID/name(在K人之中)
- 人脸验证:
人脸识别系统构造
- One-Shot 学习
- 人脸识别的困难:比如在员工数据库中,每个员工可能只有一张照片。如果利用卷积神经网络实现,用softmax单元来输出n+1个标签(n对应数据库中员工个数,+1这一项表示不是这n个人的概率),这样效果不好,因为训练集很小,且有新成员加入数据库后,网络softmax层又要变化,需要重新训练。
- 解决方法:让人脸识别做到一次学习。神经网络需要学习这样一个函数
d
(
i
m
g
1
,
i
m
g
2
)
=
d
e
g
r
e
e
−
o
f
−
d
i
f
f
e
r
e
n
c
e
−
b
e
t
w
e
e
n
−
i
m
a
g
e
s
d(img1,img2)=degree-of-difference-between-images
d(img1,img2)=degree−of−difference−between−images,
- 两张图片为输入
- 输出这两张图片的差异值
- 如果是同一个人的两张照片,网络输出很小的值;如果是两个长相差别很大的人的照片,输出很大的值。所以在识别过程中,如果两张图片差异值小于阈值 τ \tau τ(超参数),就能预测这两张图片是同一个人;如果差异值大于 τ \tau τ,就能预测这是不同的两个人。
-
Siamese Network
- 实现d函数功能的一个方法就是使用siamese网络,如上图
- 图示的上下两个卷积神经网络完全一致,最后通过全连接得到的是特征向量(我们把最后的128维向量称为encoding<编码>,不再设置softmax)
- 最后定义 d ( x ( 1 ) , x ( 2 ) ) = ∣ ∣ f ( x ( 1 ) ) − f ( x ( 2 ) ) ∣ ∣ 2 d(x^{(1)}, x^{(2)}) = || f(x^{(1)}) - f(x^{(2)}) ||^{2} d(x(1),x(2))=∣∣f(x(1))−f(x(2))∣∣2 1
- 对于两个不同的输入,运行相同的卷积神经网络,然后比较它们,这一般叫做Siamese网络架构
- siamese网络的训练,实际上只是训练一个网络
- Siamese Network之Triplet Loss
通过学习神经网络的参数来得到优质的人脸图片编码,方法之一就是定义三元组损失函数然后应用梯度下降
- 为使用三元组损失,一次比较需要有三张图片(Anchor图片、Positive图片、Negative图片)A,P,N。A和P(positive就意味着是同一个人)是同一个人的不同照片,N是另一个人的照片。
- 用公式表示,自然希望有
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 ≤ ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 || f(A) - f(P) ||^{2} \le || f(A) - f(N) ||^{2} ∣∣f(A)−f(P)∣∣2≤∣∣f(A)−f(N)∣∣2
也即 d ( A , P ) − d ( A , N ) ≤ 0 d(A,P) - d(A,N) \le 0 d(A,P)−d(A,N)≤0
但是会有 0 − 0 ≤ 0 0 - 0 \le 0 0−0≤0的情况,为了避免这种情况发生,引入margin间隔: α \alpha α
∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 + α ≤ 0 || f(A) - f(P) ||^{2} - || f(A) - f(N) ||^{2} + \alpha \le 0 ∣∣f(A)−f(P)∣∣2−∣∣f(A)−f(N)∣∣2+α≤0 - 三元组损失函数:基于三张图片A,P,N
L ( A , P , N ) = m a x ( ∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 + α , 0 ) L(A,P,N) = max(|| f(A) - f(P) ||^{2} - || f(A) - f(N) ||^{2} + \alpha, 0) L(A,P,N)=max(∣∣f(A)−f(P)∣∣2−∣∣f(A)−f(N)∣∣2+α,0)- 当max左项小于等于零,达到了我们想要的目标,故损失为0;max左项大于零,最终得到一个正的损失值。
- 最小化L的结果就是让max左项小于等于0.
- 代价函数
J = ∑ i = 1 m L ( A ( i ) , P ( i ) , N ( i ) ) J = \sum_{i=1}^{m} L(A^{(i)}, P^{(i)}, N^{(i)}) J=i=1∑mL(A(i),P(i),N(i))- 整个网络代价函数为每一组三元组损失之和, i表示第i组数据
- 关于训练集:
- 需要有同一个人的多张不同照片组成一个个三元组(A,P,N)
- 注意N不能随机选,因为随机选择下的 d ( A , P ) − d ( A , N ) + α ≤ 0 d(A,P) - d(A,N) + \alpha \le 0 d(A,P)−d(A,N)+α≤0很容易达到,这样训练网络梯度算法没什么效果,最终网络很轻松能达到结果,并不能学到什么。故要制作难训练的三元组,也即使 d ( A , P ) d(A,P) d(A,P)尽量接近 d ( A , N ) d(A,N) d(A,N)
- Siamese Network变体之面部验证与二分类
另一训练神经网络的方法是选取一对神经网络(Siamese),使其同时计算这些embeddings(嵌入),比如128维的嵌入/更高维,然后将其输入到逻辑回归单元进行预测,如果是相同的人则输出是1,若是不同的人,输出是0。这就把人脸识别问题转换为一个二分类问题,训练这种系统时可以替换Triplet loss的方法。
- y ^ = σ ( ∑ k = 1 128 w k ∣ f ( x ( i ) ) k − f ( x ( j ) ) k ∣ + b ) \hat{y} = \sigma( \sum_{k=1}^{128} w_{k}|f(x^{(i)})_{k} - f(x^{(j)})_{k}| + b) y^=σ(k=1∑128wk∣f(x(i))k−f(x(j))k∣+b)
- 上式中 ∣ f ( x ( i ) ) k − f ( x ( j ) ) k ∣ |f(x^{(i)})_{k} - f(x^{(j)})_{k}| ∣f(x(i))k−f(x(j))k∣可替换为 χ 2 = ( f ( x ( i ) ) k − f ( x ( j ) ) k ) 2 f ( x ( i ) ) k + f ( x ( j ) ) k \chi^{2} = \frac{(f(x^{(i)})_{k} - f(x^{(j)})_{k})^{2}}{f(x^{(i)})_{k} + f(x^{(j)})_{k}} χ2=f(x(i))k+f(x(j))k(f(x(i))k−f(x(j))k)2
- 在实际部署时,可以预先计算每个员工对应的编码,当某一员工走近时可以使用上方卷积网络计算编码,再与预先计算好的编码比较输出预测值。这种预训练的工作也可以用在triplet loss函数上。
- 总结:把人脸验证当作一个监督学习,创建一个只有成对图片的训练集,目标标签是1表示一对图片是一个人,目标标签是0表示图片中是不同的人。利用不同的成对图片,使用反向传播算法去训练得到Siamese神经网络。
- 术语补充
解释来源知乎:https://www.zhihu.com/question/507322595/answer/2286602597
- encoder 编码器,将信息进行编码(一般是向量化或降维,如词向量)并保持语义信息(encoder的学习方向)
- embedding一般指映射得到的向量,直观含义就是将某种人类能理解的模态数据(如文本、图片),转换为计算机能够处理的向量,这一过程通常称为embed(嵌入)。embedding在不同任务下会有具体的指代:
- 在NLP中,一般会称encoder的结果是embedding
- 在ViT中,称Transformer前,对图像Patch进行特征提取的结果称为embedding。
- decoder 解码器,将特征向量解码为任务相关的输出。如词向量->词,feature map->检测框+类别序列。
- 总体来说,encoder用来提取、凝练(降维)特征,embedding指由某种能理解的模态提取得到的特征,decoder用于将特征向量转化为我们需要的结果。
神经风格迁移
- 效果展示
- 深度卷积网络可视化理解
加入了自己的理解和一些表达,没有去看论文原文,如有错误欢迎批评指正
假如有训练好的卷积神经网络,观察各隐藏层中隐藏单元的计算结果:
- 第一隐藏层有很多隐藏单元。我们遍历一遍数据集找到使这一层的某一个特定单元激活值最大的图片块,发现这些图片块都具有垂直线条的画面(只是举个例子),说明第一层的这个单元对图片中固定区域内的垂直线条“敏感”。
-
为什么我认为是固定区域?可以从卷积的过程去分析,随着卷积深度加深,深层隐藏层内的单元对应最初图片的区域会越来越大(后面会提到)。貌似这个固定区域有官方说法叫感受野(Receptive Field)
- 同理,这个第一层中的其他隐藏单元可能会对其它线条类型(如左斜线等等)“敏感”。以此类推,可以这样理解,第一层的隐藏单元通常会找一些简单的特征,比如说边缘或者颜色阴影。
- 如果在深层的隐藏单元中进行计算,卷积神经网络的深层部分,一个隐藏单元会看到一张图片更大的视野,检测的模式和特征也就更复杂。
- (极端情况下,可以假设每一个像素都会影响到神经网络更深层的输出)
- 再去考虑:CNN中filter也有自己的数量,如 5 ∗ 5 ∗ 3 ∗ 12 5*5*3*12 5∗5∗3∗12中的12,就是要对前一层某一特定区域进行12次卷积,可能得到对这一特定区域的12次不同特点的提取。后续风格代价部分也会具体举例描述。
- 神经风格迁移算法概要
构建一个神经风格迁移系统关键需要定义其代价函数,再梯度下降法对代价函数最小化。
- 定义:内容图像C(content),风格图片S(style),生成新图片G(generate)
- 代价函数 = 内容代价函数(度量C和G的相似度) + 风格代价函数(度量S和G的相似度)
J ( G ) = α J c o n t e n t ( C , G ) + β J s t y l e ( S , G ) J(G) = \alpha J_{content}(C,G) + \beta J_{style}(S,G) J(G)=αJcontent(C,G)+βJstyle(S,G)
α , β \alpha , \beta α,β为两个超参数,赋予两个代价一定的权重
- 算法运行流程:
- 随机初始化生成新图像G,比如100*100*3的图片(由于随机生成使得G就是一个白噪声图像–花屏)
- 使用代价函数 J ( G ) J(G) J(G)用梯度下降法逐步更新G图像的像素值,慢慢得到生成图片。
- 内容代价函数
- 选用隐藏层l计算内容代价:(包含了自己的一些理解)
- 如果l=1(浅层):代价函数不断最小化,会使生成图片非常非常接近内容图片
- 如果l为深层:生成图片会确保与内容图片整体上有同样的要素(比如:图片上都含有一只狗)
- 实际中l的选择不会太深也不会太浅。
- J c o n t e n t ( C , G ) = 1 / 2 ∣ ∣ a [ l ] [ C ] − a [ l ] [ G ] ∣ ∣ 2 2 J_{content}(C,G) = 1/2 || a^{[l][C]} - a^{[l][G]} ||^{2}_{2} Jcontent(C,G)=1/2∣∣a[l][C]−a[l][G]∣∣22
- 1/2这个归一化影响不大,因为我们有超参数 α \alpha α进行调整。
- 上式a表示层l的激活单元矩阵,计算的是做差后矩阵的L2范数的平方,也即各个差值的平方和。
- 风格代价函数
-
我们取出了某一隐藏层,为方便分析,假设这隐藏层有五个通道,我们需要关注任两个通道对应位置的激活项,并计算它们的相关系数。
-
一个通道是对某个特征的检测(因为生成该通道的filter参数确定),通道中某一处数值的强弱就是对当前特征强弱的反应
-
来看一个例子:
- 假设红色的通道(编号1)能找出图片中的特定位置是否含有这些垂直的纹理(编号3),而第二个黄色的通道(编号2)可以粗略地找出橙色的区域。
- 如果它们有高度相关性,那么这幅图片中出现垂直纹理的地方很大概率是橙色的;如果它们是不相关的,图片中有垂直纹理的地方很大概率不是橙色的。
- 相关系数描述的是线性相关关系,(由于是线性关系)直观上可以理解为当图片某处出现这种垂直纹理时,该处又同时是橙色的可能性。
-
相关系数提供了一种去测量这些不同的特征的方法,去测量它们在图片中的各个位置同时出现或不同时出现的频率。
-
如果我们在通道之间使用相关系数来描述通道的风格,我们需要测量生成图像中第一个通道(编号1)是否与第二个通道(编号2)相关,通过测量得知在生成的图像中垂直纹理和橙色同时出现或者不同时出现的频率,进而能够测量生成的图像的风格与输入的风格图像的相似程度。
-
公式描述
- 设 a i , j , k [ l ] a_{i,j,k}^{[l]} ai,j,k[l]表示网络中第l隐藏层中i(高度),j(宽度),k(通道)对应位置下的激活项。
- 需要计算风格矩阵 G [ l ] ( S ) , G [ l ] ( G ) G^{[l](S)}, G^{[l](G)} G[l](S),G[l](G),两者大小均为 n c h a n n e l s ∗ n c h a n n e l s n_{channels}*n_{channels} nchannels∗nchannels
- 以风格矩阵
G
[
l
]
G^{[l]}
G[l]中的某一个值计算为例(不在考虑是S图像的还是G图像的了,都一样):
- $ G^{[l]}_{kk’}$ 表示第k通道和第k’通道之间的对应位置上的激活项乘积之和
G k k ′ [ l ] = ∑ i = 1 n H [ l ] ∑ j = 1 n W [ l ] a i j k [ l ] a i j k ′ [ l ] G^{[l]}_{kk'} = \sum_{i=1}^{n_{H}^{[l]}} \sum_{j=1}^{n_{W}^{[l]}} a^{[l]}_{ijk} a^{[l]}_{ijk'} Gkk′[l]=i=1∑nH[l]j=1∑nW[l]aijk[l]aijk′[l] - $ G^{l}{kk’}, G^{l}{kk’} $ 的计算就是上述公式,进而得到 $ G^{l}, G^{l} $
- $ G^{[l]}_{kk’}$ 表示第k通道和第k’通道之间的对应位置上的激活项乘积之和
- 由此,有风格代价函数:
J s t y l e [ l ] ( S , G ) = 1 ( 2 n H [ l ] n W [ l ] n C [ l ] ) 2 ∣ ∣ G [ l ] ( S ) − G [ l ] ( G ) ∣ ∣ F 2 J_{style}^{[l]}(S,G) = \frac{1}{(2n_{H}^{[l]}n_{W}^{[l]}n_{C}^{[l]})^{2}} || G^{[l](S)} - G^{[l](G)} ||_{F}^{2} Jstyle[l](S,G)=(2nH[l]nW[l]nC[l])21∣∣G[l](S)−G[l](G)∣∣F2- F角标表示矩阵的Frobenius范数, ∣ ∣ A ∣ ∣ F = ∑ i = 1 m ∑ j = 1 n a i j 2 ||A||_{F} = \sqrt{\sum_{i=1}^{m} \sum_{j=1}^{n} a_{ij}^{2}} ∣∣A∣∣F=∑i=1m∑j=1naij2
- 另外, J s t y l e [ l ] ( S , G ) J_{style}^{[l]}(S,G) Jstyle[l](S,G)计算式前面那一堆归一化系数实际上也用不着,我们有超参数 $ \beta $
- 若果要对网络各隐藏层都使用风格代价函数,会让结果变得更好:定义代价函数为,把各个层的风格代价函数结果乘以对应权重
λ
[
l
]
\lambda^{[l]}
λ[l]再加起来。
J s t y l e ( S , G ) = ∑ l λ [ l ] J s t y l e [ l ] ( S , G ) J_{style}(S,G) = \sum_{l} \lambda^{[l]} J_{style}^{[l]}(S,G) Jstyle(S,G)=l∑λ[l]Jstyle[l](S,G)
- 一维到三维推广
- 我直接写两个式子,看看就懂了(注意,这里的*特指卷积,在其他地方出现的*还是乘的意思)
- 一维: ( 14 × 1 ) ∗ ( 5 × 1 × 16 ) − o u t p u t > ( 10 × 16 ) (14 \times 1)*(5 \times 1 \times 16) -output> (10 \times 16) (14×1)∗(5×1×16)−output>(10×16)
-
1表示通道数,16表示filter个数
- 二维: ( 14 × 14 × 1 ) ∗ ( 5 × 5 × 1 × 16 ) − o u t p u t > ( 10 × 10 × 16 ) (14 \times 14 \times 1)*(5 \times 5 \times 1 \times 16) -output> (10 \times 10 \times 16) (14×14×1)∗(5×5×1×16)−output>(10×10×16)
- 三维: ( 14 × 14 × 3 × 1 ) ∗ ( 5 × 5 × 3 × 1 × 16 ) − o u t p u t > ( 10 × 10 × 3 × 16 ) (14 \times 14 \times 3 \times 1)*(5 \times 5 \times 3 \times 1 \times 16) -output> (10 \times 10 \times 3 \times 16) (14×14×3×1)∗(5×5×3×1×16)−output>(10×10×3×16)
d实际上就是distance的意思 ↩︎