深度学习—从入门到放弃(八)使用CNN进行人脸识别
问题重述
假设我们需要进行面部识别系统的开发,我们的思路如下:
- 有一个有K个人的人脸数据的数据集
- 进行人脸识别时我们先有一个输入图像
- 输出图像为输入图像在数据集里的分类标签
针对整个思路我们又面临着如下的挑战:
- 人的个数多但是数据集里每一个人对应的图像又很少,即数据量小,我们需要在给定较少输入图像的情况下进行人脸识别
鉴于以上,我们不选择简单的分类器,而是选择CNN,让CNN去学习相似度(类似于聚类)
使用 CNN 进行人脸识别
大型 CNN 的一种应用是面部识别。面部识别中的问题表述与我们目前看到的图像分类略有不同。在面部识别中,我们不希望模型可以学习固定数量的个体。如果是这种情况,那么要学习一个新人,就需要修改架构的输出部分并重新训练以适应新人。
相反,我们训练一个模型来学习嵌入,其中来自同一个人的图像在嵌入空间中彼此靠近,而不同人对应的图像相距很远。当模型被训练时,它将图像作为输入并输出与图像对应的嵌入向量。
查看数据
import requests, zipfile, io, os
# original link: https://github.com/ben-heil/cis_522_data.git
url = 'https://osf.io/2kyfb/download'
fname = 'faces'
if not os.path.exists(fname+'zip'):
print("Data is being downloaded...")
r = requests.get(url, stream=True)
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall()
print("The download has been completed.")
else:
print("Data has already been downloaded.")
一个训练有素的面部识别系统应该能够将同一个人的不同图像相对靠近地映射在一起。我们将加载三个人的 15 张图像
预处理
现在我们已经加载了图像,我们需要对它们进行预处理。为了使网络更容易学习图像,我们将它们裁剪为仅包含人脸。
MTCNN检测人脸并在人脸周围裁剪图像。然后我们将所有图像堆叠在一个张量中。
嵌入预训练网络
我们加载了一个名为FaceNet的预训练面部识别模型。它在VGGFace2数据集上进行了训练,该数据集包含 9131 个人的331万张图像。
我们使用预训练模型来计算所有输入图像的嵌入。
resnet = InceptionResnetV1(pretrained='vggface2').eval().to(DEVICE)
在这里我们计算了我们数据集里这三个人各自的嵌入向量。并且在通过PCA降维后进行展示。
# Calculate embedding
resnet.classify = False
bruce_embeddings = resnet(bruce_tensor.to(DEVICE))
neil_embeddings = resnet(neil_tensor.to(DEVICE))
pam_embeddings = resnet(pam_tensor.to(DEVICE))
由上图我们可以发现每个个体对应的图像在嵌入空间中相互分离,并且呈现一种聚类的趋势。
总结
上图显示了在人脸识别系统中,我们是如何通过嵌入向量的欧几里得距离去衡量图像和图像之间相似度的过程。
欢迎大家关注公众号奇趣多多一起交流!
深度学习—从入门到放弃(一)pytorch基础
深度学习—从入门到放弃(二)简单线性神经网络
深度学习—从入门到放弃(三)多层感知器MLP
深度学习—从入门到放弃(四)优化器
深度学习—从入门到放弃(五)正则化
深度学习—从入门到放弃(六)CNN入门
深度学习—从入门到放弃(七)CNN进阶,迁移学习