Deep Learning Note: 4-10 人脸识别

1. 人脸认证和人脸识别

  在人脸认证(Face Verification)问题中,输入为一张图像和身份(姓名或 ID 等),输出为图像中的人是否与输入的身份相匹配。人脸认证是一个 1:1 问题,即只需要判断输入的一个图像是否与输入的一个身份相符。

  在人脸识别(Face Recognition)问题中,有一个记录了 K 个人身份信息的数据库,对于一张输入图像,如果图像中的人在数据库中有记录,则输出图像中的人的身份信息,否则输出“未识别”。人脸识别是一个 1:K 问题,对准确率有更高的要求。假设某个人脸识别系统有 99% 的准确率,看上去很高,但如果 K = 100,则每识别一遍所有的人就可能出现 1 次错误,因此实际中往往会要求系统具有非常高的准确率。

2. One Shot Learning

  对于很多人脸识别的系统,在可用的训练数据中,通常每个人只有一张照片,系统需要需要能通过一个样本就学会识别这个人的身份,这是一个 One Shot Learning 的问题。

  实现人脸识别的一个直接(但是错误)的思路是使用普通的图像识别方法,即训练一个卷积网络,输入一张人的照片,输出人的身份。这样做有两个问题:其一是每个人只有一张图片,不足以训练网络来识别一个特定的人;其二是每当要识别新的人,就需要重新训练。

  实际中,实现人脸识别这种 One Shot Learning 问题的一个方法是训练网络来学习一个相似度函数(Similarity Function),即:

\begin{equation}
d(img1, img2) = degree \; of \; difference \; between \; images \tag{1}
\end{equation}

  相似度函数的输入为两张人脸的图像,输出是这两张图像中人脸的相似度:如果两张图像中的人很相似,则输出一个较小的值,否则输出一个较大的值。预测时,可以选择一个判定的阈值 $\tau$,如果 $d(img1, img2) \leq \tau$,则判断两张图像中是同一个人;如果 $d(img1, img2) > \tau$,则判断两张图像中的不是同一个人。这里的 $\tau$ 可以作为一个超参数。

  在进行人脸识别时,对于一张输入图像,使用式 (1) 计算它与数据库中所有图像的相似度,如果输入图像与数据库中的某张图像非常相似,是同一个人,则成功识别到了输入图像中的人的身份;如果输入图像与数据库中的所有图像都不相似,则认为输入图像中人的身份未知。如果需要将新的人加入到识别系统中,则只需要将其照片和身份信息放入数据库,不需要重新训练。

3. Siamese Network

  相似度函数可以通过 Siamese Network 训练得到。

  图 1 是一个没有预测节点的传统的卷积神经网络,输入一张图像 $x^{(1)}$,经过若干个卷积层、池化层、全连接层的组合,在进行最终预测前,网络可以输出一个向量 $f(x^{(1)})$,可以把 $f(x^{(1)})$ 看做是 $x^{(1)}$ 的一个编码。

图 1

图 1

图 2

图 2

  对于另一张图像 $x^{(2)}$,使用同样的网络,可以得到一个向量 $f(x^{(2)})$,如图 2 所示。$f(x^{(2)})$ 可以看做是 $x^{(2)}$ 的一个编码。如果 $f(x)$ 能很好地编码 $x$,则可以通过比较 $f(x^{(1)})$ 和 $f(x^{(2)})$ 来得到 $x^{(1)}$ 和 $x^{(2)}$ 两张图像的相似度,如计算 $f(x^{(1)})$ 和 $f(x^{(2)})$ 两个向量的欧几里得范数:

\begin{equation}
d(x^{(1)}, x^{(2)}) = \left\Vert f(x^{(1)}) – f(x^{(2)}) \right\Vert_2^{2} \tag{2}
\end{equation}

  像上面这样,使用同一个网络计算两个不同的输入,并对结果进行比较的结构,就称为 Siamese Network,可以在这篇论文中找到更详细的内容。

  使用网络对图像进行编码,网络的参数就决定了具体的编码方式,即 $f(x^{(i)})$。我们需要训练网络,使得:

  • 如果 $x^{(i)}$ 和 $x^{(j)}$ 是同一个人,则 $d(x^{(i)}, x^{(j)})$ 的值很小;
  • 如果 $x^{(i)}$ 和 $x^{(j)}$ 不是同一个人,则 $d(x^{(i)}, x^{(j)})$ 的值很大。

4. Triplet Loss

  训练上述 Siamese Network 的一种方法是使用 Triplet 损失函数,并在其上进行梯度下降。

图 3

图 3

  图 3 中有三张该图像:Anchor(以下简称 A)、Positive(以下简称 P)和 Negative(以下简称 N)。它们可以分为两组,其中 A 和 P 是同一个人,A 和 N 不是同一个人,如前所述,我们希望 $d(A, P)$ 很小,$d(A, N)$ 很大,即有:

\begin{equation}
d(A, P) \leq d(A, N) \tag{3}
\end{equation}

  将式 (2) 带入式 (3),可得:

\begin{equation}
\left\Vert f(A) – f(P) \right\Vert_2^{2} \leq \left\Vert f(A) – f(N) \right\Vert_2^{2}
\end{equation}

\begin{equation}
\left\Vert f(A) – f(P) \right\Vert_2^{2} – \left\Vert f(A) – f(N) \right\Vert_2^{2} \leq 0 \tag{4}
\end{equation}

  若以式 (4) 为目标,则会存在一个问题:如果网络习得编码方式,即 $f(x)$ 是一个常数函数($f(x) = c$,其中 $c$ 为常数),则式 (4) 中两个相减的项都为零,虽然能够满足条件,但 $f(x)$ 本身并没有对 $x$ 进行任何有意义的编码。为了避免这种情况,需要引入一个不为零的值 $\alpha$,使得式 (4) 不等号左边的值始终略小于零,而不能等于零,即:

\begin{equation}
\left\Vert f(A) – f(P) \right\Vert_2^{2} – \left\Vert f(A) – f(N) \right\Vert_2^{2} \leq 0 – \alpha \tag{4}
\end{equation}

  式 (4) 也可以写成:

\begin{equation}
\left\Vert f(A) – f(P) \right\Vert_2^{2} – \left\Vert f(A) – f(N) \right\Vert_2^{2} + \alpha \leq 0 \tag{5}
\end{equation}

  即:

\begin{equation}
d(A, P) – d(A, N) + \alpha \leq 0 \tag{6}
\end{equation}

  这里的 $\alpha$ 称为 Margin,它控制了 $d(A, P)$ 和 $d(A, N)$ 之间的最小差距,是一个超参数。

  Triplet 损失函数定义在如前所述的 A、P、N 三张图像上,图像 A 和图像 P 是同一个人,图像 A 和 图像 N 不是同一个人。Triplet 损失函数的定义为:

\begin{equation}
L(A, P, N) = max \left( \left\Vert f(A) – f(P) \right\Vert_2^{2} – \left\Vert f(A) – f(N) \right\Vert_2^{2} + \alpha, 0 \right) \tag{6}
\end{equation}

  式 (6) 中对 $\left\Vert f(A) – f(P) \right\Vert_2^{2} – \left\Vert f(A) – f(N) \right\Vert_2^{2} + \alpha$ 和 0 取最大值,如果满足式 (5) 的条件,则 $L(A, P, N)$ 的值为 $0$,否则 $L(A, P, N)$ 的值为 $\left\Vert f(A) – f(P) \right\Vert_2^{2} – \left\Vert f(A) – f(N) \right\Vert_2^{2} + \alpha$,是一个大于 $0$ 的数。

  通过最小化 $L(A, P, N)$,可以令 $\left\Vert f(A) – f(P) \right\Vert_2^{2} – \left\Vert f(A) – f(N) \right\Vert_2^{2} + \alpha$ 向小于等于零的方向发展,只要它小于零,则不关心它比零小多少。

  以上是对单个样本的损失函数的定义,整个样本集的代价函数定义为各个样本的 $L(A, P, N)$ 之和,即:

\begin{equation}
J = \sum\limits_{i=1}^m L(A^{(i)}, P^{(i)}, N^{(i)}) \tag{7}
\end{equation}

  例如训练集中有 1000 个人的 10000 张图像,则用这 10000 张图像组成 A、P、N 的图像对用作训练,通过最小化式 (7) 得到前述 Siamese Network 的参数,使得 Siamese Network 能够对图像进行符合要求的编码。

  对于 A、P、N 图像的选择,如果只是随机地从同一个人的照片中选出两张作为 A 和 P,再随机地从其他人的照片中选择一张作为 N,则式 (6) 的条件其实很好满足,因为 A 和 N 有很大概率相差很大,而 A 和 P 往往相差很小,这样的训练集过于简单,网络学不到多少东西。合适的做法是,选择更困难的 A、P、N 组合,即三者相差不大,有 $d(A, P) \approx d(A, N)$,这样网络就要努力使 $d(A, P)$ 更小或 $d(A, N)$ 更大,有利于其学习,提高计算效率。

  需要注意的是,在训练集中,每个人需要有多张图片,才能从中选出 A 和 P,否则就无法进行训练。训练完成后,网络就可以用于前述的 One Shot Learning 问题,只需要一张输入图像,就可以识别图像中的人。关于以上算法更详细的内容可以在这篇论文中找到。

  现代的商用人脸识别系统往往使用了上百万、上千万甚至上亿的图像进行训练,即便从现代的标准来看,这也是海量的数据,一般人难以获得和训练。有些公司将他们训练得到的参数开源出来,可以在这些开源实现的基础上进行进一步的训练。

5. 人脸验证和二分类

  除了使用 Triplet 损失函数,还可以通过二分类的方法训练网络参数。

图 4

图 4

  如图 4 所示,使用两个 Siamese Network 对两张图像 $x^{(i)}$ 和 $x^{(j)}$ 进行编码,然后将两个编码输入一个逻辑回归单元并给出预测:如果 $x^{(i)}$ 和 $x^{(j)}$ 是同一个人,则输出 $1$,否则输出 $0$。其中逻辑回归单元计算 $\hat{y}$ 的方法是:

\begin{equation}
\hat{y} = \sigma(\sum\limits_{k=1}^n w\left|f(x^{(i)})_k – f(x^{(j)})_k \right| + b) \tag{8}
\end{equation}

  式 (8) 中 $n$ 为 $f(x)$ 的长度,$f(x)_k$ 表示 $f(x)$ 中的第 $k$ 项。式 (8) 通过对 $f(x^{(i)})$ 和 $f(x^{(j)})$ 逐元素求差的绝对值,得到二者之间差异程度,以此作为一个逻辑回归单元的输入特征,计算该单元的输出,其中 $w$ 和 $b$ 为这个逻辑回归单元的权重和偏置参数。通过训练图 4 所示的网络,也可以得到 Siamese Network 的参数,来对图像进行编码。

  除了像式 (8) 那样逐元素计算 $f(x^{(i)})$ 和 $f(x^{(j)})$ 的差的绝对值,也可以使用 $\chi^2$ 相似度(详见这篇论文),即:

\begin{equation}
\hat{y} = \sigma(\sum\limits_{k=1}^n w \frac{\left(f(x^{(i)})_k – f(x^{(j)})_k\right)^2}{f(x^{(i)})_k + f(x^{(j)})_k} + b) \tag{8}
\end{equation}

  训练时,每个样本包含两张图像,如果这两张图像是同一个人,则该样本的标签为 1,否则为 0。使用这样的训练集对网络进行训练,可以得到 Siamese Network 和最后的逻辑回归单元的参数。

  需要注意的是,图 4 中的两个 Siamese Network 是完全相同的,它们共享同一套参数。在部署时,可以预先计算数据库中所有图像的编码并存储起来,这样对于新的输入图像,可以只计算该图像的编码,然后直接与预先计算的数据库中图像的编码进行比较,不需要重复计算数据库中的图像的编码。这种预先计算的技巧也适用于前面使用 Triplet Loss 的实现。