1. 首页
  2. 技术文章

如何在Keras中使用FaceNet开发人脸识别系统

人脸识别是一项基于计算机的视觉任务,用于根据人脸的照片来识别和验证人。

如何在Keras中使用FaceNet开发人脸识别系统

FaceNet是Google的研究人员于2015年开发的人脸识别系统,该系统在一系列人脸识别基准数据集上取得了当时的最新水平。FaceNet系统可以广泛使用,这要归功于该模型的多个第三方开源实现以及预先训练的模型的可用性。

FaceNet系统可用于从面部提取高质量的特征(称为面部嵌入),然后将其用于训练面部识别系统。

在本教程中,您将发现如何使用FaceNet和SVM分类器来开发面部检测系统,以从照片中识别人物。

完成本教程后,您将知道:

  • 关于Google开发的FaceNet人脸识别系统以及开源实现和预先训练的模型。
  • 如何准备面部检测数据集,包括首先通过面部检测系统提取面部,然后通过面部嵌入提取面部特征。
  • 如何拟合,评估和演示SVM模型以从人脸嵌入预测身份。

让我们开始吧。

教程概述

本教程分为五个部分。他们是:

  1. 人脸识别
  2. FaceNet模型
  3. 如何在Keras中加载FaceNet模型
  4. 如何检测人脸以进行人脸识别
  5. 如何开发人脸分类系统

人脸识别

人脸识别是从人脸照片中识别和验证人的一般任务。

2011年有关人脸识别的书名为《人脸识别手册》,介绍了人脸识别的两种主要模式,即:

  • 面部验证。给定脸部与已知身份的一对一映射(例如,此人是人吗?)。
  • 人脸识别。给定脸部与已知脸部数据库(例如,此人是谁)的一对多映射。

面部识别系统有望自动识别图像和视频中存在的面部。它可以以两种模式中的一种或两种来运行:(1)人脸验证(或身份验证),以及(2)人脸识别(或识别)。

在本教程中,我们将重点介绍人脸识别任务。

想要通过深度学习获得用于计算机视觉的结果吗?

立即参加我的7天免费电子邮件速成课程(包括示例代码)。

单击以注册,并获得该课程的免费PDF电子书版本。

FaceNet模型

FaceNet是Florian Schroff等人描述的人脸识别系统。在Google于2015年发表的论文中,标题为“ FaceNet:人脸识别和聚类的统一嵌入”。

这是一个系统,给定一张人脸图片,它将从该人脸提取高质量特征并预测代表这些特征的128个元素矢量,称为人脸嵌入。

如何在Keras中加载FaceNet模型

有许多项目提供工具来训练基于FaceNet的模型并利用预训练的模型。

也许最著名的就是OpenFace,它提供了使用PyTorch深度学习框架构建和训练的FaceNet模型。OpenFace到Keras有一个端口,称为Keras OpenFace,但是在撰写本文时,这些模型似乎需要Python 2,这是非常有限的。

大卫·桑德伯格(David Sandberg)将另一个著名的项目称为FaceNet,该项目提供使用TensorFlow构建和训练的FaceNet模型。尽管在撰写本文时未提供基于库的安装,也未提供干净的API,但该项目看起来很成熟。有用的是,David的项目提供了许多高性能的预训练FaceNet模型,并且有许多项目可以移植或转换这些模型以用于Keras。

一个著名的例子是Hiroki Taniai的Keras FaceNet。他的项目提供了一个脚本,用于将Inception ResNet v1模型从TensorFlow转换为Keras。他还提供了可以使用的经过预先训练的Keras模型。

在本教程中,我们将使用Hiroki Taniai提供的经过预训练的Keras FaceNet模型。它在MS-Celeb-1M数据集上进行了训练,并期望输入图像是彩色的,像素值变白(在所有三个通道中均经过标准化)并且具有160×160像素的正方形。

可以从这里下载模型:

  • Keras FaceNet预训练模型(88兆字节)

下载模型文件,并将其以文件名“ facenet_keras.h5 ”放置在当前工作目录中。

我们可以使用load_model()函数直接在Keras中加载模型;例如:

# example of loading the keras facenet model
from keras.models import load_model
# load the model
model = load_model(‘facenet_keras.h5’)
# summarize input and output shape
print(model.inputs)print(model.outputs)

运行示例将加载模型并打印输入和输出张量的形状。

我们可以看到,该模型确实期望输入正方形彩色图像(形状为160×160),并输出嵌入的人脸作为128元素矢量。

# [<tf.Tensor ‘input_1:0’ shape=(?, 160, 160, 3) dtype=float32>]
# [<tf.Tensor ‘Bottleneck_BatchNorm/cond/Merge:0’ shape=(?, 128) dtype=float32>]

现在我们有了FaceNet模型,我们可以探索使用它了。

如何检测人脸以进行人脸识别

在执行面部识别之前,我们需要检测面部。

人脸检测是自动在照片中定位人脸并通过在其范围周围绘制边界框来对其进行定位的过程。

在本教程中,我们还将使用多级层叠卷积神经网络(MTCNN)进行面部检测,例如从照片中查找和提取面部。这是用于面部检测的最先进的深度学习模型,在2016年的论文“使用多任务级联卷积网络的联合面部检测和对齐”中进行了描述。

我们将在ipazc / mtcnn项目中使用Ivánde Paz Centeno提供的实现。也可以通过pip如下安装:

sudo pip install mtcnn

我们可以通过导入库并打印版本来确认库是否已正确安装;例如:

# confirm mtcnn was installed correctly
import mtcnn
# print version
print(mtcnn.__version__)

运行示例将打印库的当前版本。

0.1.0

我们可以使用mtcnn库来创建面部检测器,并提取面部以供我们在后续部分中与FaceNet面部检测器模型一起使用。

第一步是将图像加载为NumPy数组,我们可以使用PIL库和open()函数来实现。如果图像具有Alpha通道或黑白图像,我们还将图像转换为RGB。

# load image from file
image = Image.open(filename)
# convert to RGB, if needed
image = image.convert(‘RGB’)
# convert to array
pixels = asarray(image)

接下来,我们可以创建一个MTCNN人脸检测器类,并使用它来检测加载的照片中的所有人脸。

# create the detector, using default weights
detector = MTCNN()
# detect faces in the image
results = detector.detect_faces(pixels)

结果是一个边界框列表,其中每个边界框都定义了边界框的左下角以及宽度和高度。

如果我们假设实验中照片只有一张脸,则可以如下确定边界框的像素坐标。有时库会返回负像素索引,我认为这是一个错误。我们可以通过获取坐标的绝对值来解决此问题。

# extract the bounding box from the first face
x1, y1, width, height = results[0][‘box’]
# bug fixx
1, y1 = abs(x1), abs(y1)
x2, y2 = x1 + width, y1 + height

我们可以使用这些坐标来提取人脸。

# extract the face
face = pixels[y1:y2, x1:x2]

然后,我们可以使用PIL库将脸部小图像调整为所需的大小;具体来说,该模型期望的是形状为160×160的正方形输入面。

# resize pixels to the model size
image = Image.fromarray(face)
image = image.resize((160, 160))
face_array = asarray(image)

将所有这些内容结合在一起,函数extract_face()将从加载的文件名中加载照片并返回提取的面部。假定照片包含一张脸,并且将返回检测到的第一张脸。

function for face detection with mtcnn

from PIL import Image

from numpy import asarray

from mtcnn.mtcnn import MTCNN

extract a single face from a given photograph

def extract_face(filename, required_size=(160, 160)):

load image from file

image = Image.open(filename)

convert to RGB, if needed

image = image.convert(‘RGB’)

convert to array

pixels = asarray(image)

create the detector, using default weights

detector = MTCNN()

detect faces in the image

results = detector.detect_faces(pixels)

extract the bounding box from the first face

x1, y1, width, height = results[0][‘box’]

bug fix

x1, y1 = abs(x1), abs(y1)

x2, y2 = x1 + width, y1 + height

extract the face

face = pixels[y1:y2, x1:x2]

resize pixels to the model size

image = Image.fromarray(face)

image = image.resize(required_size)

face_array = asarray(image)

return face_array

load the photo and extract the face

pixels = extract_face(‘…’)

我们可以根据需要在下一部分中使用此功能来提取人脸,这些人脸可以作为FaceNet模型的输入提供。

如何开发人脸分类系统

在本节中,我们将开发一个面部检测系统来预测给定面部的身份。

该模型将使用包含5个不同名人的许多照片的“ 5张名人面孔数据集”进行训练和测试。

我们将使用MTCNN模型进行人脸检测,将使用FaceNet模型为每个检测到的人脸创建人脸嵌入,然后我们将开发线性支持向量机(SVM)分类器模型来预测给定人脸的身份。

5张名人面孔数据集

5位名人面孔数据集是一个小型数据集,其中包含名人的照片。

数据集由Dan Becker准备并提供,可以在Kaggle上免费下载。注意,必须使用Kaggle帐户才能下载数据集。

下载数据集(这可能需要Kaggle登录),data.zip(2.5兆字节),并使用文件夹名称“ 5-celebrity-faces-dataset ”将其解压缩到本地目录中。

现在,您应该具有一个具有以下结构的目录(请注意,某些目录名称中存在拼写错误,并且在本示例中按原样保留它们):

5-celebrity-faces-dataset
├── train│  
├── ben_afflek│  
├── elton_john│  
├── jerry_seinfeld│  
├── madonna│   └── mindy_kaling
└── val    
├── ben_afflek    
├── elton_john    
├── jerry_seinfeld    
├── madonna    
└── mindy_kaling

我们可以看到有一个训练数据集和一个验证或测试数据集。

查看目录中的某些照片,我们可以看到这些照片为面部提供了各种方向,光线和各种尺寸的图像。重要的是,每张照片都包含该人的一张脸。

我们将使用此数据集作为分类器的基础,仅在“ train ”数据集上进行训练,并对“ val ”数据集中的人脸进行分类。您可以使用相同的结构来开发带有您自己的照片的分类器。

检测人脸

第一步是检测每张照片中的人脸,并将数据集简化为一系列人脸。

让我们测试上一节中定义的面部检测器功能,特别是extract_face()

在“ 5-celebrity-faces-dataset / train / ben_afflek / ”目录中,我们可以看到训练数据集中有14张Ben Affleck的照片。我们可以检测每张照片中的人脸,并创建一个包含14张人脸的图,每行有两行,每人七个图像。

下面列出了完整的示例。

# demonstrate face detection on 5 Celebrity Faces Dataset

from os import listdir
from PIL import Image
from numpy import asarray
from matplotlib import pyplot
from mtcnn.mtcnn import MTCNN

# extract a single face from a given photograph

def extract_face(filename, required_size=(160, 160)):
# load image from file
image = Image.open(filename)
# convert to RGB, if needed
image = image.convert(‘RGB’)
# convert to array
pixels = asarray(image)
# create the detector, using default weights
detector = MTCNN()
# detect faces in the image
results = detector.detect_faces(pixels)
# extract the bounding box from the first face
x1, y1, width, height = results[0][‘box’]
# bug fix
x1, y1 = abs(x1), abs(y1)
x2, y2 = x1 + width, y1 + height
# extract the face
face = pixels[y1:y2, x1:x2]
# resize pixels to the model size
image = Image.fromarray(face)
image = image.resize(required_size)
face_array = asarray(image)
return face_array

# specify folder to plot

folder = ‘5-celebrity-faces-dataset/train/ben_afflek/’
i = 1

# enumerate files

for filename in listdir(folder):
# path
path = folder + filename
# get face
face = extract_face(path)
print(i, face.shape)
# plot
pyplot.subplot(2, 7, i)
pyplot.axis(‘off’)
pyplot.imshow(face)
i += 1
pyplot.show()

运行示例需要一些时间,并报告每张已加载照片的进度以及包含面部像素数据的NumPy数组的形状。

1 (160, 160, 3)
2 (160, 160, 3)
3 (160, 160, 3)
4 (160, 160, 3)
5 (160, 160, 3)
6 (160, 160, 3)
7 (160, 160, 3)
8 (160, 160, 3)
9 (160, 160, 3)
10 (160, 160, 3)
11 (160, 160, 3)
12 (160, 160, 3)
13 (160, 160, 3)
14 (160, 160, 3)

将创建一个包含在Ben Affleck目录中检测到的面部的图形。

我们可以看到已正确检测到每个脸部,并且在检测到的脸部中有一系列的照明,肤色和方向。

如何在Keras中使用FaceNet开发人脸识别系统

到目前为止,一切都很好。

接下来,我们可以扩展该示例以遍历给定数据集(例如“ train ”或“ val ”)的每个子目录,提取面部,并准备一个名称为每个检测到的面部的输出标签的数据集。

下面的load_faces()函数会将所有面孔加载到给定目录的列表中,例如“ 5-celebrity-faces-dataset / train / ben_afflek / ”。

load images and extract faces for all images in a directory

def load_faces(directory):
faces = list()
# enumerate files
for filename in listdir(directory):
# path
path = directory + filename
# get face
face = extract_face(path)
# store
faces.append(face)
return faces

我们可以为“ train ”或“ val ”文件夹中的每个子目录调用load_faces()函数。每张脸都有一个标签,即名人的名字,我们可以从目录名称中获取。

下面的load_dataset()函数采用目录名称,例如“ 5-celebrity-faces-dataset / train / ”,并为每个子目录(名人)检测面部,并为每个检测到的面部分配标签。

它将数据集的Xy元素作为NumPy数组返回。

load a dataset that contains one subdir for each class that in turn contains images

def load_dataset(directory):
X, y = list(), list()
# enumerate folders, on per class
for subdir in listdir(directory):
# path
path = directory + subdir + ‘/’
# skip any files that might be in the dir
if not isdir(path):
continue
# load all faces in the subdirectory
faces = load_faces(path)
# create labels
labels = [subdir for _ in range(len(faces))]
# summarize progress
print(‘>loaded %d examples for class: %s’ % (len(faces), subdir))
# store
X.extend(faces)
y.extend(labels)
return asarray(X), asarray(y)

然后,我们可以为“ train”和“ val”文件夹调用此函数以加载所有数据,然后通过savez_compressed()函数将结果保存在单个压缩的NumPy数组文件中。

load train dataset

trainX, trainy = load_dataset(‘5-celebrity-faces-dataset/train/’)
print(trainX.shape, trainy.shape)

load test dataset

testX, testy = load_dataset(‘5-celebrity-faces-dataset/val/’)
print(testX.shape, testy.shape)

save arrays to one file in compressed format

savez_compressed(‘5-celebrity-faces-dataset.npz’, trainX, trainy, testX, testy)

综合所有这些,下面列出了检测5张名人面孔数据集中所有面孔的完整示例。

face detection for the 5 Celebrity Faces Dataset

from os import listdir
from os.path import isdir
from PIL import Image
from matplotlib import pyplot
from numpy import savez_compressed
from numpy import asarray
from mtcnn.mtcnn import MTCNN

extract a single face from a given photograph

def extract_face(filename, required_size=(160, 160)):
# load image from file
image = Image.open(filename)
# convert to RGB, if needed
image = image.convert(‘RGB’)
# convert to array
pixels = asarray(image)
# create the detector, using default weights
detector = MTCNN()
# detect faces in the image
results = detector.detect_faces(pixels)
# extract the bounding box from the first face
x1, y1, width, height = results[0][‘box’]
# bug fix
x1, y1 = abs(x1), abs(y1)
x2, y2 = x1 + width, y1 + height
# extract the face
face = pixels[y1:y2, x1:x2]
# resize pixels to the model size
image = Image.fromarray(face)
image = image.resize(required_size)
face_array = asarray(image)
return face_array

load images and extract faces for all images in a directory

def load_faces(directory):
faces = list()
# enumerate files
for filename in listdir(directory):
# path
path = directory + filename
# get face
face = extract_face(path)
# store
faces.append(face)
return faces

load a dataset that contains one subdir for each class that in turn contains images

def load_dataset(directory):
X, y = list(), list()
# enumerate folders, on per class
for subdir in listdir(directory):
# path
path = directory + subdir + ‘/’
# skip any files that might be in the dir
if not isdir(path):
continue
# load all faces in the subdirectory
faces = load_faces(path)
# create labels
labels = [subdir for _ in range(len(faces))]
# summarize progress
print(‘>loaded %d examples for class: %s’ % (len(faces), subdir))
# store
X.extend(faces)
y.extend(labels)
return asarray(X), asarray(y)

load train dataset

trainX, trainy = load_dataset(‘5-celebrity-faces-dataset/train/’)
print(trainX.shape, trainy.shape)

load test dataset

testX, testy = load_dataset(‘5-celebrity-faces-dataset/val/’)

save arrays to one file in compressed format

savez_compressed(‘5-celebrity-faces-dataset.npz’, trainX, trainy, testX, testy)

运行该示例可能需要一些时间。

首先,加载“火车”数据集中的所有照片,然后提取人脸,得到93个带有方脸输入和类标签字符串作为输出的样本。然后加载“ val ”数据集,提供25个可用作测试数据集的样本。

然后将这两个数据集保存到一个名为“ 5-celebrity-faces-dataset.npz ”的压缩NumPy数组文件中,该文件大小约为3兆字节,并存储在当前工作目录中。

>loaded 14 examples for class: ben_afflek
>loaded 19 examples for class: madonna
>loaded 17 examples for class: elton_john
>loaded 22 examples for class: mindy_kaling
>loaded 21 examples for class: jerry_seinfeld
(93, 160, 160, 3) (93,)
>loaded 5 examples for class: ben_afflek
>loaded 5 examples for class: madonna
>loaded 5 examples for class: elton_john
>loaded 5 examples for class: mindy_kaling
>loaded 5 examples for class: jerry_seinfeld
(25, 160, 160, 3) (25,)

该数据集已准备好提供给面部检测模型。

创建面部嵌入

下一步是创建面部嵌入。

人脸嵌入是代表从人脸提取的特征的向量。然后可以将其与为其他人脸生成的向量进行比较。例如,另一个(某种程度上)相近的向量可能是同一个人,而另一个(某种程度上)相距较远的向量可能是不同的人。

我们要开发的分类器模型将以嵌入人脸作为输入并预测人脸的身份。FaceNet模型将针对给定的面部图像生成此嵌入。

FaceNet模型可以用作分类器本身的一部分,或者我们可以使用FaceNet模型对人脸进行预处理以创建人脸嵌入,可以将其存储并用作我们的分类器模型的输入。后一种方法是首选的,因为FaceNet模型既大又慢,无法创建人脸嵌入。

因此,我们可以为火车中所有面孔预先计算面孔嵌入,并在我们的5张名人面孔数据集中测试(正式为“ val ”)设置。

首先,我们可以使用load()NumPy函数加载检测到的面部数据集。

load the face dataset

data = load(‘5-celebrity-faces-dataset.npz’)
trainX, trainy, testX, testy = data[‘arr_0’], data[‘arr_1’], data[‘arr_2’], data[‘arr_3’]
print(‘Loaded: ‘, trainX.shape, trainy.shape, testX.shape, testy.shape)

接下来,我们可以加载FaceNet模型,准备将面部转换为面部嵌入。

load the facenet model

model = load_model(‘facenet_keras.h5’)
print(‘Loaded Model’)

然后,我们可以枚举火车中的每个面孔并测试数据集以预测嵌入。

为了预测嵌入,首先需要适当准备图像的像素值以满足FaceNet模型的期望。FaceNet模型的这种特定实现期望像素值是标准化的。

scale pixel values

face_pixels = face_pixels.astype(‘float32’)

standardize pixel values across channels (global)

mean, std = face_pixels.mean(), face_pixels.std()
face_pixels = (face_pixels – mean) / std

为了对Keras中的一个示例做出预测,我们必须扩展尺寸,以使面部阵列成为一个样本。

transform face into one sample

samples = expand_dims(face_pixels, axis=0)

然后,我们可以使用该模型进行预测并提取嵌入向量。

make prediction to get embedding

yhat = model.predict(samples)

get embedding

embedding = yhat[0]

下面定义的get_embedding()函数实现了这些行为,并且会在给定单个面部图像和已加载的FaceNet模型的情况下返回面部嵌入。

get the face embedding for one face

def get_embedding(model, face_pixels):
# scale pixel values
face_pixels = face_pixels.astype(‘float32’)
# standardize pixel values across channels (global)
mean, std = face_pixels.mean(), face_pixels.std()
face_pixels = (face_pixels – mean) / std
# transform face into one sample
samples = expand_dims(face_pixels, axis=0)
# make prediction to get embedding
yhat = model.predict(samples)
return yhat[0]

综合所有这些,下面列出了将每个面部转换为嵌入在训练和测试数据集中的面部的完整示例。

calculate a face embedding for each face in the dataset using facenet

from numpy import load
from numpy import expand_dims
from numpy import asarray
from numpy import savez_compressed
from keras.models import load_model

get the face embedding for one face

def get_embedding(model, face_pixels):
# scale pixel values
face_pixels = face_pixels.astype(‘float32’)
# standardize pixel values across channels (global)
mean, std = face_pixels.mean(), face_pixels.std()
face_pixels = (face_pixels – mean) / std
# transform face into one sample
samples = expand_dims(face_pixels, axis=0)
# make prediction to get embedding
yhat = model.predict(samples)
return yhat[0]

load the face dataset

data = load(‘5-celebrity-faces-dataset.npz’)
trainX, trainy, testX, testy = data[‘arr_0’], data[‘arr_1’], data[‘arr_2’], data[‘arr_3’]
print(‘Loaded: ‘, trainX.shape, trainy.shape, testX.shape, testy.shape)

load the facenet model

model = load_model(‘facenet_keras.h5’)
print(‘Loaded Model’)

convert each face in the train set to an embedding

newTrainX = list()
for face_pixels in trainX:
embedding = get_embedding(model, face_pixels)
newTrainX.append(embedding)
newTrainX = asarray(newTrainX)
print(newTrainX.shape)

convert each face in the test set to an embedding

newTestX = list()
for face_pixels in testX:
embedding = get_embedding(model, face_pixels)
newTestX.append(embedding)
newTestX = asarray(newTestX)
print(newTestX.shape)

save arrays to one file in compressed format

savez_compressed(‘5-celebrity-faces-embeddings.npz’, newTrainX, trainy, newTestX, testy)

运行示例将报告进度。

我们可以看到人脸数据集已正确加载,模型也已正确加载。然后将火车数据集转换为93个面部嵌入,每个面部嵌入由128个元素向量组成。测试数据集中的25个示例也被适当地转换为面部嵌入。

然后将所得数据集保存到当前工作目录中名为“ 5-celebrity-faces-embeddings.npz ”的压缩NumPy数组中,该数组约为50 KB 。

Loaded: (93, 160, 160, 3) (93,) (25, 160, 160, 3) (25,)
Loaded Model
(93, 128)
(25, 128)

现在,我们准备开发面部分类器系统。

执行人脸分类

在本节中,我们将开发一个模型来将面部嵌入分类为5个名人面部数据集中的已知名人之一。

首先,我们必须加载面部嵌入数据集。

load dataset

data = load(‘5-celebrity-faces-embeddings.npz’)
trainX, trainy, testX, testy = data[‘arr_0’], data[‘arr_1’], data[‘arr_2’], data[‘arr_3’]
print(‘Dataset: train=%d, test=%d’ % (trainX.shape[0], testX.shape[0]))

接下来,在建模之前,数据需要一些小的准备。

首先,规范化人脸嵌入向量是一个好习惯。这是一个好习惯,因为经常使用距离量度将向量相互比较。

在这种情况下,向量归一化意味着缩放这些值,直到向量的长度或大小为1或单位长度为止。这可以通过使用scikit-learn中的Normalizer类来实现。在上一步中创建人脸嵌入时,执行此步骤甚至可能更加方便。

normalize input vectors

in_encoder = Normalizer(norm=’l2′)
trainX = in_encoder.transform(trainX)
testX = in_encoder.transform(testX)

接下来,每个名人姓名的字符串目标变量都需要转换为整数。

这可以通过scikit-learn中的LabelEncoder类来实现。

label encode targets

out_encoder = LabelEncoder()
out_encoder.fit(trainy)
trainy = out_encoder.transform(trainy)
testy = out_encoder.transform(testy)

接下来,我们可以拟合模型。

在使用标准化人脸嵌入输入时,通常使用线性支持向量机(SVM)。这是因为该方法在分离面部嵌入矢量方面非常有效。我们可以使用scikit-learn中的SVC类并将“ kernel ”属性设置为“ linear ”来将线性SVM拟合到训练数据。以后进行预测时,我们可能还需要概率,可以通过将“概率”设置为“”来配置概率

fit model

model = SVC(kernel=’linear’)
model.fit(trainX, trainy)

接下来,我们可以评估模型。

这可以通过使用拟合模型对火车和测试数据集中的每个示例进行预测,然后计算分类精度来实现。

predict

yhat_train = model.predict(trainX)
yhat_test = model.predict(testX)

score

score_train = accuracy_score(trainy, yhat_train)
score_test = accuracy_score(testy, yhat_test)

summarize

print(‘Accuracy: train=%.3f, test=%.3f’ % (score_train100, score_test100))

结合所有这些,下面列出了在5个Celebrity Faces数据集的面部嵌入上拟合线性SVM的完整示例。

develop a classifier for the 5 Celebrity Faces Dataset

from numpy import load
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import Normalizer
from sklearn.svm import SVC

load dataset

data = load(‘5-celebrity-faces-embeddings.npz’)
trainX, trainy, testX, testy = data[‘arr_0’], data[‘arr_1’], data[‘arr_2’], data[‘arr_3’]
print(‘Dataset: train=%d, test=%d’ % (trainX.shape[0], testX.shape[0]))

normalize input vectors

in_encoder = Normalizer(norm=’l2′)
trainX = in_encoder.transform(trainX)
testX = in_encoder.transform(testX)

label encode targets

out_encoder = LabelEncoder()
out_encoder.fit(trainy)
trainy = out_encoder.transform(trainy)
testy = out_encoder.transform(testy)

fit model

model = SVC(kernel=’linear’, probability=True)
model.fit(trainX, trainy)

predict

yhat_train = model.predict(trainX)
yhat_test = model.predict(testX)

score

score_train = accuracy_score(trainy, yhat_train)
score_test = accuracy_score(testy, yhat_test)

summarize

print(‘Accuracy: train=%.3f, test=%.3f’ % (score_train100, score_test100))

首先运行示例,确认训练和测试数据集中的样本数量与我们预期的一样

接下来,在训练和测试数据集上对模型进行评估,显示出完美的分类准确性。考虑到数据集的大小以及所使用的面部检测和面部识别模型的强大功能,这不足为奇。

Dataset: train=93, test=25
Accuracy: train=100.000, test=100.000

通过绘制原始人脸和预测,我们可以使其变得更加有趣。

首先,我们需要加载面部数据集,特别是测试数据集中的面部。我们还可以加载原始照片,使其更加有趣。

load faces

data = load(‘5-celebrity-faces-dataset.npz’)
testX_faces = data[‘arr_2’]

在我们拟合模型之前,其余示例都是相同的。

首先,我们需要从测试集中选择一个随机示例,然后获取嵌入,面部像素,预期类别预测以及类别的相应名称。

test model on a random example from the test dataset

selection = choice([i for i in range(testX.shape[0])])
random_face_pixels = testX_faces[selection]
random_face_emb = testX[selection]
random_face_class = testy[selection]
random_face_name = out_encoder.inverse_transform([random_face_class])

接下来,我们可以将脸部嵌入用作输入,以使用拟合模型进行单个预测。

我们可以预测类整数和预测的概率。

prediction for the face

samples = expand_dims(random_face_emb, axis=0)
yhat_class = model.predict(samples)
yhat_prob = model.predict_proba(samples)

然后,我们可以获得预测的类整数的名称以及该预测的概率。

get name

class_index = yhat_class[0]
class_probability = yhat_prob[0,class_index] * 100
predict_names = out_encoder.inverse_transform(yhat_class)

然后,我们可以打印此信息。

print(‘Predicted: %s (%.3f)’ % (predict_names[0], class_probability))
print(‘Expected: %s’ % random_face_name[0])

我们还可以绘制面部像素以及预测的名称和概率。

plot for fun

pyplot.imshow(random_face_pixels)
title = ‘%s (%.3f)’ % (predict_names[0], class_probability)
pyplot.title(title)
pyplot.show()

综合所有这些,下面列出了用于预测测试数据集中给定看不见的照片的身份的完整示例。

develop a classifier for the 5 Celebrity Faces Dataset

from random import choice
from numpy import load
from numpy import expand_dims
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import Normalizer
from sklearn.svm import SVC
from matplotlib import pyplot

load faces

data = load(‘5-celebrity-faces-dataset.npz’)
testX_faces = data[‘arr_2’]

load face embeddings

data = load(‘5-celebrity-faces-embeddings.npz’)
trainX, trainy, testX, testy = data[‘arr_0’], data[‘arr_1’], data[‘arr_2’], data[‘arr_3’]

normalize input vectors

in_encoder = Normalizer(norm=’l2′)
trainX = in_encoder.transform(trainX)
testX = in_encoder.transform(testX)

label encode targets

out_encoder = LabelEncoder()
out_encoder.fit(trainy)
trainy = out_encoder.transform(trainy)
testy = out_encoder.transform(testy)

fit model

model = SVC(kernel=’linear’, probability=True)
model.fit(trainX, trainy)

test model on a random example from the test dataset

selection = choice([i for i in range(testX.shape[0])])
random_face_pixels = testX_faces[selection]
random_face_emb = testX[selection]
random_face_class = testy[selection]
random_face_name = out_encoder.inverse_transform([random_face_class])

prediction for the face

samples = expand_dims(random_face_emb, axis=0)
yhat_class = model.predict(samples)
yhat_prob = model.predict_proba(samples)

get name

class_index = yhat_class[0]
class_probability = yhat_prob[0,class_index] * 100
predict_names = out_encoder.inverse_transform(yhat_class)
print(‘Predicted: %s (%.3f)’ % (predict_names[0], class_probability))
print(‘Expected: %s’ % random_face_name[0])

plot for fun

pyplot.imshow(random_face_pixels)
title = ‘%s (%.3f)’ % (predict_names[0], class_probability)
pyplot.title(title)
pyplot.show()

每次运行代码时,都会从测试数据集中选择一个不同的随机示例。

注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑运行该示例几次并比较平均结果。

在这种情况下,将选择杰瑞·塞恩菲尔德(Jerry Seinfeld)的照片并正确预测。

Predicted: jerry_seinfeld (88.476)
Expected: jerry_seinfeld

还创建所选面部的图,在图像标题中显示预测的名称和概率。

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站不拥有所有权,不承担相关法律责任。如发现有侵权/违规的内容, 联系QQ1841324605,本站将立刻清除。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

联系我们

服务热线:130-0886-1890

QR code