Keras 教程:什么是 Keras?如何安装 Python [例子]

什么是 Keras?

Keras 是一个用以下语言编写的开源神经网络库 Python 运行在 Theano 或 Tensorflow 之上。它被设计为模块化、快速且易于使用。它由 Google 工程师 François Chollet 开发。Keras 不处理低级计算。相反,它使用另一个库来执行此操作,称为“后端”。

Keras 是低级 API 的高级 API 包装器,能够在 TensorFlow、CNTK 或 Theano 之上运行。Keras 高级 API 处理我们制作模型的方式,定义层,或设置多个输入输出模型。在这个级别,Keras 还使用损失和优化器函数编译我们的模型,使用拟合函数进行训练过程。Keras 在 Python 不处理低级 API,例如制作计算图、制作张量或其他变量,因为它已由“后端”引擎处理。

什么是后端?

后端是 Keras 中的一个术语,它在 Tensorflow 或 Theano 等其他库的帮助下执行所有低级计算,例如张量积、卷积和许多其他计算。因此,“后端引擎”将执行模型的计算和开发。 Tensorflow 是默认的“后端引擎”,但我们可以在配置中更改它。

Theano、Tensorflow 和 CNTK 后端

Theano 后端

Theano 是一个开源项目,由加拿大魁北克省蒙特利尔大学的 MILA 小组开发。它是第一个被广泛使用的框架。它是一个 Python 库可帮助使用 Numpy 或 Scipy 进行多维数组的数学运算。Theano 可以使用 GPU 进行更快的计算,还可以自动构建符号图来计算梯度。Theano 在其网站上声称它可以识别数值不稳定的表达式并使用更稳定的算法来计算它们,这对我们的不稳定表达式非常有用。

TensorFlow 后端

另一方面,Tensorflow是深度学习框架的后起之秀。它由谷歌大脑团队开发,是最受欢迎的深度学习工具。凭借许多功能,研究人员致力于帮助开发这个用于深度学习目的的框架。

CNTK后端

Keras 的另一个后端引擎是 Microsoft 认知工具包或 CNTK。它是一个开源深度学习框架,由 Microsoft 团队。它可以在多个 GPU 或多台机器上运行,以大规模训练深度学习模型。在某些情况下,据报道 CNTK 比其他框架(如 Tensorflow 或 Theano)更快。接下来在本 Keras CNN 教程中,我们将比较 Theano、TensorFlow 和 CNTK 的后端。

比较后端

我们需要做一个基准测试来了解这两个后端之间的比较。正如你所看到的 李正润的基准,比较了 3 个不同后端在不同硬件上的性能。据报道,结果是 Theano 比其他后端慢 50倍 速度较慢,但​​准确率接近。

另一个 基准测试 由执行 贾斯梅特·巴蒂亚。他报告说,在某些测试中,Theano 比 Tensorflow 慢。但对于每个测试的网络来说,总体准确度几乎是相同的。

因此,在 Theano、Tensorflow 和 CTK 之间,很明显 TensorFlow 优于 Theano。使用 TensorFlow,计算时间要短得多,并且 CNN 比其他方法更好。

接下来是这个 Keras Python 教程中,我们将了解 Keras 和 TensorFlow 之间的区别(Keras 与 Tensorflow).

Keras 与 Tensorflow

参数 Keras Tensorflow
类型 高级 API 包装器 低级API
复杂 易于使用,如果你 Python language 您需要学习使用一些 Tensorflow 函数的语法
目的 快速部署,用标准层制作模型 允许您制作任意计算图或模型层
工具 使用其他 API 调试工具,例如 TFDBG 您可以使用 Tensorboard 可视化工具
社群 大型活跃社区 庞大活跃的社区和广泛共享的资源

Keras 的优点

快速部署且易于理解

Keras 制作网络模型非常快。如果你想用几行代码制作一个简单的网络模型, Python Keras 可以帮你实现这一点。请看下面的 Keras 示例:

from keras.models import Sequential
from keras.layers import Dense, Activation

model = Sequential()
model.add(Dense(64, activation='relu', input_dim=50)) #input shape of 50
model.add(Dense(28, activation='relu')) #input shape of 50
model.add(Dense(10, activation='softmax'))

由于API友好,我们可以很容易地理解该过程。用简单的函数编写代码,无需设置多个参数。

大型社区支持

有许多人工智能社区使用 Keras 作为深度学习框架。他们中的许多人向公众发布他们的代码和教程。

有多个后端

您可以选择 Tensorflow、CNTK 和 Theano 作为 Keras 的后端。您可以根据需要为不同的项目选择不同的后端。每个后端都有自己独特的优势。

跨平台、轻松模型部署

借助各种受支持的设备和平台,您可以在任何设备上部署 Keras,例如

  • iOS 与 CoreML
  • Android 使用 Tensorflow Android,
  • 支持 .js 的 Web 浏览器
  • 云引擎
  • Raspberry Pi的

多 GPU 支持

您可以在单个 GPU 上训练 Keras,也可以同时使用多个 GPU。因为 Keras 具有对数据并行性的内置支持,因此它可以处理大量数据并加快训练所需的时间。

Keras 的缺点

无法处理低级 API

Keras 仅处理在其他框架或后端引擎(例如 Tensorflow、Theano 或 CNTK)上运行的高级 API。因此,如果您想出于研究目的创建自己的抽象层,那么它不是很有用,因为 Keras 已经有预配置的层。

安装 Keras

在本节中,我们将研究可用于安装 Keras 的各种方法

直接安装或虚拟环境

哪一个更好?直接安装到当前的python还是使用虚拟环境?如果您有很多项目,我建议使用虚拟环境。想知道为什么吗?这是因为不同的项目可能使用不同版本的 keras 库。

例如我有一个项目需要 Python 3.5 使用 OpenCV 3.3 和较旧的 Keras-Theano 后端,但在另一个项目中,我必须使用最新版本的 Keras 和 Tensorflow 作为后端 Python 3.6.6支持

我们不希望 Keras 库相互冲突,对吧?因此,我们使用虚拟环境来本地化具有特定类型库的项目,或者我们可以使用其他平台(如云服务)为我们进行计算,例如 Amazon 网络服务。

安装 Keras Amazon 网络服务 (AWS)

Amazon Web 服务是一个为研究人员或任何其他目的提供云计算服务和产品的平台。AWS 出租他们的硬件、网络、数据库等,以便我们可以直接从互联网上使用。用于深度学习的流行 AWS 服务之一是 Amazon 机器图像深度学习服务或 DL

有关如何使用 AWS 的详细说明,请参阅此 教程

关于 AMI 的注意事项:您将拥有以下可用 AMI

在 AWS 上安装 Keras

AWS Deep Learning AMI 是 AWS EC2 服务中的虚拟环境,可帮助研究人员或从业人员使用深度学习。 DLAMI 提供从小型 CPU 引擎到带有预配置 CUDA、cuDNN 的高性能多 GPU 引擎,并附带各种深度学习框架。

如果您想立即使用它,您应该选择 Deep Learning AMI,因为它预装了流行的深度学习框架。

但如果您想尝试使用自定义深度学习框架进行研究,则应安装 Deep Learning Base AMI,因为它附带基础库,例如 CUDA、cuDNN、GPU 驱动程序以及在您的深度学习环境中运行所需的其他库。

如何在 Amazon SageMaker

Amazon SageMaker 是一个深度学习平台,帮助您使用最佳算法训练和部署深度学习网络。

对于初学者来说,这是迄今为止使用 Keras 最简单的方法。下面是如何在 Amazon SageMaker:

步骤 1) 打开 Amazon SageMaker

第一步,打开 Amazon Sagemaker 控制台并单击创建笔记本实例。

安装 Keras Amazon SageMaker

步骤 2) 输入详细信息

  1. 输入您的笔记本名称。
  2. 创建 IAM 角色。它将创建一个 AMI 角色 Amazon IAM 角色格式为 AmazonSageMaker-Executionrole-YYYYMMDD|HHmmSS。
  3. 最后,选择创建笔记本实例。片刻之后, Amazon Sagemaker 启动笔记本实例。

安装 Keras Amazon SageMaker

备注:如果您想访问VPC内的资源,请将直接公网访问设置为启用。否则,该笔记本实例将无法访问互联网,因此无法训练或托管模型

步骤3)启动实例

单击“打开”以启动实例

安装 Keras Amazon SageMaker

步骤 4) 开始编码

In Jupyter单击新建 > conda_tensorflow_p36,即可开始编码

安装 Keras Amazon SageMaker

在 Linux 中安装 Keras

为了启用 Keras 以 Tensorflow 作为后端引擎,我们需要首先安装 Tensorflow。运行此命令以安装带CPU的tensorflow(无GPU)

pip install --upgrade tensorflow

如果你想启用GPU对tensorflow的支持,你可以使用这个命令

pip install --upgrade tensorflow-gpu

在 Linux 上安装 Keras

让我们来看看 Python 通过输入以下内容来查看安装是否成功

user@user:~$ python
Python 3.6.4 (default, Mar 20 2018, 11:10:20) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow
>>>

如果没有错误信息,则安装过程成功

安装 Keras

安装完Tensorflow后,我们开始安装keras。在终端中输入此命令

pip install keras

它将开始安装 Keras 及其所有依赖项。您应该看到类似这样的内容:

安装 Keras

现在我们的系统中已经安装了 Keras!

验证

在开始使用 Keras 之前,我们应该通过打开配置文件来检查我们的 Keras 是否使用 Tensorflow 作为后端:

gedit ~/.keras/keras.json

你应该看到这样的东西

{
    "floatx": "float32",
    "epsilon": 1e-07,
    "backend": "tensorflow",
    "image_data_format": "channels_last"
}

正如你所看到的,“后端”使用tensorflow。这意味着 keras 正如我们预期的那样使用 Tensorflow 作为后端

现在通过输入在终端上运行它

user@user:~$ python3
Python 3.6.4 (default, Mar 20 2018, 11:10:20) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import keras
Using TensorFlow backend.
>>> 

如何在 Windows

在我们安装之前 Tensorflow 和 Keras,我们应该安装 Python、pip 和 virtualenv。如果您已经安装了这些库,则应继续下一步,否则请执行以下操作:

安装 Python 3 从此处下载 链接

通过运行安装 pip Free Introduction

使用此命令安装 virtualenv

pip3 install –U pip virtualenv

安装 Microsoft 视觉 C++ 2015 可再发行更新 3

然后运行这个脚本

pip3 install virtualenv

设置虚拟环境

用于隔离工作系统与主系统。

virtualenv –-system-site-packages –p python3 ./venv

激活环境

.\venv\Scripts\activate

准备好环境后,Tensorflow和Keras的安装与Linux相同。接下来,在 Keras 深度学习教程中,我们将了解深度学习的 Keras 基础知识。

Keras 深度学习基础知识

Keras 中的主要结构是模型,它定义了网络的完整图。您可以向现有模型添加更多层,以构建项目所需的自定义模型。

以下是如何制作序列模型和深度学习中的一些常用层

1. 顺序模型

from keras.models import Sequential
from keras.layers import Dense, Activation,Conv2D,MaxPooling2D,Flatten,Dropout

model = Sequential()

2. 卷积层

这是一个 Keras Python 以卷积层为输入层的示例,输入形状为 320x320x3,具有 48 个大小为 3×3 的过滤器,并使用 ReLU 作为激活函数。

input_shape=(320,320,3) #this is the input shape of an image 320x320x3
model.add(Conv2D(48, (3, 3), activation='relu', input_shape= input_shape))

另一种类型是

model.add(Conv2D(48, (3, 3), activation='relu'))

3.最大Poolin层

要对输入表示进行下采样,请使用 MaxPool2d 并指定内核大小

model.add(MaxPooling2D(pool_size=(2, 2)))

4. 致密层

只需指定输出大小即可添加全连接层

model.add(Dense(256, activation='relu'))

5. Dropout层

以 50% 的概率添加 dropout 层

model.add(Dropout(0.5))

编译、训练和评估

定义模型后,让我们开始训练它们。需要首先使用损失函数和优化器函数来编译网络。这将允许网络改变权重并最小化损失。

model.compile(loss='mean_squared_error', optimizer='adam')

现在开始训练,使用 fit 将训练和验证数据输入模型。这将允许您批量训练网络并设置纪元。

model.fit(X_train, X_train, batch_size=32, epochs=10, validation_data=(x_val, y_val))

我们的最后一步是使用测试数据评估模型。

score = model.evaluate(x_test, y_test, batch_size=32)

让我们尝试使用简单的线性回归

import keras
from keras.models import Sequential
from keras.layers import Dense, Activation
import numpy as np
import matplotlib.pyplot as plt 
 
x = data = np.linspace(1,2,200)
y = x*4 + np.random.randn(*x.shape) * 0.3


model = Sequential()
model.add(Dense(1, input_dim=1, activation='linear'))

model.compile(optimizer='sgd', loss='mse', metrics=['mse'])

weights = model.layers[0].get_weights()
w_init = weights[0][0][0]
b_init = weights[1][0]
print('Linear regression model is initialized with weights w: %.2f, b: %.2f' % (w_init, b_init)) 


model.fit(x,y, batch_size=1, epochs=30, shuffle=False)

weights = model.layers[0].get_weights()
w_final = weights[0][0][0]
b_final = weights[1][0]
print('Linear regression model is trained to have weight w: %.2f, b: %.2f' % (w_final, b_final))

predict = model.predict(data)

plt.plot(data, predict, 'b', data , y, 'k.')
plt.show()

训练数据后,输出应如下所示

线性回归

与初始重量

Linear regression model is initialized with weights w: 0.37, b: 0.00

和最终重量

Linear regression model is trained to have weight w: 3.70, b: 0.61

在 Keras 中微调预训练模型以及如何使用它们

为什么我们使用微调模型以及何时使用它

微调是调整预训练模型以使参数适应新模型的任务。当我们想要从头开始训练一个新模型时,我们需要大量数据,以便网络可以找到所有参数。但在这种情况下,我们将使用预先训练的模型,因此参数已经学习并具有权重。

例如,如果我们想训练自己的 Keras 模型来解决分类问题,但我们只有少量数据,那么我们可以使用 转移学习 + 微调方法。

使用预先训练的网络和权重,我们不需要训练整个网络。我们只需要训练用于解决任务的最后一层,我们称之为微调方法。

网络模型准备

对于预训练模型,我们可以加载 Keras 库中已有的各种模型,例如:

  • VGG16
  • 盗版V3
  • RESNET
  • 移动网
  • Xception
  • InceptionResNetV2

但在此过程中,我们将使用 VGG16 网络模型和 imageNet 作为模型的权重。我们将微调网络,以使用来自的图像对 8 种不同类型的类进行分类 Kaggle 自然图像数据集

VGG16模型架构

VGG16模型架构

资源

将我们的数据上传到AWS S3存储桶

对于我们的训练过程,我们将使用来自 8 个不同类别的自然图像,例如飞机、汽车、猫、狗、花、水果、摩托车和人。首先,我们需要将数据上传到 Amazon S3 存储桶。

Amazon S3水桶

步骤1) 登录到您的S3帐户后,让我们通过时钟创建一个存储桶 创建存储桶

将数据上传到AWS S3存储桶

步骤2) 现在根据您的帐户选择存储桶名称和您的区域。确保存储桶名称可用。之后点击 创建。

将数据上传到AWS S3存储桶

步骤3) 如您所见,您的 Bucket 已可供使用。但正如您所看到的,访问权限不是公开的,如果您想将其保密,这对您有好处。您可以在存储桶属性中将此存储桶更改为公共访问

将数据上传到AWS S3存储桶

步骤4) 现在您开始将训练数据上传到您的存储桶。在这里我将上传 tar.gz 文件,其中包含用于训练和测试过程的图片。

将数据上传到AWS S3存储桶

步骤5) 现在单击您的文件并复制 链接 以便我们可以下载它。

将数据上传到AWS S3存储桶

资料准备

我们需要使用 Keras ImageData 生成训练数据Generator.

首先,您必须使用 wget 下载 S3 Bucket 中的文件链接。

!wget https://s3.us-east-2.amazonaws.com/naturalimages02/images.tar.gz		
!tar -xzf images.tar.gz

下载数据后,让我们开始训练过程。

from keras.preprocessing.image import ImageDataGenerator
import numpy as np
import matplotlib.pyplot as plt

train_path = 'images/train/'
test_path = 'images/test/'
batch_size = 16
image_size = 224
num_class = 8


train_datagen = ImageDataGenerator(validation_split=0.3,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   horizontal_flip=True)

train_generator = train_datagen.flow_from_directory(
                        directory=train_path,
                        target_size=(image_size,image_size),
                        batch_size=batch_size,
                        class_mode='categorical',
                        color_mode='rgb',
                        shuffle=True)

图像数据Generator 将从目录中生成 X_training 数据。该目录中的子目录将用作每个对象的类。图像将以 RGB 颜色模式加载,Y_training 数据将以分类类模式加载,批处理大小为 16。最后,对数据进行混洗。

让我们通过使用 matplotlib 绘制图像来随机查看图像

x_batch, y_batch = train_generator.next()

fig=plt.figure()
columns = 4
rows = 4
for i in range(1, columns*rows):
    num = np.random.randint(batch_size)
    image = x_batch[num].astype(np.int)
    fig.add_subplot(rows, columns, i)
    plt.imshow(image)
plt.show()

资料准备

之后,让我们使用 imageNet 预训练权重从 VGG16 创建网络模型。我们将冻结这些层,使这些层不可训练,以帮助我们减少计算时间。

从 VGG16 创建我们的模型

import keras
from keras.models import Model, load_model
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.preprocessing.image import ImageDataGenerator
from keras.applications.vgg16 import VGG16


#Load the VGG model
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))

print(base_model.summary())

    # Freeze the layers 
for layer in base_model.layers:
    layer.trainable = False
 
# # Create the model
model = keras.models.Sequential()

# # Add the vgg convolutional base model
model.add(base_model)
 
# # Add new layers
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dense(1024, activation='relu'))
model.add(Dense(num_class, activation='softmax'))
 
# # Show a summary of the model. Check the number of trainable parameters    
print(model.summary())

如下所示,我们的网络模型的摘要。然后,我们根据 VGG16 层的输入添加 2 个全连接层(将提取 1024 个特征)和一个输出层(将使用 softmax 激活计算 8 个类别)。

Layer (type)                 Output Shape              Param #   
=================================================================
vgg16 (Model)                (None, 7, 7, 512)         14714688  
_________________________________________________________________
flatten_1 (Flatten)          (None, 25088)             0         
_________________________________________________________________
dense_1 (Dense)              (None, 1024)              25691136  
_________________________________________________________________
dense_2 (Dense)              (None, 1024)              1049600   
_________________________________________________________________
dense_3 (Dense)              (None, 8)                 8200      
=================================================================
Total params: 41,463,624
Trainable params: 26,748,936
Non-trainable params: 14,714,688

培训

# # Compile the model
from keras.optimizers import SGD

model.compile(loss='categorical_crossentropy',
          optimizer=SGD(lr=1e-3),
          metrics=['accuracy'])

# # Start the training process
# model.fit(x_train, y_train, validation_split=0.30, batch_size=32, epochs=50, verbose=2)

# # #save the model
# model.save('catdog.h5')

history = model.fit_generator(
        train_generator,
        steps_per_epoch=train_generator.n/batch_size,
        epochs=10)
        
model.save('fine_tune.h5')

# summarize history for accuracy
import matplotlib.pyplot as plt

plt.plot(history.history['loss'])
plt.title('loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['loss'], loc='upper left')
plt.show()

成果

Epoch 1/10
432/431 [==============================] - 53s 123ms/step - loss: 0.5524 - acc: 0.9474 
Epoch 2/10
432/431 [==============================] - 52s 119ms/step - loss: 0.1571 - acc: 0.9831
Epoch 3/10
432/431 [==============================] - 51s 119ms/step - loss: 0.1087 - acc: 0.9871
Epoch 4/10
432/431 [==============================] - 51s 119ms/step - loss: 0.0624 - acc: 0.9926
Epoch 5/10
432/431 [==============================] - 51s 119ms/step - loss: 0.0591 - acc: 0.9938
Epoch 6/10
432/431 [==============================] - 51s 119ms/step - loss: 0.0498 - acc: 0.9936
Epoch 7/10
432/431 [==============================] - 51s 119ms/step - loss: 0.0403 - acc: 0.9958
Epoch 8/10
432/431 [==============================] - 51s 119ms/step - loss: 0.0248 - acc: 0.9959
Epoch 9/10
432/431 [==============================] - 51s 119ms/step - loss: 0.0466 - acc: 0.9942
Epoch 10/10
432/431 [==============================] - 52s 120ms/step - loss: 0.0338 - acc: 0.9947

培训

正如你所看到的,我们的损失显着下降,并且准确率几乎是 100%。为了测试我们的模型,我们通过互联网随机挑选图像并将其放在具有不同类别的测试文件夹中进行测试

测试我们的模型

model = load_model('fine_tune.h5')

test_datagen = ImageDataGenerator()
train_generator = train_datagen.flow_from_directory(
                        directory=train_path,
                        target_size=(image_size,image_size),
                        batch_size=batch_size,
                        class_mode='categorical',
                        color_mode='rgb',
                        shuffle=True)

test_generator = test_datagen.flow_from_directory(
                        directory=test_path, 
                        target_size=(image_size, image_size),
                        color_mode='rgb',
                        shuffle=False,
                        class_mode='categorical',
                        batch_size=1)

filenames = test_generator.filenames
nb_samples = len(filenames)

fig=plt.figure()
columns = 4
rows = 4
for i in range(1, columns*rows -1):
    x_batch, y_batch = test_generator.next()

    name = model.predict(x_batch)
    name = np.argmax(name, axis=-1)
    true_name = y_batch
    true_name = np.argmax(true_name, axis=-1)

    label_map = (test_generator.class_indices)
    label_map = dict((v,k) for k,v in label_map.items()) #flip k,v
    predictions = [label_map[k] for k in name]
    true_value = [label_map[k] for k in true_name]

    image = x_batch[0].astype(np.int)
    fig.add_subplot(rows, columns, i)
    plt.title(str(predictions[0]) + ':' + str(true_value[0]))
    plt.imshow(image)
plt.show()

我们的测试如下!在 1 张图像的测试中,只有 14 张图像预测错误!

测试模型

使用 Keras 进行人脸识别神经网络

为什么我们需要认可

我们需要识别来让我们更容易地识别或识别一个人的脸、物体类型、从一个人的脸上估计年龄,甚至知道这个人的面部表情。

使用 Keras 进行人脸识别神经网络

也许您意识到,每次您尝试在照片中标记朋友的脸部时,Facebook 中的功能都已经为您完成了这一任务,即标记您朋友的脸部,而无需您先进行标记。这是Facebook应用的人脸识别技术,让我们更容易标记朋友。

那么它是怎样工作的?每次我们标记朋友的脸时,Facebook 的人工智能都会学习它并尝试预测它,直到得到正确的结果。我们将使用相同的系统来制作我们自己的面部识别。让我们开始使用深度学习制作我们自己的人脸识别

网络模型

我们将使用 VGG16 网络模型,但具有 VGGFace 权重。

VGG16模型架构

网络模型

什么是 VGGFace?它是 Parkhi、Omkar M. 等人引入的 Deep Face Recognition 的 Keras 实现。 “深度人脸识别。” BMVC(2015)。该框架使用VGG16作为网络架构。

您可以从以下位置下载 VGGFace: github上

from keras.applications.vgg16 import VGG16
from keras_vggface.vggface import VGGFace

face_model = VGGFace(model='vgg16', 
                weights='vggface',
                input_shape=(224,224,3)) 
face_model.summary()

正如你所看到的网络摘要

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 224, 224, 3)       0         
_________________________________________________________________
conv1_1 (Conv2D)             (None, 224, 224, 64)      1792      
_________________________________________________________________
conv1_2 (Conv2D)             (None, 224, 224, 64)      36928     
_________________________________________________________________
pool1 (MaxPooling2D)         (None, 112, 112, 64)      0         
_________________________________________________________________
conv2_1 (Conv2D)             (None, 112, 112, 128)     73856     
_________________________________________________________________
conv2_2 (Conv2D)             (None, 112, 112, 128)     147584    
_________________________________________________________________
pool2 (MaxPooling2D)         (None, 56, 56, 128)       0         
_________________________________________________________________
conv3_1 (Conv2D)             (None, 56, 56, 256)       295168    
_________________________________________________________________
conv3_2 (Conv2D)             (None, 56, 56, 256)       590080    
_________________________________________________________________
conv3_3 (Conv2D)             (None, 56, 56, 256)       590080    
_________________________________________________________________
pool3 (MaxPooling2D)         (None, 28, 28, 256)       0         
_________________________________________________________________
conv4_1 (Conv2D)             (None, 28, 28, 512)       1180160   
_________________________________________________________________
conv4_2 (Conv2D)             (None, 28, 28, 512)       2359808   
_________________________________________________________________
conv4_3 (Conv2D)             (None, 28, 28, 512)       2359808   
_________________________________________________________________
pool4 (MaxPooling2D)         (None, 14, 14, 512)       0         
_________________________________________________________________
conv5_1 (Conv2D)             (None, 14, 14, 512)       2359808   
_________________________________________________________________
conv5_2 (Conv2D)             (None, 14, 14, 512)       2359808   
_________________________________________________________________
conv5_3 (Conv2D)             (None, 14, 14, 512)       2359808   
_________________________________________________________________
pool5 (MaxPooling2D)         (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
fc6 (Dense)                  (None, 4096)              102764544 
_________________________________________________________________
fc6/relu (Activation)        (None, 4096)              0         
_________________________________________________________________
fc7 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
fc7/relu (Activation)        (None, 4096)              0         
_________________________________________________________________
fc8 (Dense)                  (None, 2622)              10742334  
_________________________________________________________________
fc8/softmax (Activation)     (None, 2622)              0         
=================================================================
Total params: 145,002,878
Trainable params: 145,002,878
Non-trainable params: 0
_________________________________________________________________
Traceback (most recent call last):

我们将做一个 转移学习 + 微调,使用小数据集加快训练速度。首先,我们将冻结基础层,使这些层无法训练。

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

然后我们添加自己的层来识别我们的测试面孔。我们将添加 2 个全连接层和一个可检测 5 个人的输出层。

from keras.models import Model, Sequential
from keras.layers import Input, Convolution2D, ZeroPadding2D, MaxPooling2D, Flatten, Dense, Dropout, Activation

person_count = 5

last_layer = face_model.get_layer('pool5').output

x = Flatten(name='flatten')(last_layer)
x = Dense(1024, activation='relu', name='fc6')(x)
x = Dense(1024, activation='relu', name='fc7')(x)
out = Dense(person_count, activation='softmax', name='fc8')(x)

custom_face = Model(face_model.input, out)

让我们看看我们的网络摘要

Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 224, 224, 3)       0
_________________________________________________________________
conv1_1 (Conv2D)             (None, 224, 224, 64)      1792
_________________________________________________________________
conv1_2 (Conv2D)             (None, 224, 224, 64)      36928
_________________________________________________________________
pool1 (MaxPooling2D)         (None, 112, 112, 64)      0
_________________________________________________________________
conv2_1 (Conv2D)             (None, 112, 112, 128)     73856
_________________________________________________________________
conv2_2 (Conv2D)             (None, 112, 112, 128)     147584
_________________________________________________________________
pool2 (MaxPooling2D)         (None, 56, 56, 128)       0
_________________________________________________________________
conv3_1 (Conv2D)             (None, 56, 56, 256)       295168
_________________________________________________________________
conv3_2 (Conv2D)             (None, 56, 56, 256)       590080
_________________________________________________________________
conv3_3 (Conv2D)             (None, 56, 56, 256)       590080
_________________________________________________________________
pool3 (MaxPooling2D)         (None, 28, 28, 256)       0
_________________________________________________________________
conv4_1 (Conv2D)             (None, 28, 28, 512)       1180160
_________________________________________________________________
conv4_2 (Conv2D)             (None, 28, 28, 512)       2359808
_________________________________________________________________
conv4_3 (Conv2D)             (None, 28, 28, 512)       2359808
_________________________________________________________________
pool4 (MaxPooling2D)         (None, 14, 14, 512)       0
_________________________________________________________________
conv5_1 (Conv2D)             (None, 14, 14, 512)       2359808
_________________________________________________________________
conv5_2 (Conv2D)             (None, 14, 14, 512)       2359808
_________________________________________________________________
conv5_3 (Conv2D)             (None, 14, 14, 512)       2359808
_________________________________________________________________
pool5 (MaxPooling2D)         (None, 7, 7, 512)         0
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0
_________________________________________________________________
fc6 (Dense)                  (None, 1024)              25691136
_________________________________________________________________
fc7 (Dense)                  (None, 1024)              1049600
_________________________________________________________________
fc8 (Dense)                  (None, 5)                 5125
=================================================================
Total params: 41,460,549
Trainable params: 26,745,861
Non-trainable params: 14,714,688

正如您在上面看到的,在 pool5 层之后,它将被展平为单个特征向量,该特征向量将由密集层用于最终识别。

准备我们的脸

现在让我们准备好我们的脸。我制作了一个由 5 位名人组成的目录

  • 马云
  • 杰森 - 斯坦森
  • 约翰尼·德普
  • 小罗伯特唐尼
  • 罗温·艾金森

每个文件夹包含 10 张图片,用于每次训练和评估过程。虽然数据量很小,但这就是挑战,对吗?

我们将使用Keras工具的帮助来帮助我们准备数据。该函数将在数据集文件夹中进行迭代,然后准备它以便可以在训练中使用。

from keras.preprocessing.image import ImageDataGenerator
batch_size = 5
train_path = 'data/'
eval_path = 'eval/'

train_datagen = ImageDataGenerator(rescale=1./255,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   horizontal_flip=True)

valid_datagen = ImageDataGenerator(rescale=1./255,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   horizontal_flip=True)

train_generator = train_datagen.flow_from_directory(
                        train_path,
                        target_size=(image_size,image_size),
                        batch_size=batch_size,
                        class_mode='sparse',
                        color_mode='rgb')

valid_generator = valid_datagen.flow_from_directory(
    directory=eval_path,
    target_size=(224, 224),
    color_mode='rgb',
    batch_size=batch_size,
    class_mode='sparse',
    shuffle=True,
)

训练我们的模型

让我们通过使用损失函数和优化器编译网络来开始我们的训练过程。在这里,我们使用稀疏分类交叉熵作为损失函数,并借助 SGD 作为学习优化器。

from keras.optimizers import SGD

custom_face.compile(loss='sparse_categorical_crossentropy',
                         optimizer=SGD(lr=1e-4, momentum=0.9),
                         metrics=['accuracy'])

history = custom_face.fit_generator(
        train_generator,
        validation_data=valid_generator,
        steps_per_epoch=49/batch_size,
        validation_steps=valid_generator.n,
        epochs=50)

custom_face.evaluate_generator(generator=valid_generator)
        
custom_face.save('vgg_face.h5')
Epoch 25/50
10/9 [==============================] - 60s 6s/step - loss: 1.4882 - acc: 0.8998 - val_loss: 1.5659 - val_acc: 0.5851
Epoch 26/50
10/9 [==============================] - 59s 6s/step - loss: 1.4882 - acc: 0.8998 - val_loss: 1.5638 - val_acc: 0.5809
Epoch 27/50
10/9 [==============================] - 60s 6s/step - loss: 1.4779 - acc: 0.8597 - val_loss: 1.5613 - val_acc: 0.5477
Epoch 28/50
10/9 [==============================] - 60s 6s/step - loss: 1.4755 - acc: 0.9199 - val_loss: 1.5576 - val_acc: 0.5809
Epoch 29/50
10/9 [==============================] - 60s 6s/step - loss: 1.4794 - acc: 0.9153 - val_loss: 1.5531 - val_acc: 0.5892
Epoch 30/50
10/9 [==============================] - 60s 6s/step - loss: 1.4714 - acc: 0.8953 - val_loss: 1.5510 - val_acc: 0.6017
Epoch 31/50
10/9 [==============================] - 60s 6s/step - loss: 1.4552 - acc: 0.9199 - val_loss: 1.5509 - val_acc: 0.5809
Epoch 32/50
10/9 [==============================] - 60s 6s/step - loss: 1.4504 - acc: 0.9199 - val_loss: 1.5492 - val_acc: 0.5975
Epoch 33/50
10/9 [==============================] - 60s 6s/step - loss: 1.4497 - acc: 0.8998 - val_loss: 1.5490 - val_acc: 0.5851
Epoch 34/50
10/9 [==============================] - 60s 6s/step - loss: 1.4453 - acc: 0.9399 - val_loss: 1.5529 - val_acc: 0.5643
Epoch 35/50
10/9 [==============================] - 60s 6s/step - loss: 1.4399 - acc: 0.9599 - val_loss: 1.5451 - val_acc: 0.5768
Epoch 36/50
10/9 [==============================] - 60s 6s/step - loss: 1.4373 - acc: 0.8998 - val_loss: 1.5424 - val_acc: 0.5768
Epoch 37/50
10/9 [==============================] - 60s 6s/step - loss: 1.4231 - acc: 0.9199 - val_loss: 1.5389 - val_acc: 0.6183
Epoch 38/50
10/9 [==============================] - 59s 6s/step - loss: 1.4247 - acc: 0.9199 - val_loss: 1.5372 - val_acc: 0.5934
Epoch 39/50
10/9 [==============================] - 60s 6s/step - loss: 1.4153 - acc: 0.9399 - val_loss: 1.5406 - val_acc: 0.5560
Epoch 40/50
10/9 [==============================] - 60s 6s/step - loss: 1.4074 - acc: 0.9800 - val_loss: 1.5327 - val_acc: 0.6224
Epoch 41/50
10/9 [==============================] - 60s 6s/step - loss: 1.4023 - acc: 0.9800 - val_loss: 1.5305 - val_acc: 0.6100
Epoch 42/50
10/9 [==============================] - 59s 6s/step - loss: 1.3938 - acc: 0.9800 - val_loss: 1.5269 - val_acc: 0.5975
Epoch 43/50
10/9 [==============================] - 60s 6s/step - loss: 1.3897 - acc: 0.9599 - val_loss: 1.5234 - val_acc: 0.6432
Epoch 44/50
10/9 [==============================] - 60s 6s/step - loss: 1.3828 - acc: 0.9800 - val_loss: 1.5210 - val_acc: 0.6556
Epoch 45/50
10/9 [==============================] - 59s 6s/step - loss: 1.3848 - acc: 0.9599 - val_loss: 1.5234 - val_acc: 0.5975
Epoch 46/50
10/9 [==============================] - 60s 6s/step - loss: 1.3716 - acc: 0.9800 - val_loss: 1.5216 - val_acc: 0.6432
Epoch 47/50
10/9 [==============================] - 60s 6s/step - loss: 1.3721 - acc: 0.9800 - val_loss: 1.5195 - val_acc: 0.6266
Epoch 48/50
10/9 [==============================] - 60s 6s/step - loss: 1.3622 - acc: 0.9599 - val_loss: 1.5108 - val_acc: 0.6141
Epoch 49/50
10/9 [==============================] - 60s 6s/step - loss: 1.3452 - acc: 0.9399 - val_loss: 1.5140 - val_acc: 0.6432
Epoch 50/50
10/9 [==============================] - 60s 6s/step - loss: 1.3387 - acc: 0.9599 - val_loss: 1.5100 - val_acc: 0.6266

正如您所看到的,我们的验证准确率高达 64%,这对于少量训练数据来说是一个不错的结果。我们可以通过添加更多层或添加更多训练图像来改进这一点,以便我们的模型可以更多地了解面部并获得更高的准确性。

让我们用测试图片来测试我们的模型

测试图片

from keras.models import load_model
from keras.preprocessing.image import load_img, save_img, img_to_array
from keras_vggface.utils import preprocess_input

test_img = image.load_img('test.jpg', target_size=(224, 224))
img_test = image.img_to_array(test_img)
img_test = np.expand_dims(img_test, axis=0)
img_test = utils.preprocess_input(img_test)
predictions = model.predict(img_test)
predicted_class=np.argmax(predictions,axis=1)

labels = (train_generator.class_indices)
labels = dict((v,k) for k,v in labels.items())
predictions = [labels[k] for k in predicted_class]
print(predictions)
['RobertDJr']

使用小罗伯特唐尼的照片作为我们的测试图片,表明预测的脸部是真实的!

使用实时摄像头进行预测!

如果我们通过网络摄像头的输入来测试我们的技能如何?使用 OpenCV 和 Haar Face 级联来找到我们的脸,并在我们的网络模型的帮助下,我们可以识别这个人。

第一步是准备您和您朋友的脸部。我们拥有的数据越多,结果就越好!

像上一步一样准备和训练您的网络,训练完成后,添加此行以从 cam 获取输入图像

#Load trained model
from keras.models import load_model
from keras_vggface import utils
import cv2

image_size = 224
device_id = 0 #camera_device id 

model = load_model('my faces.h5')

#make labels according to your dataset folder 
labels = dict(fisrtname=0,secondname=1) #and so on
print(labels)

cascade_classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
camera = cv2.VideoCapture(device_id)

while camera.isOpened():
    ok, cam_frame = camera.read()
    if not ok:
        break
    
    gray_img=cv2.cvtColor(cam_frame, cv2.COLOR_BGR2GRAY)
    faces= cascade_classifier.detectMultiScale(gray_img, minNeighbors=5)

    for (x,y,w,h) in faces:
        cv2.rectangle(cam_frame,(x,y),(x+w,y+h),(255,255,0),2)
        roi_color = cam_frame [y:y+h, x:x+w]
        roi color = cv2.cvtColor(roi_color, cv2.COLOR_BGR2RGB)
        roi_color = cv2.resize(roi_color, (image_size, image_size))
        image = roi_color.astype(np.float32, copy=False)
        image = np.expand_dims(image, axis=0)
        image = preprocess_input(image, version=1) # or version=2
        preds = model.predict(image)
        predicted_class=np.argmax(preds,axis=1)

        labels = dict((v,k) for k,v in labels.items())
        name = [labels[k] for k in predicted_class]

        cv2.putText(cam_frame,str(name), 
                    (x + 10, y + 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,255), 2)
        
    cv2.imshow('video image', cam_frame)
    key = cv2.waitKey(30)
    if key == 27: # press 'ESC' to quit
        break

camera.release()
cv2.destroyAllWindows()

哪一个更好? Keras 或 Tensorflow

Keras 在编写脚本时提供了简单性。我们可以直接用 Keras 开始编写和理解,因为它并不太难理解。它更加用户友好且易于实现,不需要设置很多变量来运行模型。所以,我们不需要了解后端流程的每一个细节。

另一方面,如果你想要制作任意的计算图或模型,Tensorflow 是提供灵活性和高级操作的低级操作。Tensorflow 还可以借助以下工具可视化该过程 张量板 以及专门的调试工具。

因此,如果您想以不太复杂的方式开始使用深度学习,请使用 Keras。因为 Keras 比 Tensorflow 更简单、用户友好且易于实现。但如果你想在深度学习项目或研究中编写自己的算法,你应该使用 Tensorflow。

总结

因此,让我们总结一下我们在本教程中讨论和完成的所有内容。

  • Keras 是一个高级 API,用于在后端引擎的帮助下使深度学习网络变得更容易。
  • Keras 易于使用和理解,并且支持 Python,因此感觉比以往更加自然。对于想要学习深度学习的初学者和想要易于使用 API 的研究人员来说,它非常有用。
  • 安装过程很简单,您可以使用虚拟环境或使用外部平台,例如 AWS.
  • Keras 还附带了各种类型的网络模型,因此它使我们更容易使用可用的模型来预训练和微调我们自己的网络模型。
  • 此外,还有许多关于使用来自全球社区代码的 Keras 进行深度学习的教程和文章。