65.9K
CodeProject 正在变化。 阅读更多。
Home

使用预训练模型进行 AI 人脸识别

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2020年8月6日

CPOL

4分钟阅读

viewsIcon

19920

downloadIcon

435

在本文中,我们将改编 VGG16 模型。

引言

如果你看过电影少数派报告,你可能还记得汤姆·克鲁斯走进 Gap 商店的场景。 视网膜扫描仪读取了他的眼睛,并为他播放了一条定制广告。 好吧,现在是 2020 年。 我们不需要视网膜扫描仪,因为我们有人工智能 (AI) 和机器学习 (ML)!

在本系列中,我们将向您展示如何使用深度学习来执行面部识别,然后 – 基于识别的面部 – 使用神经网络文本转语音 (TTS) 引擎来播放定制广告。 欢迎您在这里浏览 CodeProject 上的代码,或下载 .zip 文件在您自己的机器上浏览代码。

我们假设你熟悉 AI/ML 的基本概念,并且能够使用 Python。

为什么要使用别人的 CNN?

到目前为止,我们已经完成了设计、实现和训练我们自己的用于面部识别的 CNN 所需的一切。 在本文中,我们将研究一种替代方法 – 使用预训练的 VGG (牛津视觉几何组) 模型之一。 这些 CNN 已经针对大型数据集进行了设计和训练,并取得了出色的结果。

我们为什么要重用其他人为他们的数据集(显然与我们的数据集不同)设计和训练的 CNN? 嗯,主要原因是有人花费了大量的 CPU/GPU 时间在巨大的数据集上训练这些模型。 我们可以很好地利用这种训练。 在另一个模型中重用已经训练好的 CNN 的想法被称为“迁移学习”。

一些著名的 VGG 模型包括 VGG16、VGG19、ResNet50、InceptionV3 和 Xception。 它们具有不同的架构,并且都可以在 Keras 中使用。 这些模型中的每一个都经过了 ImageNet 数据集的训练,该数据集包含大约 120 万张图像。

在本文中,我们将改编VGG16 模型

VGG16 架构图显示,此 CNN 的输入定义为 (224, 224, 3)。 因此,如果我们要使此 CNN 适应我们的问题,则有两种选择。 我们可以将图像裁剪并调整大小为 224 x 224。 或者,我们可以将 VGG16 的输入层更改为 (我们的_图像_宽度我们的_图像_高度,3) (用于彩色图像 (RGB)) 或 (我们的_图像_宽度我们的_图像_高度,1) (用于灰度图像)。

请注意,VGG16 的输出层包含 1,000 个类。 由于我们的问题没有那么多可能的类,因此我们必须更改输出层的形状。

实现 VGG16

我们将使用 VGG16 作为基础模型,并从中派生一个新的 CNN – VGGNet。 这个新的 CNN 将具有 VGG16 的层和权重,并在输入层(以使其适应我们的图像宽度、高度和配色方案)以及输出层(以使其适应我们的类数)中进行一些修改。

为了实现我们的自定义 VGGNet 模型,让我们创建一个从 MLModel 继承的类,就像我们在本系列的前一篇文章中所做的那样。 在这个名为 VggModel 的类中,除了 init_model() 之外的所有方法都将具有与我们的 ConvolutionalModel 类中相同的实现。 这就是代码的样子

def init_model(self):
           base_model = VGG16(weights=constant.IMAGENET, include_top=False,
                  input_tensor=Input(shape=(constant.IMG_WIDTH,
                  constant.IMG_HEIGHT, 3)), pooling='max', classes=15)   

base_model.summary()

for layer in base_model.layers:
          layer.trainable = False

x = base_model.get_layer('block5_pool').output
# Stacking a new simple convolutional network on top of it
x = Convolution2D(64, 3)(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Flatten()(x)
x = Dense(constant.NUMBER_FULLY_CONNECTED, activation=constant.RELU_ACTIVATION_FUNCTION)(x)
x = Dense(self.n_classes, activation=constant.SOFTMAX_ACTIVATION_FUNCTION)(x)

self.vgg = Model(inputs=base_model.input, outputs=x)
self.vgg.summary()

请注意,我们在 CNN 的末尾添加了以下层:Flatten、Dense、MaxPooling 和 Dense。“迷你 CNN”的目的,我们已将其附加到 VGG 的末尾,是为了连接其 block5_pool 并使其适合我们的问题,其中包含正确的类数。

此外,我们将添加的层的 layer.trainable 属性设置为 False。 这使我们可以在额外的训练中保留原始模型的权重,我们必须进行这些训练以拟合新层。 您可以通过调用 self.vgg.summary() 获取修改后模型的完整描述。

我们在该类的构造函数中使用以下 lossoptimizer 函数

def __init__(self, dataSet=None):
   super().__init__(dataSet)
   opt = keras.optimizers.Adam(learning_rate=0.001)
   self.vgg.compile(loss=keras.losses.binary_crossentropy,
                    optimizer=opt,
                    metrics=[constant.METRIC_ACCURACY])

应用于耶鲁数据集

现在让我们将 VGGNet 模型应用于我们的耶鲁人脸数据集。 哇:我们仅在三个 epoch 中就实现了超过 93% 的准确率!

只是提醒您:我们从头开始开发的 CNN 在 50 个 epoch 后给我们的准确率约为 85%。 因此,使用预训练的模型大大提高了算法的收敛速度。

下一步?

好了,就这样:我们完成了人脸识别部分。 本系列的最后一篇文章将重点介绍使用深度学习进行文本转语音。 我们将应用 TTS 来选择要播放给刚刚识别出面部的人的消息。 敬请期待!

© . All rights reserved.