人脸识别的限制
人脸识别的主要限制来源于数据集,对于我们想要用人脸识别管理的团队or公司,其中每个人的图像数据都非常有限,达不到我们训练深度网络动辄上千上万的要求。另外,如果训练一个对应团队内所有成员的多元分类器,当团队新增成员的时候训练工作就要推倒重来,非常地消耗算力。这种样本非常有限,乃至于只有一个样本的学习任务,就被称作单样本学习(one shot learning)
为了解决这种问题,我们不如转换一下思路,将多元分类问题转换为相似度比较问题。对于给定的两张照片,我们要求网络判断他们的差异值有多大,输出一个量化的实数,若该差异值低于某个阈值,我们就认为两张图片上是同一个人;反之则认为两者并不是同一人。这样,我们的核心算法就变成了一个相似度比较算法,当团队中新加入成员时,不需要对网络做任何修改,只需要把新成员的照片存入数据库即可。
孪生网络架构
在普通的CNN中,我们输入一张图片,经过卷积层、池化层、全连通层等等,最后得到一个多维列向量(比如128维),这128维储存了由输入的人像图片经过复杂运算得到的特征值,我们可以通过比对两张图像的特征向量,来得到两个人脸相似度的量化结果。由于两张图像通过的网络是完全相同的,因此这个架构被称为孪生网络架构。
要计算两个特征向量差异有多大,可以通过两向量之差的模长的平方来判断,即
d
(
x
(
i
)
,
x
(
j
)
)
=
∣
∣
f
(
x
(
i
)
)
−
f
(
x
(
2
)
)
∣
∣
2
2
d(x^{(i)},x^{(j)})=||f(x^{(i)})-f(x^{(2)})||_2^2
d(x(i),x(j))=∣∣f(x(i))−f(x(2))∣∣22
在训练网络的过程中,我们希望达到的效果就是,若两张照片中是同一个人,我们希望 d ( x ( i ) , x ( j ) ) d(x^{(i)},x^{(j)}) d(x(i),x(j))尽量小;若两张照片里不是同一个人,则希望 d ( x ( i ) , x ( j ) ) d(x^{(i)},x^{(j)}) d(x(i),x(j))尽量大。为了达到这样的效果,我们引入了三胞损失。
三胞损失(Triplet Loss)
为了定义训练的损失函数,我们采用三胞损失函数计算,这里的三胞指的是三张照片,其中两张是来自同一个人(anchor和positive),另一张是干扰项(negative)。我们希望由同一个人的两张照片计算出的差异值
d
(
A
,
P
)
d(A,P)
d(A,P)能小于等于来自不同的人的两张照片
d
(
A
,
N
)
d(A,N)
d(A,N)。且为了防止网络“摆烂”,即网络对于任何照片都输出相同的特征值,我们还设置了边距
α
\alpha
α,最终我们的期望是
d
(
A
,
P
)
−
d
(
A
,
N
)
+
α
≤
0
d(A,P)-d(A,N)+\alpha\le 0
d(A,P)−d(A,N)+α≤0
如此,通过调整
α
\alpha
α,我们能控制网络分辨两张照片是否为同一人的严格程度。最后,定义损失函数如下,当区分度足够的时候损失为0,而区分度不够的时候就以多出来的部分作为损失:
L
(
A
,
P
,
N
)
=
max
(
d
(
A
,
P
)
−
d
(
A
,
N
)
+
α
,
0
)
\mathcal{L}(A,P,N)=\max(d(A,P)-d(A,N)+\alpha,0)
L(A,P,N)=max(d(A,P)−d(A,N)+α,0)同理可得代价函数
J
(
⋯
)
=
∑
i
=
1
m
L
(
A
(
i
)
,
P
(
i
)
,
N
(
i
)
)
J(\cdots)=\sum_{i=1}^m\mathcal{L}(A^{(i)},P^{(i)},N^{(i)})
J(⋯)=i=1∑mL(A(i),P(i),N(i))
要训练一个可靠的网络,大概需要有
1
k
1k
1k个人的
10
k
10k
10k张照片,也就是平均一人十张照片。不过在训练结束后,该网络就可用于单样本问题,即使你只有待检测成员的一张照片,它也能完成识别任务。
另外,在选择三胞损失中的第三张混淆照片时,如果随机的选择一张其他人的照片,网络很容易就能达到 d ( A , P ) − d ( A , N ) + α ≤ 0 d(A,P)-d(A,N)+\alpha\le 0 d(A,P)−d(A,N)+α≤0的要求,最好选择一些长相相似分辨难度高的混淆项,让网络的功能更强大。
二元分类
除了三胞损失,我们还可以将两个列向量作为输入给到一个二元分类网络中,输出1表示是同一个人,0表示不是同一个人。通过训练,使分类器能够通过获得一个合适的权重,能够在运算后输出两张照片是一个人的概率。
y
^
=
σ
(
∑
k
=
1
n
w
i
∣
f
(
x
(
i
)
)
k
−
f
(
x
(
j
)
)
k
∣
+
b
)
\hat{y}=\sigma(\sum_{k=1}^nw_i|f(x^{(i)})_k-f(x^{(j)})_k|+b)
y^=σ(k=1∑nwi∣f(x(i))k−f(x(j))k∣+b)
除了把两个特征向量之差的绝对值作为输入特征,还有其他的变种,比如
χ
2
\chi^2
χ2公式:
(
f
(
x
(
i
)
)
k
−
f
(
x
(
j
)
)
k
)
2
f
(
x
(
i
)
)
k
+
f
(
x
(
j
)
)
k
\frac{(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(f(x(i))k−f(x(j))k)2
虽然理论上的网络架构仍然是孪生网络,意味着我们要输入两张图片在两个一样的网络上运算。实际上对于数据库里用来对比的图片,我们可以预先计算出特征向量,这样进行人脸识别的时候只需计算待检测人脸的特征向量即可,节省一半的算力。