Python-深度学习应用指南-全-

Python 深度学习应用指南(全)

原文:Deep Learning with Applications Using Python

协议:CC BY-NC-SA 4.0

一、TensorFlow 基础

本章涵盖深度学习框架 TensorFlow 的基础知识。深度学习在模式识别方面做得非常好,特别是在图像、声音、语音、语言和时序数据的背景下。在深度学习的帮助下,你可以分类、预测、聚类和提取特征。好在 2015 年 11 月,谷歌发布了 TensorFlow,已经在谷歌搜索、垃圾邮件检测、语音识别、谷歌助手、Google Now、Google Photos 等谷歌大部分产品中使用。本章的目的是解释 TensorFlow 的基本组成部分。

TensorFlow 具有执行部分子图计算的独特能力,从而允许在划分神经网络的帮助下进行分布式训练。换句话说,TensorFlow 允许模型并行和数据并行。TensorFlow 提供了多个 API。最低级别的 API—tensor flow Core—为您提供完整的编程控制。

关于 TensorFlow,请注意以下要点:

  • 它的图表是对计算的描述。
  • 它的图有节点是操作。
  • 它在给定的会话上下文中执行计算。
  • 对于任何计算,必须在会话中启动图形。
  • 会话将图形操作放到 CPU 和 GPU 等设备上。
  • 会话提供了执行图形操作的方法。

请前往 https://www.tensorflow.org/install/ 进行安装。

我将讨论以下主题:

A456157_1_En_1_Figa_HTML.jpg

张量

在进入 TensorFlow 库之前,让我们先熟悉一下 TensorFlow 中的基本数据单位。张量是一个数学对象,是标量、向量和矩阵的概括。张量可以表示为多维数组。零阶张量只不过是一个标量。向量/数组是秩为 1 的张量,而矩阵是秩为 2 的张量。简而言之,张量可以认为是一个 n 维数组。

下面是一些张量的例子:

  • 5:这是一个秩为 0 的张量;这是一个形状为[ ]的标量。
  • [2.,5., 3.]:这是一个秩为 1 的张量;这是一个形状为[3]的矢量。
  • [[1., 2., 7.], [3., 5., 4.]]:这是一个秩 2 张量;它是一个形状为[2, 3]的矩阵。
  • [[[1., 2., 3.]], [[7., 8., 9.]]]:这是一个形状为[2, 1, 3]的秩为 3 的张量。

计算图形和会话

TensorFlow 因其 TensorFlow 核心程序而广受欢迎,该程序有两个主要动作。

  • 在构建阶段构建计算图
  • 在执行阶段运行计算图

我们来了解一下 TensorFlow 是如何工作的。

  • 它的程序通常分为构建阶段和执行阶段。
  • 构建阶段组装一个有节点(ops/operations)和边(tensors)的图。
  • 执行阶段使用一个会话来执行图中的操作。
  • 最简单的操作是一个常数,它不接受输入,但将输出传递给其他进行计算的操作。
  • 运算的一个例子是乘法(或加法或减法,将两个矩阵作为输入,并将一个矩阵作为输出)。
  • TensorFlow 库有一个默认图形,ops 构造函数会向其中添加节点。

因此,TensorFlow 程序的结构有两个阶段,如下所示:

A456157_1_En_1_Figb_HTML.jpg

计算图是排列成节点图的一系列 TensorFlow 运算。

让我们看看 TensorFlow 对 Numpy。在 Numpy 中,如果你计划乘两个矩阵,你创建矩阵并乘它们。但是在 TensorFlow 中,你设置了一个图(默认的图,除非你创建另一个图)。接下来,您需要创建变量、占位符和常量值,然后创建会话并初始化变量。最后,将数据输入占位符,以便调用任何操作。

要实际评估节点,您必须在会话中运行计算图。

会话封装了 TensorFlow 运行时的控制和状态。

下面的代码创建了一个Session对象:

sess = tf.Session()

然后,它调用 run 方法运行足够的计算图来计算 node1 和 node2。

计算图定义了计算。它既不计算任何东西,也不保存任何值。它旨在定义代码中提到的操作。将创建一个默认图表。所以,你不需要创建它,除非你想创建多用途的图表。

会话允许您执行图形或部分图形。它为执行分配资源(在一个或多个 CPU 或 GPU 上)。它保存中间结果和变量的实际值。

在 TensorFlow 中创建的变量值仅在一个会话中有效。如果您稍后在第二个会话中尝试查询该值,TensorFlow 将会引发一个错误,因为该变量没有在那里初始化。

要运行任何操作,您需要为该图创建一个会话。会话还将分配内存来存储变量的当前值

下面是演示的代码:

A456157_1_En_1_Figc_HTML.jpg

常量、占位符和变量

TensorFlow 程序使用张量数据结构来表示所有数据,在计算图中的操作之间只传递张量。可以把 TensorFlow 张量想象成一个 n 维数组或列表。张量有静态类型、秩和形状。这里,图形产生一个恒定的结果。变量在图的执行过程中保持状态。

深度学习一般要处理很多图像,所以要为每张图像放置像素值,对所有图像不断迭代。

要训练模型,您需要能够修改图形来调整一些对象,如权重和偏差。简而言之,变量使您能够将可训练参数添加到图形中。它们是用类型和初始值构造的。

让我们在 TensorFlow 中创建一个常量并打印出来。

A456157_1_En_1_Figd_HTML.jpg

下面是对前面代码的简单解释:

  1. 导入tensorflow模块,将其命名为tf
  2. 创建一个常数值(x),并将其赋值为数值 12。
  3. 创建一个用于计算值的会话。
  4. 只运行变量x并打印出其当前值。

前两步属于构建阶段,后两步属于执行阶段。我现在将讨论 TensorFlow 的构建和执行阶段。

您可以用另一种方式重写前面的代码,如下所示:

A456157_1_En_1_Fige_HTML.jpg

现在您将探索如何创建一个变量并初始化它。下面是实现这一点的代码:

A456157_1_En_1_Figf_HTML.jpg

下面是对前面代码的解释:

  1. 导入tensorflow模块,将其命名为tf
  2. 创建一个名为x的常量值,并赋予其数值 12。
  3. 创建一个名为y的变量,并将其定义为等式 12+11。
  4. tf.global_variables_initializer()初始化变量。
  5. 创建一个用于计算值的会话。
  6. 运行步骤 4 中创建的模型。
  7. 只运行变量y并打印出其当前值。

这里有更多的代码供您阅读:

A456157_1_En_1_Figg_HTML.jpg

占位符

占位符是一个变量,您可以在以后向其输入内容。它意味着接受外部输入。占位符可以有一维或多维,用于存储 n 维数组。

A456157_1_En_1_Figh_HTML.jpg

下面是对前面代码的解释:

  1. 导入tensorflow模块,将其命名为tf
  2. 创建一个名为x的占位符,提及float类型。
  3. 创建一个名为y的张量,它是将x乘以 10 再加上 500 的运算。注意,x的任何初始值都没有定义。
  4. 创建一个用于计算值的会话。
  5. 定义feed_dictx的值,以便运行y
  6. 打印出它的值。

在下面的示例中,您创建了一个 2×4 矩阵(2D 数组)来存储一些数字。然后,使用与前面相同的操作,按元素乘以 10 并加 1。占位符的第一个维度是None,这意味着允许任意数量的行。

你也可以考虑用 2D 数组代替 1D 数组。代码如下:

A456157_1_En_1_Figi_HTML.jpg

这是一个 2×4 矩阵。所以,如果用 2 代替None,可以看到同样的输出。

A456157_1_En_1_Figj_HTML.jpg

但是,如果您创建了一个[3, 4]形状的占位符(注意,您将在稍后填充一个 2×4 的矩阵),就会出现错误,如下所示:

A456157_1_En_1_Figk_HTML.jpg

################# What happens in a linear model ##########
# Weight and Bias as Variables as they are to be tuned
W = tf.Variable([2], dtype=tf.float32)
b = tf.Variable([3], dtype=tf.float32)
# Training dataset that will be fed while training as Placeholders

x = tf.placeholder(tf.float32)
# Linear Model
y = W * x + b

常数在你调用tf.constant时被初始化,它们的值永远不能改变。相比之下,当您调用tf.Variable时,变量不会被初始化。要初始化 TensorFlow 程序中的所有变量,必须显式调用一个特殊操作,如下所示。

A456157_1_En_1_Figl_HTML.jpg

重要的是要认识到init是初始化所有全局变量的 TensorFlow 子图的句柄。在调用sess.run之前,变量是未初始化的。

创建张量

图像是三阶张量,其中维度属于高度、宽度和通道数(红色、蓝色和绿色)。

这里你可以看到图像是如何转换成张量的:

A456157_1_En_1_Figo_HTML.jpg

A456157_1_En_1_Fign_HTML.jpg

A456157_1_En_1_Figm_HTML.jpg

您可以生成各种类型的张量,如固定张量、随机张量和顺序张量。

固定张量

这里有一个固定的张量:

A456157_1_En_1_Figq_HTML.jpg

A456157_1_En_1_Figp_HTML.jpg

tf:.fill创建一个具有唯一数字的形状张量(2×3)。

A456157_1_En_1_Figr_HTML.jpg

tf.diag创建一个具有指定对角元素的对角矩阵。

A456157_1_En_1_Figs_HTML.jpg

tf.constant创建一个常量张量。

A456157_1_En_1_Figt_HTML.jpg

序列张量

tf.range创建从指定值开始并具有指定增量的数字序列。

A456157_1_En_1_Figu_HTML.jpg

tf.linspace创建一个等距值序列。

A456157_1_En_1_Figv_HTML.jpg

随机张量

tf.random_uniform从一个范围内的均匀分布中生成随机值。

A456157_1_En_1_Figw_HTML.jpg

tf.random_normal根据具有指定平均值和标准偏差的正态分布生成随机值。

A456157_1_En_1_Figz_HTML.jpg

A456157_1_En_1_Figy_HTML.jpg

A456157_1_En_1_Figx_HTML.jpg

你能猜出结果吗?

A456157_1_En_1_Figab_HTML.jpg

A456157_1_En_1_Figaa_HTML.jpg

如果你找不到结果,请修改之前我讨论张量创建的部分。

您可以在这里看到结果:

A456157_1_En_1_Figac_HTML.jpg

处理矩阵

一旦你习惯了创建张量,你就可以享受处理矩阵的乐趣了(2D 张量)。

A456157_1_En_1_Figae_HTML.jpg

A456157_1_En_1_Figad_HTML.jpg

激活功能

激活函数的想法来自于对人类大脑中神经元如何工作的分析(见图 1-1 )。神经元在超过某个阈值后变得活跃,这个阈值更好地被称为激活电位。在大多数情况下,它还试图将输出放在一个小范围内。

Sigmoid、双曲正切(tanh)、ReLU 和 eLU 是最流行的激活函数。

我们来看看现在比较流行的激活功能。

正切双曲线和 Sigmoid

图 1-2 显示了正切双曲线和 sigmoid 激活函数。

A456157_1_En_1_Fig2_HTML.jpg

图 1-2

Two popular activation functions

A456157_1_En_1_Fig1_HTML.jpg

图 1-1

An activation function

下面是演示代码:

A456157_1_En_1_Figaf_HTML.jpg

ReLU 和 eLU

图 1-3 显示了 ReLU 和 eLU 功能。

A456157_1_En_1_Fig3_HTML.jpg

图 1-3

The ReLU and ELU functions

下面是生成这些函数的代码:

A456157_1_En_1_Figag_HTML.jpg

ReLU6

ReLU6 类似于 ReLU,只是输出不能超过 6。

A456157_1_En_1_Figah_HTML.jpg

请注意,tanh 是一个重新调整的逻辑 sigmoid 函数。

A456157_1_En_1_Figai_HTML.jpg

A456157_1_En_1_Figaj_HTML.jpg

A456157_1_En_1_Figak_HTML.jpg

A456157_1_En_1_Figal_HTML.jpg

A456157_1_En_1_Figam_HTML.jpg

A456157_1_En_1_Figan_HTML.jpg

损失函数

损失函数(成本函数)将被最小化,以便获得模型的每个参数的最佳值。例如,您需要获得权重(斜率)和偏差(y 截距)的最佳值,以便根据预测值(X)来解释目标(y)。方法是实现斜率的最佳值,y 截距是最小化代价函数/损失函数/平方和。对于任何模型,都有许多参数,并且预测或分类中的模型结构是用参数值来表示的。

你需要评估你的模型,为此你需要定义成本函数(损失函数)。损失函数的最小化可以是找到每个参数的最佳值的驱动力。对于回归/数值预测,L1 或 L2 可能是有用的损失函数。对于分类,交叉熵可以是有用的损失函数。Softmax 或 sigmoid 交叉熵可以是相当流行的损失函数。

损失函数示例

下面是演示的代码:

A456157_1_En_1_Figao_HTML.jpg

常见损失函数

以下是最常见的损失函数列表:

| `tf.contrib.losses.absolute_difference` | | `tf.contrib.losses.add_loss` | | `tf.contrib.losses.hinge_loss` | | `tf.contrib.losses.compute_weighted_loss` | | `tf.contrib.losses.cosine_distance` | | `tf.contrib.losses.get_losses` | | `tf.contrib.losses.get_regularization_losses` | | `tf.contrib.losses.get_total_loss` | | `tf.contrib.losses.log_loss` | | `tf.contrib.losses.mean_pairwise_squared_error` | | `tf.contrib.losses.mean_squared_error` | | `tf.contrib.losses.sigmoid_cross_entropy` | | `tf.contrib.losses.softmax_cross_entropy` | | `tf.contrib.losses.sparse_softmax_cross_entropy` | | `tf.contrib.losses.log(predictions,labels,weight=2.0)` |

优化者

现在你应该确信你需要使用一个损失函数来获得模型的每个参数的最佳值。如何才能获得最佳价值?

最初,您假设模型的权重和偏差的初始值(线性回归等)。).现在你需要找到达到参数最佳值的方法。优化器是达到参数最佳值的方法。在每次迭代中,该值都按照优化器建议的方向变化。假设你有 16 个权重值(w1w2w3、…、w16)和 4 个偏差(b1b2b3b4)。最初,你可以假设每一个权重和偏差都是零(或者一或任何数字)。优化器建议w1(和其他参数)是否应该在下一次迭代中增加或减少,同时牢记最小化的目标。经过多次迭代后,w1(以及其他参数)将稳定到参数的最佳值。

换句话说,TensorFlow 和其他每一个深度学习框架都提供了优化器,这些优化器缓慢地改变每个参数,以便最小化损失函数。优化器的目的是为下一次迭代中的变化给出权重和偏差的方向。假设你有 64 个权重和 16 个偏差;您尝试在每次迭代(反向传播期间)中改变权重和偏差值,以便在多次迭代后获得正确的权重和偏差值,同时尝试最小化损失函数。

为模型选择最佳优化器以快速收敛并正确学习权重和偏差是一项棘手的任务。

适应性技术(adadelta、adagrad 等。)对于复杂的神经网络收敛更快是很好的优化器。Adam 被认为是大多数情况下的最佳优化器。它也优于其他自适应技术(adadelta、adagrad 等)。),但是计算量很大。对于稀疏数据集,SGD、NAG、momentum 等方法不是最佳选择;自适应学习率方法有。一个额外的好处是,你不需要调整学习率,但可以用默认值达到最佳效果。

损失函数示例

下面是演示的代码:

A456157_1_En_1_Figaq_HTML.jpg

A456157_1_En_1_Figap_HTML.jpg

常见优化器

以下是常见优化器的列表:

A456157_1_En_1_Figar_HTML.jpg

韵律学

学了一些建立模型的方法,是时候评估模型了。所以,你需要评估回归器或分类器。

评价指标有很多,其中分类准确率、对数损失、ROC 曲线下面积是最受欢迎的。

分类准确度是正确预测数与所有预测数的比率。当每个类别的观察值没有太大偏差时,精确度可以被认为是一个很好的度量。

tf.contrib.metrics.accuracy(actual_labels, predictions)

还有其他评估指标。

指标示例

本节展示了要演示的代码。

在这里,您创建实际值(称为x)和预测值(称为y)。然后你检查准确性。准确度表示实际值等于预测值的次数与实例总数的比率。

通用指标

以下是常见指标的列表:

A456157_1_En_1_Figat_HTML.jpg

A456157_1_En_1_Figas_HTML.jpg

二、了解和使用 Keras

Keras 是一个简洁易学的深度学习高级 Python 库,可以运行在 TensorFlow(或者 Theano 或者 CNTK)之上。它允许开发人员专注于深度学习的主要概念,例如为神经网络创建层,同时关注张量的本质细节、形状和数学细节。TensorFlow(或 Theano 或 CNTK)必须是 Keras 的后端。可以使用 Keras 进行深度学习应用,而不需要与相对复杂的 TensorFlow(或者 Theano 或者 CNTK)进行交互。有两种主要的框架:顺序 API 和功能 API。顺序 API 基于一系列层的思想;这是 Keras 最常见的用法,也是 Keras 最容易的部分。顺序模型可以被认为是层的线性堆叠。

简而言之,您可以创建一个顺序模型,在这个模型中,您可以轻松地添加层,并且每个层都可以有卷积、最大池化、激活、退出和批处理规范化。让我们来看看在 Keras 中开发深度学习模型的主要步骤。

深度学习模型的主要步骤

Keras 中深度学习模型的四个核心部分如下:

  1. 定义模型。在这里,您创建一个顺序模型并添加层。每一层可以包含一个或多个卷积、汇集、批量标准化和激活功能。
  2. 编译模型。在这里,您在模型上调用compile()函数之前应用损失函数和优化器。
  3. 用训练数据拟合模型。在这里,您通过调用模型上的fit()函数来训练测试数据上的模型。
  4. 做预测。在这里,您通过调用函数(如evaluate()predict())来使用模型生成对新数据的预测。

Keras 的深度学习流程有八个步骤:

  1. 加载数据。
  2. 预处理数据。
  3. 定义模型。
  4. 编译模型。
  5. 符合模型。
  6. 评估模型。
  7. 做出预测。
  8. 保存模型。

加载数据

以下是加载数据的方式:

A456157_1_En_2_Figb_HTML.jpg

A456157_1_En_2_Figa_HTML.jpg

预处理数据

以下是预处理数据的方法:

A456157_1_En_2_Figc_HTML.jpg

A456157_1_En_2_Figd_HTML.jpg

定义模型

Keras 中的顺序模型被定义为一系列层。创建一个顺序模型,然后添加层。您需要确保输入图层具有正确的输入数量。假设你有 3072 个输入变量;然后你需要创建第一个有 512 个节点/神经元的隐藏层。在第二个隐藏层,你有 120 个节点/神经元。最后,输出层中有十个节点。例如,一幅图像映射到十个节点上,显示了被标记为 1(飞机)、2(汽车)、3(猫)、…、10(卡车)的概率。概率最高的节点是预测的类别/标签。

A456157_1_En_2_Fige_HTML.jpg

一幅图像有三个通道(RGB),在每个通道中,图像有 32×32 = 1024 个像素。因此,每个图像有 3×1024 = 3072 个像素(特征/X/输入)。

在 3072 个特征的帮助下,你需要预测标签 1(数字 0)、标签 2(数字 1)等等的概率。这意味着模型预测十个输出(数字 0-9),其中每个输出代表相应标签的概率。最后一个激活函数(sigmoid,如前所示)为 9 个输出提供 0,仅为 1 个输出提供 1。该标签是图像的预测类别(图 2-1 )。

例如,3072 功能➤ 512 节点➤ 120 节点➤ 10 节点。

A456157_1_En_2_Fig1_HTML.jpg

图 2-1

Defining the model

下一个问题是,你如何知道要使用的层数和它们的类型?没有人有确切的答案。对于评估指标来说,最好的是确定最佳层数以及每层中的参数和步骤。还使用了启发式方法。通过反复试验的过程找到最佳的网络结构。一般来说,你需要一个足够大的网络来捕捉问题的结构。

在本例中,您将使用三层全连接网络结构。密集类定义完全连接的层。

在这种情况下,将网络权重初始化为从均匀分布(均匀)生成的小随机数(在这种情况下介于 0 和 0.05 之间),因为这是 Keras 中默认的均匀权重初始化。另一个传统的选择是从高斯分布产生的小随机数的常态。您可以使用或捕捉任一类的硬分类,默认阈值为 0.5。你可以通过添加每一层把它们拼凑在一起。

编译模型

按照层定义了模型之后,您需要声明损失函数、优化器和评估指标。当提出模型时,初始权重和偏差值被假定为 0 或 1、随机正态分布数或任何其他方便的数。但是初始值并不是模型的最佳值。这意味着权重和偏差的初始值不能解释预测值(x)方面的目标/标签。所以,你想得到模型的最优值。从初始值到最优值的旅程需要一个动机,这个动机将最小化成本函数/损失函数。旅程需要一个路径(每次迭代中的变化),这是优化器建议的。这个旅程也需要一个评估测量,或者评估度量。

A456157_1_En_2_Figf_HTML.jpg

流行的损失函数是二元交叉熵、分类交叉熵、均方对数误差和铰链损失。流行的优化器是随机梯度下降(SGD)、RMSProp、adam、adagrad 和 adadelta。流行的评估指标是准确性、召回率和 F1 分数。

简而言之,这一步的目的是基于损失函数,通过基于优化器的迭代来调整权重和偏差,优化器由诸如准确性之类的度量来评估。

符合模型

定义并编译了模型之后,您需要通过对一些数据执行模型来做出预测。这里您需要指定纪元;这些是训练过程运行数据集的迭代次数和批量大小,批量大小是在权重更新之前评估的实例数量。对于这个问题,该程序将运行少量的时段(10),并且在每个时段中,它将完成 50 次(=50,000/1,000)迭代,其中批量大小为 1,000,训练数据集具有 50,000 个实例/图像。同样,没有选择批量大小的硬性规定。但是它不应该非常小,并且应该比训练数据集的大小小得多,以消耗更少的内存。

A456157_1_En_2_Figg_HTML.jpg

评估模型

在训练数据集上训练了神经网络之后,您需要评估网络的性能。请注意,这只能让您了解对数据集建模的效果(例如,训练精度),但您不知道该算法对新数据的执行效果如何。这是为了简单起见,但理想情况下,您可以将数据分为训练和测试数据集,用于模型的训练和评估。您可以使用模型上的evaluation()函数在您的训练数据集上评估您的模型,并将用于训练模型的相同输入和输出传递给它。这将为每个输入和输出对生成一个预测,并收集分数,包括平均损失和您已配置的任何度量,如准确性。

A456157_1_En_2_Figh_HTML.jpg

预报

一旦建立并评估了模型,就需要对未知数据进行预测。

A456157_1_En_2_Figi_HTML.jpg

保存并重新加载模型

这是最后一步:

A456157_1_En_2_Figk_HTML.jpg

A456157_1_En_2_Figj_HTML.jpg

可选:总结模型

现在来看如何总结模型。

A456157_1_En_2_Figl_HTML.jpg

改进 Keras 模型的其他步骤

以下是改进模型的更多步骤:

  1. Sometimes, the model building process does not complete because of a vanishing or exploding gradient. If this is the case, you should do the following:

    A456157_1_En_2_Fign_HTML.gif

  2. 对输出形状建模。

    #Shape of the n-dim array (output of the model at the current position)
    
      model.output_shape
    
    
  3. 对摘要表示进行建模。

    model.summary()
    
    
  4. 对配置建模。

    model.get_config()
    
    
  5. 列出模型中所有的重量张量。

    model.get_weights()
    
    

在这里,我分享了 Keras 模型的完整代码。你能试着解释一下吗?

A456157_1_En_2_Figm_HTML.jpg

使用 TensorFlow 很难

Keras 通过利用 TensorFlow/Theano 之上强大而清晰的深度学习库来提供高级神经网络。Keras 是 TensorFlow 的一个很好的补充,因为它的层和模型与纯 TensorFlow 张量兼容。此外,它可以与其他 TensorFlow 库一起使用。

以下是将 Keras 用于 TensorFlow 的步骤:

  1. 首先创建一个 TensorFlow 会话,并将其注册到 Keras。这意味着 Keras 将使用您注册的会话来初始化它在内部创建的所有变量。

    import TensorFlow as tf
    
    sess = tf.Session()
    
    from keras import backend as K
    
    K.set_session(sess)
    
    
  2. Keras 模块(如模型、层和激活)用于构建模型。Keras 引擎自动将这些模块转换成等价于 TensorFlow 的脚本。

  3. 除了 TensorFlow,Theano 和 CNTK 可以用作 Keras 的后端。

  4. TensorFlow 后端具有按照深度、高度、宽度顺序制作输入形状(到网络的第一层)的惯例,其中深度可以表示通道的数量。

  5. 您需要正确配置keras.json文件,以便它使用 TensorFlow 后端。它应该是这样的:

    {
    
           "backend": "theano",
    
           "epsilon": 1e-07,
    
           "image_data_format": "channels_first",
    
           "floatx": "float32"
    
    }
    
    

在接下来的章节中,您将学习如何利用 Keras 在 CNN、RNN、LSTM 和其他深度学习活动中工作。

三、多层感知器

在开始学习多层感知器之前,你需要对人工神经网络有一个大致的了解。这就是我在这一章要开始讲的。

人工神经网络

人工神经网络(ANN)是一种受生物神经网络启发的计算网络(节点和节点之间的互连系统),生物神经网络是人脑中神经元的复杂网络(见图 3-1 )。人工神经网络中创建的节点应该被编程为像实际神经元一样的行为,因此它们是人工神经元。图 3-1 显示了构成人工神经网络的节点(人工神经元)的网络。

A456157_1_En_3_Fig1_HTML.jpg

图 3-1

Artificial neural network

层数和每层的神经元/节点数可以是人工神经网络的主要结构组成部分。最初,权重(代表互连)和偏差不足以做出决定(分类等)。).它就像一个没有任何经验的婴儿的大脑。婴儿从经验中学习,以便成为一个好的决策者(分类者)。经验/数据(标记)帮助大脑的神经网络调整(神经)权重和偏差。人工神经网络经历相同的过程。每次迭代调整权重以创建好的分类器。由于手动调整数千个神经元的权重非常耗时,因此需要使用算法来完成这些任务。

调整权重的过程被称为学习或训练。这和人类日常所做的是一样的。我们试图让计算机像人类一样工作。

让我们开始探索最简单的人工神经网络模型。

典型的神经网络包含大量被称为单元的人工神经元,这些单元排列在一系列不同的层中:输入层、隐藏层和输出层(图 3-2 )。

A456157_1_En_3_Fig2_HTML.jpg

图 3-2

Neural network

神经网络是连接的,这意味着隐藏层中的每个神经元都与前一个输入层中的每个神经元以及下一个输出层完全连接。神经网络通过反复调整每层中的权重和偏差来学习,以获得最佳结果。

单层感知器

单层感知器是一个简单的线性二元分类器。它获取输入和相关权重,并将它们组合起来以产生用于分类的输出。它没有隐藏层。逻辑回归是单层感知器。

多层感知器

多层感知器(MLP)是反馈人工神经网络的一个简单例子。除了输入层和输出层之外,MLP 至少包含一个隐藏节点层。除输入层之外的层的每个节点被称为神经元,其使用诸如 sigmoid 或 ReLU 的非线性激活函数。MLP 使用一种称为反向传播的监督学习技术进行训练,同时最小化损失函数,如交叉熵。它使用优化器来调整参数(权重和偏差)。它的多层和非线性激活将 MLP 与线性感知器区分开来。

多层感知器是深度神经网络的基本形式。

在学习 MLPs 之前,我们先来看看线性模型和逻辑模型。你可以体会到线性、逻辑和 MLP 模型在复杂性方面的细微差别。

图 3-3 显示了一个输入(X)和一个输出(Y)的线性模型。

A456157_1_En_3_Fig3_HTML.jpg

图 3-3

Single-input vector

单输入模型有一个权重为 W、偏差为 b 的向量 X。输出 Y 是 WX + b,这是线性模型。

图 3-4 显示了多个输入(X1 和 X2)和一个输出(Y)。

A456157_1_En_3_Fig4_HTML.jpg

图 3-4

Linear model

此线性模型有两个输入要素:X1 和 X2,每个输入要素的对应权重为 W1、W2 和偏差 b。输出 Y 为 W1X1 + W2X2 + b

逻辑回归模型

图 3-5 显示了当二进制分类问题的输出标签 Y 为 0 或 1 时使用的学习算法。给定一个输入特征向量 X,你想要的是给定输入特征 X,Y = 1 的概率,这也被称为浅层神经网络或单层(无隐层;只有和输出层)神经网络。输出图层 Y 是σ (Z),其中 Z 是 WX + b,σ是 sigmoid 函数。

A456157_1_En_3_Fig5_HTML.jpg

图 3-5

One input (X) and one output (Y)

图 3-6 显示了当二进制分类问题的输出标签 Y 为 0 或 1 时使用的学习算法。

A456157_1_En_3_Fig6_HTML.jpg

图 3-6

Multiple inputs (X1 and X1) and one output (Y)

给定输入要素向量 X1 和 X2,您需要给定输入要素 Y = 1 的概率。这也被称为感知器。输出层 Y 为σ (Z),其中 Z 为 WX + b.

$$ \left[\begin{array}{c}X1\ {}X2\end{array}\right]\to \left[\begin{array}{cc}W1& W2\ {}W3& W4\end{array}\right]\left[\begin{array}{c}X1\ {}X2\end{array}\right]+\left[\begin{array}{c}b1\ {}b2\end{array}\right]\to \sigma \left(\left[\begin{array}{c}W1\ast X1+W2\ast X2+b1\ {}W3\ast X1+W4\ast X2+b2\end{array}\right]\right) $$

图 3-7 是一个两层的神经网络,有一个隐含层和一个输出层。考虑你有两个输入特征向量 X1 和 X2 连接到两个神经元,X1’和 X2’。从输入层到隐藏层的相关参数(权重)是 w1,w2,w3,w4,b1,b2。

A456157_1_En_3_Fig7_HTML.jpg

图 3-7

Two-layer neural network

X1 '和 X2 '计算线性组合(图 3-8 )。$$ \left[\begin{array}{c}X{1}^{\hbox{'}}\ {}X{2}^{\hbox{'}}\end{array}\right]=\left[\begin{array}{cc}w1& w2\ {}w3& w4\end{array}\right]\left[\begin{array}{c}X1\ {}X2\end{array}\right]+\left[\begin{array}{c}b1\ {}b2\end{array}\right] $$

(2×1)(2×2)(2×1)(2×1)是输入层和隐藏层的维数。

A456157_1_En_3_Fig8_HTML.jpg

图 3-8

Computation in the neural network

线性输入 X1’和 X2’通过隐藏层中的激活单元 a1 和 a2。

a1 是σ (X1 '),a2 是σ(X2 '),那么你也可以把方程写成:

$$ \left[\begin{array}{c}a1\ {}a2\end{array}\right]=\sigma \left[\begin{array}{c}X{1}^{\hbox{'}}\ {}X{2}^{\hbox{'}}\end{array}\right] $$

该值从隐藏层向前传播到输出层。输入 a1 和 a2 以及参数 w5、w6 和 b3 通过输出层 a’(图 3-9 )。

A456157_1_En_3_Fig9_HTML.jpg

图 3-9

Forward propagation

$$ {\mathrm{a}}^{\hbox{'}}=\left[w5\kern0.5em w6\right]\left[\begin{array}{c}a1\ {}a2\end{array}\right]+\left[b3\right] $$创建(w5a1 + w6a2) + b3 的线性组合,该组合将通过非线性 sigmoid 函数到达最终输出层 Y.

$$ y=\sigma \left({\mathrm{a}}^{\hbox{'}}\right) $$

假设一维的初始模型结构为 Y = w*X + b,其中参数 w 和 b 为权重和偏差。

对于参数 w = 1 和 b = 1 的初始值,考虑损失函数 L(w,b) = 0.9。你得到这样的输出:y = 1*X+1 & L(w,b) = 0.9。

目标是通过调整参数 w 和 b 来最小化损失。误差将从输出层反向传播到隐藏层,再到输入层,以通过学习率和优化器来调整参数。最后,我们想建立一个模型(回归量),可以用 x 来解释 Y。

为了开始建立模型的过程,我们初始化权重和偏差。为方便起见,w = 1,b = 1(初始值),(优化器)带学习率的随机梯度下降(α = 0.01)。

下面是第一步:Y = 1 * X + 1。

A456157_1_En_3_Figa_HTML.gif

1.20               0.35

参数调整为 w = 1.20,b = 0.35。

下面是第二步:Y1 = 1.20*X + 0.35。

A456157_1_En_3_Figb_HTML.gif

1.24               0.31

参数调整为 w = 1.24,b = 0.31。

下面是第三步:Y1 = 1.24*X + 0.31。

A456157_1_En_3_Figc_HTML.gif

1.25               0.30

经过一些迭代后,权重和偏差变得稳定。如您所见,在调优时,初始变化很大。经过一些迭代后,变化并不显著。

当 w = 1.26 且 b = 0.29 时,L(w,b)最小;因此,最终模型如下所示:

Y = 1.26 * X + 0.29

同样,在二维中,可以考虑参数,权重矩阵和偏置向量。

让我们假设初始权重矩阵和偏差向量为$$ \mathrm{W}=\left[\begin{array}{cc}1& 1\ {}1& 1\end{array}\right] $$$$ \mathrm{B}=\left[\begin{array}{c}1\ {}1\end{array}\right] $$

你迭代并反向传播误差来调整 w 和 b。

$$ \mathrm{Y}=\mathrm{W}=\left[\begin{array}{cc}1& 1\ {}1& 1\end{array}\right]\ast \left[X\right]+\left[\begin{array}{c}1\ {}1\end{array}\right] $$是初始模型。权重矩阵(2x2)和偏差矩阵(2x1)在每次迭代中进行调整。因此,我们可以看到权重和偏差矩阵的变化

下面是第一步:

$$ W=\left[\begin{array}{cc}0.7& 0.8\ {}0.6& 1.2\end{array}\right],B=\left[\begin{array}{c}2.4\ {}3.2\end{array}\right] $$

A456157_1_En_3_Fige_HTML.gif

A456157_1_En_3_Figd_HTML.gif

下面是第二步:$$ \left[\begin{array}{cc}0.7& 0.8\ {}0.6& 1.2\end{array}\right]\kern0.50em \left[\begin{array}{c}2.4\ {}3.2\end{array}\right] $$

$$ W=\left[\begin{array}{cc}0.6& 0.7\ {}0.4& 1.3\end{array}\right],B=\left[\begin{array}{c}2.8\ {}3.8\end{array}\right] $$

A456157_1_En_3_Figf_HTML.gif

下面是步骤 3: $$ \left[\begin{array}{cc}0.6& 0.7\ {}0.4& 1.3\end{array}\right]\kern0.50em \left[\begin{array}{c}2.8\ {}3.8\end{array}\right] $$你可以注意到迭代中权重矩阵(2x2)和偏差矩阵(2x1)的变化。

$$ W=\left[\begin{array}{cc}0.5& 0.6\ {}0.3& 1.3\end{array}\right],B=\left[\begin{array}{c}2.9\ {}4.0\end{array}\right] $$

A456157_1_En_3_Figg_HTML.gif

You can notice change in weight matrix(2x2) and bias matrix(2x1) in the iteration.

调整 w 和 b 后的最终模型如下:

$$ \mathrm{Y}=\left[\begin{array}{cc}0.4& 0.5\ {}0.2& 1.3\end{array}\right]\ast \left[X\right]+\left[\begin{array}{c}3.0\ {}4.0\end{array}\right] $$

在本章中,您学习了如何在每次迭代中调整权重和偏差,同时保持损失函数最小化的目标。这是在优化器如随机梯度下降的帮助下完成的。

在这一章中,我们已经理解了人工神经网络和 MLP 作为基本的深度学习模型。在这里,我们可以看到 MLP 作为线性和逻辑回归的自然进展。我们已经看到在反向传播的每次迭代中权重和偏差是如何调整的。不用深入反向传播的细节,我们已经看到了反向传播的作用/结果。在接下来的两章中,我们将学习如何在 TensorFlow 和 keras 中建立 MLP 模型。

四、TensorFlow 中的 MLP 回归

长期以来,人们一直在使用回归和分类器。现在是时候切换到神经网络的话题了。多层感知器(MLP)是一个简单的神经网络模型,您可以在输入和输出层之间添加一个或多个隐藏层。

在本章中,您将看到 TensorFlow 如何帮助您构建模型。您将从最基本的模型开始,这是一个线性模型。本章还讨论了逻辑斯蒂和 MLP 模型。

TensorFlow 构建模型的步骤

在这一节中,我将讨论在 TensorFlow 中建立模型的步骤。我将带您完成这里的步骤,然后您将看到贯穿本章的代码:

  1. 加载数据。
  2. 将数据拆分到训练和测试中。
  3. 如果需要,进行标准化。
  4. 初始化包含预测值和目标值的占位符。
  5. 创建将被调整的变量(权重和偏差)。
  6. 声明模型操作。
  7. 声明损失函数和优化器。
  8. 初始化变量和会话。
  9. 通过使用训练循环来拟合模型。
  10. 用测试数据检查并显示结果。

TensorFlow 中的线性回归

首先你需要理解 TensorFlow 中线性回归的代码。图 4-1 显示了一个基本的线性模型。

A456157_1_En_4_Fig1_HTML.jpg

图 4-1

Basic linear model

如图 4-1 所示,调整重量(W)和偏差(b)以获得正确的重量和偏差值。所以,权重(W)和偏差(b)是 TensorFlow 代码中的变量;您将在每次迭代中调整/修改它们,直到获得稳定(正确)的值。

您需要为 x 创建占位符。占位符具有特定的形状并包含特定的类型。

当你有一个以上的特性时,你会有一个类似于图 4-2 的工作模型。

A456157_1_En_4_Fig2_HTML.jpg

图 4-2

Linear model with multiple inputs

在下面的代码中,您将使用 Seaborn 的 Iris 数据集,它有五个属性。您将把萼片长度作为输入,花瓣长度作为输出值。这个回归模型的主要目的是在给定萼片长度值的情况下预测花瓣长度。x 是萼片长度,Y 是花瓣长度。

利用 TensorFlow 对虹膜数据进行线性回归

A456157_1_En_4_Figl_HTML.jpg

A456157_1_En_4_Figk_HTML.jpg

A456157_1_En_4_Figj_HTML.jpg

A456157_1_En_4_Figi_HTML.jpg

A456157_1_En_4_Figh_HTML.jpg

A456157_1_En_4_Figg_HTML.jpg

A456157_1_En_4_Figf_HTML.jpg

A456157_1_En_4_Fige_HTML.jpg

A456157_1_En_4_Figd_HTML.jpg

A456157_1_En_4_Figc_HTML.jpg

A456157_1_En_4_Figb_HTML.jpg

A456157_1_En_4_Figa_HTML.jpg

如果您运行代码,您将看到如图 4-3 所示的输出。

A456157_1_En_4_Fig3_HTML.jpg

图 4-3

Weights, bias, and loss at each step

图 4-4 显示了花瓣长度预测值的曲线图。

A456157_1_En_4_Fig4_HTML.jpg

图 4-4

Petal length versus sepal length

逻辑回归模型

对于分类,最简单的方法是逻辑回归。在本节中,您将了解如何在 TensorFlow 中执行逻辑回归。在这里,您将权重和偏差创建为变量,以便每次迭代都有调整/更改它们的范围。创建占位符是为了包含 x。您需要为 x 创建占位符。占位符具有特定的形状,包含特定的类型,如图 4-5 所示。

A456157_1_En_4_Fig5_HTML.jpg

图 4-5

Chart of logistic regression model

在下面的代码中,您将使用 Iris 数据集,它有五个属性。第五个是目标阶层。您将把萼片长度和萼片宽度视为预测属性,将花的种类视为目标值。这个逻辑回归模型的主要目的是在给定萼片长度和萼片宽度值的情况下预测物种的种类。

创建一个 Python 文件并导入所有需要的库。

A456157_1_En_4_Figv_HTML.jpg

A456157_1_En_4_Figu_HTML.jpg

A456157_1_En_4_Figt_HTML.jpg

A456157_1_En_4_Figs_HTML.jpg

A456157_1_En_4_Figr_HTML.jpg

A456157_1_En_4_Figq_HTML.jpg

A456157_1_En_4_Figp_HTML.jpg

A456157_1_En_4_Figo_HTML.jpg

A456157_1_En_4_Fign_HTML.jpg

A456157_1_En_4_Figm_HTML.jpg

如果你运行前面的代码,每个时期的交叉熵损失图如图 4-6 所示。

A456157_1_En_4_Fig6_HTML.jpg

图 4-6

Plot for cross entropy loss per epoch

TensorFlow 中的多层感知器

多层感知器(MLP)是反馈人工神经网络的一个简单例子。除了输入层和输出层之外,MLP 至少包含一个隐藏节点层。除输入层之外的层的每个节点被称为神经元,其使用诸如 sigmoid 或 ReLU 的非线性激活函数。MLP 使用一种称为反向传播的监督学习技术进行训练,同时最小化交叉熵等损失函数,并使用优化器来调整参数(权重和偏差)。它的多层和非线性激活将 MLP 与线性感知器区分开来。

TensorFlow 非常适合构建 MLP 模型。在 MLP 中,您需要调整每次迭代的权重和偏差。这意味着权重和偏差保持变化,直到它们变得稳定,同时最小化损失函数。因此,您可以在 TensorFlow 中将权重和偏差创建为变量。我倾向于给它们初始值(全 0 或者全 1 或者一些随机的正态分布值)。占位符应该具有特定类型的值和定义的形状,如图 4-7 所示。

A456157_1_En_4_Fig7_HTML.jpg

图 4-7

Flowchart for MLP

导入所有需要的库。在 TensorFlow 中实现 MLP。

A456157_1_En_4_Figae_HTML.jpg

A456157_1_En_4_Figad_HTML.jpg

A456157_1_En_4_Figac_HTML.jpg

A456157_1_En_4_Figab_HTML.jpg

A456157_1_En_4_Figaa_HTML.jpg

A456157_1_En_4_Figz_HTML.jpg

A456157_1_En_4_Figy_HTML.jpg

A456157_1_En_4_Figx_HTML.jpg

A456157_1_En_4_Figw_HTML.jpg

如果您运行这段代码,您将得到如图 4-8 所示的曲线图。

A456157_1_En_4_Fig8_HTML.jpg

图 4-8

Plot for loss while training and testing

在本章中,我讨论了如何在 TensorFlow 中系统地构建线性、逻辑和 MLP 模型。

五、Keras 的 MLP 回归

你在解决机器学习应用的同时,一直在做回归工作。线性回归和非线性回归用于预测数字目标,而逻辑回归和其他分类器用于预测非数字目标变量。在这一章,我将讨论多层感知器的进化。

具体来说,您将比较使用和不使用 Keras 时不同模型生成的准确性。

对数线性模型

创建一个新的 Python 文件并导入以下包。确保您的系统上安装了 Keras。

A456157_1_En_5_Figa_HTML.jpg

您将使用 Iris 数据集作为数据源。从 Seaborn 下载数据集。

A456157_1_En_5_Figb_HTML.jpg

虹膜数据集有五个属性。您将使用前四个属性来预测物种,其类别在数据集的第五个属性中定义。

A456157_1_En_5_Figc_HTML.jpg

使用scikit-learn的函数,分割测试和训练数据集。

A456157_1_En_5_Figd_HTML.jpg

##################################
# scikit Learn for (Log) Linear Regression #
##################################

使用model.fit功能用训练数据集训练模型。

A456157_1_En_5_Fige_HTML.jpg

随着模型的定型,您可以预测测试集的输出。

A456157_1_En_5_Figf_HTML.jpg

线性回归的 Keras 神经网络

现在,让我们建立一个线性回归的 Keras 神经网络模型。

A456157_1_En_5_Figh_HTML.jpg

A456157_1_En_5_Figg_HTML.jpg

使用model.fit功能用训练数据集训练模型。

A456157_1_En_5_Figi_HTML.jpg

随着模型的定型,您可以预测测试集的输出。

A456157_1_En_5_Figj_HTML.jpg

打印两种模型获得的精度。

A456157_1_En_5_Figk_HTML.jpg

如果运行该代码,您将看到以下输出:

A456157_1_En_5_Figl_HTML.jpg

逻辑回归

在这一节,我将分享一个逻辑回归的例子,这样你就可以比较scikit-learn和 Keras 中的代码(见图 5-1 )。

A456157_1_En_5_Fig1_HTML.jpg

图 5-1

Logistic regression used for classification

创建一个新的 Python 文件并导入以下包。确保您的系统上安装了 Keras。

A456157_1_En_5_Figm_HTML.jpg

您将使用 Iris 数据集作为数据源。因此,从 scikit-learn 加载数据集。

A456157_1_En_5_Fign_HTML.jpg

使用scikit-learn的函数,分割测试和训练数据集。

A456157_1_En_5_Figo_HTML.jpg

sci kit-学习逻辑回归

使用model.fit功能用训练数据集训练模型。模型定型后,您可以预测测试集的输出。

A456157_1_En_5_Figp_HTML.jpg

########################################

用于逻辑回归的 Keras 神经网络

一键编码将要素转换为更适合分类和回归算法的格式。

A456157_1_En_5_Figs_HTML.jpg

A456157_1_En_5_Figr_HTML.jpg

A456157_1_En_5_Figq_HTML.jpg

使用model.fit功能用训练数据集训练模型。

A456157_1_En_5_Figt_HTML.jpg

使用model.evaluate功能评估模型的性能。

A456157_1_En_5_Figu_HTML.jpg

打印两种模型获得的精度。基于 scikit-learn 的模型的准确性

A456157_1_En_5_Figv_HTML.jpg

精度为 0.83。keras 模型的精度

A456157_1_En_5_Figw_HTML.jpg

精度为 0.99。

如果运行该代码,您将看到以下输出:

A456157_1_En_5_Figx_HTML.jpg

为了给出真实的例子,我将讨论一些使用时尚 MNIST 数据集的代码,这是 Zalando.com 的图像数据集,由 60,000 个示例的训练集和 10,000 个示例的测试集组成。每个示例都是一个 28×28 灰度图像,与来自 10 个类别的标签相关联。

时尚 MNIST 数据:Keras 中的逻辑回归

创建一个新的 Python 文件并导入以下包。确保您的系统上安装了 Keras。

A456157_1_En_5_Figy_HTML.jpg

如上所述,您将使用时尚 MNIST 数据集。将数据和标签存储在两个不同的变量中。

A456157_1_En_5_Figz_HTML.jpg

规范化数据集,如下所示:

A456157_1_En_5_Figaa_HTML.jpg

定义模型,如下所示:

A456157_1_En_5_Figab_HTML.jpg

将模型保存在一个.h5文件中(这样您以后可以直接使用 keras.models 中的load_model()函数)并打印测试集中模型的准确性,如下所示:

A456157_1_En_5_Figac_HTML.jpg

如果运行前面的代码,您将看到以下输出:

('train-images-idx3-ubyte.gz', <http.client.HTTPMessage object at 0x00000171338E2B38>)
_______________________________________________________________
Layer (type)                 Output Shape              Param #   
===============================================================
dense_59 (Dense)             (None, 256)               200960    
_______________________________________________________________
dropout_10 (Dropout)         (None, 256)               0         
_______________________________________________________________
dense_60 (Dense)             (None, 512)               131584    
_______________________________________________________________
dense_61 (Dense)             (None, 10)                5130      
===============================================================
Total params: 337,674
Trainable params: 337,674
Non-trainable params: 0
_______________________________________________________________
Train on 60000 samples, validate on 10000 samples
Epoch 1/2
60000/60000 [==============================] - loss: 0.5188 - acc: 0.8127 - val_loss: 0.4133 - val_acc: 0.8454
Epoch 2/2
60000/60000 [==============================] - loss: 0.3976 - acc: 0.8545 - val_loss: 0.4010 - val_acc: 0.8513
Test loss: 0.400989927697
Test accuracy: 0.8513

上的 mips

多层感知器是一个最小的神经网络模型。在这一部分,我将向您展示代码。

写代码

创建一个新的 Python 文件并导入以下包。确保您的系统上安装了 Keras。

A456157_1_En_5_Figad_HTML.jpg

通过使用 Pandas 读取 CSV 文件来加载数据集。

A456157_1_En_5_Figae_HTML.jpg

将数值分配给数据集的类别。

A456157_1_En_5_Figaf_HTML.jpg

将数据框转换为数组。

A456157_1_En_5_Figag_HTML.jpg

分割数据和目标,并将它们存储在两个不同的变量中。

A456157_1_En_5_Figah_HTML.jpg

使用 Numpy 更改目标格式。

A456157_1_En_5_Figai_HTML.jpg

建立一个连续的 Keras 模型

在这里,您将建立一个多层感知器模型与一个隐藏层。

A456157_1_En_5_Figaj_HTML.jpg

  • 输入层:输入层包含四个神经元,代表虹膜的特征(萼片长度等。).
  • 隐层:隐层包含十个神经元,激活使用 ReLU。
  • 输出层:输出层包含三个神经元,代表 Iris softmax 层的类别。

编译模型并选择优化器和损失函数来训练和优化数据,如下所示:

A456157_1_En_5_Figak_HTML.jpg

使用model.fit功能训练模型,如下所示:

A456157_1_En_5_Figal_HTML.jpg

加载并准备测试数据,如下所示:

A456157_1_En_5_Figam_HTML.jpg

将字符串值转换为数值,如下所示:

A456157_1_En_5_Figan_HTML.jpg

将数据框转换为数组,如下所示:

A456157_1_En_5_Figao_HTML.jpg

分割xy,换句话说,特性集和目标集,如下所示:

A456157_1_En_5_Figap_HTML.jpg

对训练好的模型进行预测,如下所示:

A456157_1_En_5_Figaq_HTML.jpg

计算精确度,如下所示:

A456157_1_En_5_Figar_HTML.jpg

打印模型生成的精度,如下所示:

A456157_1_En_5_Figas_HTML.jpg

如果运行该代码,您将看到以下输出:

Epoch 1/100
120/120 [==============================] - 0s - loss: 2.7240 - acc: 0.3667
Epoch 2/100
120/120 [==============================] - 0s - loss: 2.4166 - acc: 0.3667
Epoch 3/100
120/120 [==============================] - 0s - loss: 2.1622 - acc: 0.4083
Epoch 4/100
120/120 [==============================] - 0s - loss: 1.9456 - acc: 0.6583

Epoch 98/100
120/120 [==============================] - 0s - loss: 0.5571 - acc: 0.9250
Epoch 99/100
120/120 [==============================] - 0s - loss: 0.5554 - acc: 0.9250
Epoch 100/100
120/120 [==============================] - 0s - loss: 0.5537 - acc: 0.9250

MNIST 数据的 MLPs(数字分类)

MNIST 是预测手写数字的标准数据集。在本节中,您将看到如何应用多层感知器的概念并制作一个手写数字识别系统。

创建一个新的 Python 文件并导入以下包。确保您的系统上安装了 Keras。

A456157_1_En_5_Figat_HTML.jpg

定义了一些重要的变量。

A456157_1_En_5_Figau_HTML.jpg

使用mnist.load_data()功能加载数据集。

A456157_1_En_5_Figav_HTML.jpg

训练集和测试集的类型被转换为float32

A456157_1_En_5_Figaw_HTML.jpg

数据集是标准化的;换句话说,它们被设置为 Z 分数。

A456157_1_En_5_Figax_HTML.jpg

显示数据集中存在的训练样本的数量以及可用测试集的数量。

A456157_1_En_5_Figay_HTML.jpg

将类别向量转换为二进制类别矩阵。

A456157_1_En_5_Figaz_HTML.jpg

定义多层感知器的顺序模型。

A456157_1_En_5_Figba_HTML.jpg

使用优化器。

A456157_1_En_5_Figbb_HTML.jpg

要优化的函数是真实标签和模型输出(softmax)之间的交叉熵。

A456157_1_En_5_Figbc_HTML.jpg

使用model.fit功能训练模型。

A456157_1_En_5_Figbd_HTML.jpg

使用模型,评估函数来评估模型的性能。

A456157_1_En_5_Figbe_HTML.jpg

打印模型中生成的精度。

A456157_1_En_5_Figbf_HTML.jpg

如果运行该代码,您将获得以下输出:

60000 train samples
10000 test samples
Train on 60000 samples, validate on 10000 samples
Epoch 1/20
13s - loss: 0.2849 - acc: 0.9132 - val_loss: 0.1149 - val_acc: 0.9652
Epoch 2/20
11s - loss: 0.1299 - acc: 0.9611 - val_loss: 0.0880 - val_acc: 0.9741
Epoch 3/20
11s - loss: 0.0998 - acc: 0.9712 - val_loss: 0.1121 - val_acc: 0.9671
Epoch 4/20
Epoch 18/20
14s - loss: 0.0538 - acc: 0.9886 - val_loss: 0.1241 - val_acc: 0.9814
Epoch 19/20
12s - loss: 0.0522 - acc: 0.9888 - val_loss: 0.1154 - val_acc: 0.9829
Epoch 20/20
13s - loss: 0.0521 - acc: 0.9891 - val_loss: 0.1183 - val_acc: 0.9824
Test score: 0.118255248802
Test accuracy: 0.9824

现在,是时候创建一个数据集并使用多层感知器了。在这里,您将使用随机函数创建自己的数据集,并对生成的数据运行多层感知器模型。

随机生成数据的 MLPs

创建一个新的 Python 文件并导入以下包。确保您的系统上安装了 Keras。

A456157_1_En_5_Figbg_HTML.jpg

使用random功能生成数据。

A456157_1_En_5_Figbh_HTML.jpg

创建顺序模型。

A456157_1_En_5_Figbi_HTML.jpg

编译模型。

A456157_1_En_5_Figbj_HTML.jpg

使用model.fit功能训练模型。

A456157_1_En_5_Figbk_HTML.jpg

使用model.evaluate功能评估模型的性能。

A456157_1_En_5_Figbl_HTML.jpg

如果运行该代码,您将获得以下输出:

Epoch 1/20
1000/1000 [==============================] - 0s - loss: 2.4432 - acc: 0.0970     
Epoch 2/20
1000/1000 [==============================] - 0s - loss: 2.3927 - acc: 0.0850     
Epoch 3/20
1000/1000 [==============================] - 0s - loss: 2.3361 - acc: 0.1190     
Epoch 4/20
1000/1000 [==============================] - 0s - loss: 2.3354 - acc: 0.1000
Epoch 19/20
1000/1000 [==============================] - 0s - loss: 2.3034 - acc: 0.1160     
Epoch 20/20
1000/1000 [==============================] - 0s - loss: 2.3055 - acc: 0.0980     
100/100 [==============================] - 0s

在这一章中,我讨论了如何系统地在 Keras 中建立线性、逻辑和 MLP 模型。

六、卷积神经网络

卷积神经网络(CNN)是一种深度前馈人工神经网络,其中神经网络通过学习内部特征表示并概括常见图像问题(如对象识别和其他计算机视觉问题)中的特征来保留分层结构。它不限于图像;它还在自然语言处理问题和语音识别方面取得了最先进的成果。

CNN 中的不同层

一个 CNN 由多层组成,如图 6-1 所示。

A456157_1_En_6_Fig1_HTML.jpg

图 6-1

Layers in a convolution neural network

卷积层由滤镜和图像贴图组成。假设灰度输入图像的大小为 5×5,这是一个 25 像素值的矩阵。图像数据表示为宽×高×通道的三维矩阵。

Note

图像映射是与特定图像相关的坐标列表。

卷积旨在从输入图像中提取特征,因此它通过使用输入数据的小方块学习图像特征来保持像素之间的空间关系。可以预期旋转不变性、平移不变性和比例不变性。例如,由于卷积步骤,CNN 可以容易地识别旋转的 cat 图像或重新缩放的 cat 图像。在原始图像(此处为 1 个像素)上滑动滤镜(方形矩阵),在每个给定位置,计算元素级乘法(滤镜和原始图像的矩阵之间),并将乘法输出相加,以获得形成输出矩阵元素的最终整数。

子采样是简单的平均池,每个特征图具有可学习的权重,如图 6-2 所示。

A456157_1_En_6_Fig2_HTML.jpg

图 6-2

Subsampling

如图 6-2 所示,滤波器有输入权值,产生一个输出神经元。假设您定义了一个卷积层,它有六个过滤器和接收域,宽 2 像素,高 2 像素,默认步长为 1,默认填充设置为 0。每个滤波器从图像的 2×2 像素部分接收输入。换句话说,就是一次 4 个像素。因此,您可以说它将需要 4 + 1(偏差)输入权重。

输入体积为 5×5×3(宽×高×通道数),有 6 个 2×2 大小的滤波器,步长为 1,pad 为 0。因此,对于每个滤波器,该层中的参数数量为 223 + 1 = 13 个参数(对于偏差加上+ 1)。因为有六个过滤器,所以有 13*6 = 78 个参数。

A456157_1_En_6_Fig3_HTML.jpg

图 6-3

Input volume

这里有一个总结:

  • 输入体积的大小为 W1 × H1 × D1。
  • 该模型需要超参数:滤波器的数量(f)、步距(S)、零填充量(P)。
  • 这产生尺寸为 W2 × H2 × D2 的体积。
  • W2 = (W1-f+ 2P) /S + 1 = 4。
  • H2 = (H1-f+2P)/S +1 = 4。
  • D2 =过滤器数量= f = 6。

池层减少了先前层的激活映射。接下来是一个或多个卷积层,整合了前几层激活图中的所有特性。这减少了训练数据的过拟合,并概括了网络所表示的特征。感受野大小几乎总是设置为 2×2,并使用 1 或 2(或更高)的步幅以确保没有重叠。您将对每个感受野使用最大操作,以便激活为最大输入值。在这里,每四个数字映射到一个数字。于是,这一步像素数下降到原来的四分之一(图 6-4 )。

A456157_1_En_6_Fig4_HTML.jpg

图 6-4

Maxpooling-reducing the number of pixels

全连接层是前馈人工神经网络层。这些层具有非线性激活函数来输出类别预测概率。在所有特征被卷积层识别和提取并且已经被网络中的汇集层合并之后,它们被用于最后。这里,隐藏层和输出层是完全连接的层。

CNN 架构

CNN 是一种前馈深度神经网络架构,由几个卷积层组成,每个卷积层后面都有一个池层、激活函数和可选的批量标准化。它还包括完全连接的层。当图像在网络中移动时,它会变小,这主要是因为 max pooling。最后一层输出类别概率预测。

A456157_1_En_6_Fig5_HTML.jpg

图 6-5

CNN Architecture for Classification

在过去的几年中,已经开发了许多架构,这些架构在图像分类领域取得了巨大的进步。屡获殊荣的预训练网络(VGG16、VGG19、ResNet50、Inception V3 和 Xception)已被用于各种图像分类挑战,包括医学成像。迁移学习是一种除了几层之外还使用预训练模型的实践。它可以用来解决图像分类在各个领域的挑战。

七、TensorFlow 中的 CNN

本章将演示如何使用 TensorFlow 建立一个 CNN 模型。CNN 模型可以帮助你建立一个可以预测/分类图像的图像分类器。一般来说,您在模型架构中创建一些层,这些层具有权重和偏差的初始值。然后,您可以在训练数据集的帮助下调整权重和偏差。还有另一种方法,包括使用预训练模型(如 InceptionV3)对图像进行分类。您可以使用这种迁移学习方法,在预训练模型(参数值保持不变)的层之上添加一些层(其参数已被训练),以制作非常强大的分类器。

在这一章中,我将使用 TensorFlow 展示如何为各种计算机视觉应用开发卷积网络。将 CNN 架构表示为数据流图更容易。

CNN 模型为什么要 TensorFlow?

在 TensorFlow 中,图像可以表示为三维数组或形状的张量(高度、宽度和通道)。TensorFlow 提供了快速迭代的灵活性,允许您更快地训练模型,并使您能够运行更多的实验。将 TensorFlow 模型投入生产时,可以在大规模 GPU 和 TPU 上运行。

用于为 MNIST 数据构建图像分类器的 TensorFlow 代码

在本节中,我将带您通过一个示例来了解如何在 TensorFlow 中实现 CNN。

以下代码从 TensorFlow contrib 包中导入包含数字的 28×28 灰度图像的 MNIST 数据集,并加载所有必需的库。这里,目标是建立分类器来预测图像中给定的数字。

from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets
from tensorflow.python.framework import ops
import tensorflow as tf
import numpy as np

然后启动图形会话。

# Start a graph session
sess = tf.Session()

您加载 MNIST 数据并创建训练集和测试集。

# Load data
from keras.datasets import mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()

然后规范化训练和测试集特征。

# Z- score  or Gaussian Normalization
X_train = X_train - np.mean(X_train) / X_train.std()
X_test = X_test - np.mean(X_test) / X_test.std()

由于这是一个多类分类问题,因此最好使用输出类值的一次性编码。

# Convert labels into one-hot encoded vectors
num_class = 10
train_labels = tf.one_hot(y_train, num_class)
test_labels = tf.one_hot(y_test, num_class)

现在让我们设置模型参数,因为这些图像是灰度的。因此,图像(通道)的深度是 1。

# Set model parameters
batch_size = 784
samples =500
learning_rate = 0.03
img_width = X_train[0].shape[0]
img_height = X_train[0].shape[1]
target_size = max(train_labels) + 1
num_channels = 1 # greyscale = 1 channel
epoch = 200
no_channels = 1
conv1_features = 30
filt1_features = 5
conv2_features = 15
filt2_features = 3
max_pool_size1 = 2 # NxN window for 1st max pool layer
max_pool_size2 = 2 # NxN window for 2nd max pool layer
fully_connected_size1 = 150

让我们声明模型的占位符。可以为训练集和评估集更改输入数据特征、目标变量和批量大小。

# Declare model placeholders
x_input_shape = (batch_size, img_width, img_height, num_channels)
x_input = tf.placeholder(tf.float32, shape=x_input_shape)
y_target = tf.placeholder(tf.int32, shape=(batch_size))
eval_input_shape = (samples, img_width, img_height, num_channels)
eval_input = tf.placeholder(tf.float32, shape=eval_input_shape)
eval_target = tf.placeholder(tf.int32, shape=(samples))

让我们为输入层和隐藏层的神经元声明模型变量的权重和偏差值。

# Declare model variables
W1 = tf.Variable(tf.random_normal([filt1_features, filt1_features, no_channels, conv1_features]))
b1 = tf.Variable(tf.ones([conv1_features]))
W2 = tf.Variable(tf.random_normal([filt2_features, filt2_features, conv1_features, conv2_features]))
b2 = tf.Variable(tf.ones([conv2_features]))

让我们为完全连接的层声明模型变量,并为最后两层定义权重和偏差。

# Declare model variables for fully connected layers
resulting_width = img_width // (max_pool_size1 * max_pool_size2)
resulting_height = img_height // (max_pool_size1 * max_pool_size2)
full1_input_size = resulting_width * resulting_height * conv2_features
W3 = tf.Variable(tf.truncated_normal([full1_input_size, fully_connected_size1], stddev=0.1, dtype=tf.float32))
b3 = tf.Variable(tf.truncated_normal([fully_connected_size1], stddev=0.1, dtype=tf.float32))
W_out = tf.Variable(tf.truncated_normal([fully_connected_size1, target_size], stddev=0.1, dtype=tf.float32))
b_out = tf.Variable(tf.truncated_normal([target_size], stddev=0.1, dtype=tf.float32))

让我们创建一个助手函数来定义卷积层和最大池层。

# Define helper functions for the convolution and maxpool layers:
def conv_layer(x, W, b):
    conv = tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding="SAME")
    conv_with_b = tf.nn.bias_add(conv, b)
    conv_out = tf.nn.relu(conv_with_b)
    return conv_out
def maxpool_layer(conv, k=2):
    return tf.nn.max_pool(conv, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding="SAME")

神经网络模型由两个隐藏层和两个完全连接的层定义。整流线性单元被用作隐藏层和最终输出层的激活函数。

# Initialize Model Operations

def my_conv_net(input_data):
    # First Conv-ReLU-MaxPool Layer
    conv_out1 = conv_layer(input_data, W1, b1)
    maxpool_out1 = maxpool_layer(conv_out1)

    # Second Conv-ReLU-MaxPool Layer
    conv_out2 = conv_layer(maxpool_out1, W2, b2)
    maxpool_out2 = maxpool_layer(conv_out2)

    # Transform Output into a 1xN layer for next fully connected layer
    final_conv_shape = maxpool_out2.get_shape().as_list()
    final_shape = final_conv_shape[1] * final_conv_shape[2] * final_conv_shape[3]
    flat_output = tf.reshape(maxpool_out2, [final_conv_shape[0], final_shape])

    # First Fully Connected Layer
    fully_connected1 = tf.nn.relu(tf.add(tf.matmul(flat_output, W3), b3))
    # Second Fully Connected Layer
    final_model_output = tf.add(tf.matmul(fully_connected1, W_out), b_out)

    return(final_model_output)

model_output = my_conv_net(x_input)
test_model_output = my_conv_net(eval_input)

您将使用 softmax 交叉熵函数(更适用于多类分类)来定义作用于逻辑的损失。

# Declare Loss Function

(softmax cross entropy)
loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=model_output, labels=y_target))

让我们定义训练集和测试集的预测函数。

# Create a prediction function
prediction = tf.nn.softmax(model_output)
test_prediction = tf.nn.softmax(test_model_output)

为了确定每一批的模型精度,让我们定义精度函数。

# Create accuracy function
def get_accuracy(logits, targets):
    batch_predictions = np.argmax(logits, axis=1)
    num_correct = np.sum(np.equal(batch_predictions, targets))
    return(100\. * num_correct/batch_predictions.shape[0])

让我们声明训练步骤并定义优化器函数。

# Create an optimizer
my_optimizer = tf.train.AdamOptimizer(learning_rate, 0.9)
train_step = my_optimizer.minimize(loss)

让我们初始化前面声明的所有模型变量。

# Initialize Variables
varInit = tf.global_variables_initializer()
sess.run(varInit)

让我们开始训练模型,并随机循环处理这些数据。您希望在训练和测试集批次上评估模型,并记录损失和准确性。

# Start training loop

train_loss = []
train_acc = []
test_acc = []
for i in range(epoch):
    random_index = np.random.choice(len(X_train), size=batch_size)
    random_x = X_train[random_index]
    random_x = np.expand_dims(random_x, 3)
    random_y = train_labels[random_index]   

    train_dict = {x_input: random_x, y_target: random_y}

    sess.run(train_step, feed_dict=train_dict)
    temp_train_loss, temp_train_preds = sess.run([loss, prediction], feed_dict=train_dict)
    temp_train_acc = get_accuracy(temp_train_preds, random_y)

    eval_index = np.random.choice(len(X_test), size=evaluation_size)
    eval_x = X_test[eval_index]
    eval_x = np.expand_dims(eval_x, 3)
    eval_y = test_labels[eval_index]
    test_dict = {eval_input: eval_x, eval_target: eval_y}
    test_preds = sess.run(test_prediction, feed_dict=test_dict)
    temp_test_acc = get_accuracy(test_preds, eval_y)

模型的结果以下列格式记录并打印在输出中:

# Record and print results

train_loss.append(temp_train_loss)
train_acc.append(temp_train_acc)
test_acc.append(temp_test_acc)
print('Epoch # {}. Train Loss: {:.2f}. Train Acc : {:.2f} . temp_test_acc : {:.2f}'.format(i+1,temp_train_loss,temp_train_acc,temp_test_acc))

使用高级 API 构建 CNN 模型

TFLearn、TensorLayer、tflayers、TF-Slim、tf.contrib.learn、Pretty Tensor、keras 和 Sonnet 都是高级 TensorFlow APIs。如果您使用这些高级 API 中的任何一个,您都可以用几行代码构建 CNN 模型。因此,您可以探索这些 API 中的任何一个来更好地工作。

八、Keras CNN

本章将演示如何使用 Keras 建立 CNN 模型。CNN 模型可以帮助你建立一个可以预测和分类图像的图像分类器。一般来说,您在模型架构中创建一些层,这些层具有权重和偏差的初始值。然后,在训练数据集的帮助下,调整权重和偏差变量。在这种情况下,您将学习如何用 Keras 编码。还有另一种方法涉及使用预训练的模型,如 InceptionV3 和 ResNet50,这些模型可以对图像进行分类。

让我们定义一个 CNN 模型,并评估它的性能。您将使用带有卷积层的结构;然后,您将使用 max pooling 并展平网络以完全连接图层并进行预测。

为 Keras 中的 MNIST 数据构建影像分类器

在这里,我将演示使用流行的 MNIST 数据集构建手写数字分类器的过程。

这项任务对于玩神经网络来说是一个很大的挑战,但它可以在单台计算机上管理。

MNIST 数据库包含 60,000 幅训练图像和 10,000 幅测试图像。

首先导入 Numpy 并为计算机的伪随机数发生器设置一个种子。这允许您从脚本中重现结果。

import numpy as np
# random seed for reproducibility
np.random.seed(123)

接下来,从 Keras 导入顺序模型类型。这只是神经网络层的线性堆栈。

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers import Conv2D
from keras.layers import MaxPooling2d
#Now we will import some utilities
from keras.utils import np_utils
#Fixed dimension ordering issue
from keras import backend as K
K.set_image_dim_ordering('th')

#Load image data from MNIST

#Load pre-shuffled MNIST data into train and test sets
(X_train,y_train),(X_test, y_test)=mnist.load_data()

#Preprocess imput data for Keras

# Reshape input data.
# reshape to be [samples][channels][width][height]
X_train=X_train.reshape(X_train.shape[0],1,28,28)
X_test=X_test.reshape(X_test.shape[0],1,28,28)
# to convert our data type to float32 and normalize our database
X_train=X_train.astype('float32')
X_test=X_test.astype('float32')
print(X_train.shape)

# Z-scoring or Gaussian Normalization
X_train=X_train - np.mean(X_train) / X_train.std()
X_test=X_test – np.mean(X_test) / X_test.std()
#(60000, 1, 28, 28)

# convert 1-dim class arrays to 10 dim class metrices
#one hot encoding outputs
y_train=np_utils.to_categorical(y_train)
y_test-np_utils.to_categorical(y_test)
num_classes=y_test.shape[1]
print(num_classes)
#10

#Define a simple CNN model
print(X_train.shape)
#(60000,1,28,28)

定义网络结构

网络结构如下:

  • 网络有一个卷积输入层,有 32 个大小为 5×5 的特征图。激活函数是整流线性单位。
  • 最大池层的大小为 2×2。
  • 辍学率设定为 30%。
  • 您可以展平图层。
  • 该网络具有 240 个单元的全连接层,并且激活函数是指数线性单元。
  • 网络的最后一层是具有 10 个单元的全连接输出层,激活函数是 softmax。

然后,使用二元交叉熵作为损失函数,使用 adagrad 作为优化器来编译模型。

定义模型架构

该架构由卷积层和最大池化层以及最后的密集层组成。

# create a model

     model=Sequential()
     model.add(Conv2D(32, (5,5), input_shape=(1,28,28), activation="relu"))
     model.add(MaxPooling2D(pool_size=(2,2)))
     model.add(Dropout(0.3))      # Dropout, one form of regularization
     model.add(Flatten())
     model.add(Dense(240,activation='elu'))
     model.add(Dense(num_classes, activation="softmax"))
     print(model.output_shape)
     (None, 10)

# Compile the model

model.compile(loss='binary_crossentropy', optimizer="adagrad", matrices=['accuracy'])

然后,通过采用 200 的批量大小,使用训练数据集来拟合模型。该模型从训练数据集中取出前 200 个实例/行(从第 1 个到第 200 个),并训练网络。然后,该模型再次取第二个 200 个实例(从第 201 个到第 400 个)用于训练网络。这样,您可以通过网络传播所有实例。该模型需要较少的内存,因为每次训练的网络实例较少。但是小批量不能很好地估计梯度,因此调整重量和偏差是一个挑战。

一个时期意味着所有训练样本的一次向前传递和一次向后传递。完成一个历元需要多次迭代。

这里,你有 60,000 个训练样本,你的批量是 200 个,那么完成 1 个历元需要 300 次迭代。

# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=1, batch_size=200)

# Evaluate model on test data

     # Final evaluation of the model
     scores =model.evaluate(X_test, y_test, verbose=0)
     print("CNN error: % .2f%%" % (100-scores[1]*100))
     # CNN Error: 17.98%

     # Save the model
     # save model
     model_json= model.to_join()
     with open("model_json", "w") as json_file:
     json_file.write(model_json)
     # serialize weights to HDFS
     model.save_weights("model.h5")

利用 CIFAR-10 数据构建图像分类器

本节解释了如何使用 Keras CNN 模型构建一个分类器来对 CIFAR-10 数据集的 10 个标签进行分类。

Note

CIFAR-10 数据集由 10 类 60,000 幅 32×32 彩色图像组成,每类 6,000 幅图像。有 50,000 个训练图像和 10,000 个测试图像。

###########Building CNN Model with CIFAR10 data###################
# plot cifar10 instances
     from keras.datasets import cifar10
     from matplotlib import pyplot
     from scipy.misc import toimage
     import numpy
     from keras.models import Sequential
     from keras.layers import Dense
     from keras.layers import Dropout
     from keras.layers import Flatten
     from keras.layers import Conv2D
     from keras.layers import MaxPooling2d
     #Now we will import some utilities
     from keras.utils import np_utils
     from keras.layers.normalization import BatchNormalization

     #Fixed dimension ordering issue
     from keras import backend as K
     K.set_image_dim_ordering('th')

     # fix random seed for reproducibility
     seed=12
     numpy.random.seed(seed)
     #Preprocess imput data for Keras

     # Reshape input data.
     # reshape to be [samples][channels][width][height]
     X_train=X_train.reshape(X_train.shape[0],3,32,32).astype('float32')
     X_test=X_test.reshape(X_test.shape[0],3,32,32).astype('float32')

     # Z-scoring or Gaussian Normalization
     X_train=X_train - np.mean(X_train) / X_train.std()
     X_test=X_test – np.mean(X_test) / X_test.std()

     # convert 1-dim class arrays to 10 dim class metrices
     #one hot encoding outputs
     y_train=np_utils.to_categorical(y_train)
     y_test-np_utils.to_categorical(y_test)
     num_classes=y_test.shape[1]
     print(num_classes)
     #10

     #Define a simple CNN model
     print(X_train.shape)
     #(50000,3,32,32)

定义网络结构

网络结构如下:

  • 卷积输入层有 32 个大小为 5×5 的特征映射,激活函数是一个校正的线性单元。
  • 最大池层的大小为 2×2。
  • 卷积层有 32 个大小为 5×5 的特征图,激活函数是一个校正的线性单元。
  • 网络有批量归一化。
  • 最大池层的大小为 2×2。
  • 辍学率设定为 30%。
  • 您可以展平图层。
  • 全连接层有 240 个单元,激活函数是指数线性单元。
  • 全连接输出层有十个单元,激活函数是 softmax。

然后,通过采用 200 的批量大小,使用训练数据集来拟合模型。从训练数据集中取出前 200 个实例/行(从第 1 个到第 200 个)来训练网络。然后你取第二个 200 个实例(从第 201 个到第 400 个)再次训练网络。这样,您可以通过网络传播所有实例。一个时期意味着所有训练样本的一次向前传递和一次向后传递。完成一个历元需要多次迭代。

这里,你有 50,000 个训练样本,你的批量是 200 个,那么完成 1 个历元需要 250 次迭代。

定义模型架构

使用卷积层和最大池层的组合创建顺序模型。随后,附着完全连接的致密层。

# create a model

     model=Sequential()
     model.add(Conv2D(32, (5,5), input_shape=(3,32,32), activation="relu"))
     model.add(MaxPooling2D(pool_size=(2,2)))
     model.add(Conv2D(32, (5,5), activation="relu", padding="same"))
     model.add(BatchNormalization())
     model.add(MaxPooling2D(pool_size=(2,2)))
     model.add(Dropout(0.3))      # Dropout, one form of regularization
     model.add(Flatten())
     model.add(Dense(240,activation='elu'))
     model.add(Dense(num_classes, activation="softmax"))
     print(model.output_shape)
     model.compile(loss='binary_crossentropy', optimizer="adagrad")
     # fit model
     model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=1, batch_size=200)

     # Final evaluation of the model
     scores =model.evaluate(X_test, y_test, verbose=0)
     print("CNN error: % .2f%%" % (100-scores[1]*100

预训练模型

在这一部分,我将展示如何使用预训练的模型,如 VGG 和 inception,来构建一个分类器。

A456157_1_En_8_Figb_HTML.gif

A456157_1_En_8_Figa_HTML.gif

Inception-V3 预训练模型可以检测/分类 22,000 个类别的对象。它可以检测/分类托盘,手电筒,雨伞和其他。

在许多场景中,我们需要根据自己需求构建分类器。为此,在我们使用预训练模型(用于特征提取)和多个神经网络的情况下,使用迁移学习。

九、RNN 和 LSTM

本章将讨论循环神经网络(RNNs)的概念及其修改版本,长短期记忆(LSTM)。LSTM 主要用于序列预测。您将了解各种序列预测,然后学习如何借助 LSTM 模型进行时间序列预测。

RNNs 的概念

循环神经网络是一种人工神经网络,最适合于识别数据序列中的模式,如文本、视频、语音、语言、基因组和时序数据。RNN 是一种非常强大的算法,可以对数据进行分类、聚类和预测,尤其是时间序列和文本。

RNN 可以看作是一个 MLP 网络,只是在体系结构上增加了环路。在图 9-1 中,可以看到有一个输入层(节点为 x1、x2 等)、一个隐藏层(节点为 h1、h2 等)、一个输出层(节点为 y1、y2 等)。这类似于 MLP 的建筑。不同之处在于隐藏层的节点是相互连接的。在普通(基本)RNN/LSTM 中,节点单向连接。这意味着 h2 依赖于 h1(和 x2),h3 依赖于 h2(和 x3)。隐藏层中的节点由隐藏层中的前一个节点决定。

A456157_1_En_9_Fig1_HTML.jpg

图 9-1

An RNN

这种架构确保 t=n 时的输出取决于 t=n、t=n-1、…、t=1 时的输入。换句话说,输出取决于数据的顺序而不是单个数据(图 9-2 )。

A456157_1_En_9_Fig2_HTML.gif

图 9-2

The sequence

图 9-3 显示了隐藏层的节点如何连接到输入层的节点。

A456157_1_En_9_Fig3_HTML.gif

图 9-3

The connections

在 RNN 中,如果序列很长,则在训练(反向传播)期间计算梯度(这对调整权重和偏差很重要)。它们要么消失(许多小于 1 的小值相乘),要么爆炸(许多大于 1 的大值相乘),导致模型训练非常缓慢。

LSTM 的概念

长短期记忆是一种改进的 RNN 体系结构,它解决了消失和爆炸梯度的问题,并解决了长序列训练和保持记忆的问题。所有的 rnn 在循环层都有反馈回路。反馈回路有助于将信息长时间保存在“记忆”中。但是,很难训练标准的 rnn 来解决需要学习长期时间依赖性的问题。由于损失函数的梯度随时间呈指数衰减(这种现象称为消失梯度问题),因此很难训练典型的 rnn。这就是为什么 RNN 被修改为包括一个可以在存储器中长时间保存信息的存储单元。改良后的 RNN 更为人所知的名字是 LSTM。在 LSTM,一组门用于控制信息何时进入内存,这解决了消失或爆炸梯度问题。

循环连接给网络增加了状态或记忆,并允许它学习和利用输入序列中观察值的有序性质。内部存储器意味着网络的输出取决于输入序列中的最近上下文,而不是刚刚作为网络输入呈现的内容。

LSTM 模式

LSTM 可以有以下模式之一:

  • 一对一模型
  • 一对多模型
  • 多对一模型
  • 多对多模型

除了这些模式之外,同步的多对多模型也正在被使用,尤其是对于视频分类。

图 9-4 显示了多对一的 LSTM。这意味着在这个模型中许多输入产生一个输出。

A456157_1_En_9_Fig4_HTML.jpg

图 9-4

Many-to-one LSTM

序列预测

LSTM 最适合序列数据。LSTM 可以预测、分类和生成序列数据。序列意味着一个观察顺序,而不是一组观察。序列的一个例子是测试系列,其中时间戳和值按照序列的顺序(按时间顺序)排列。另一个例子是视频,它可以被认为是图像序列或音频剪辑序列。

基于数据序列的预测称为序列预测。序列预测据说有四种类型。

  • 序列数值预测
  • 序列分类
  • 序列生成
  • 序列间预测

序列数值预测

序列数值预测是预测给定序列的下一个值。它的用例是股票市场预测和天气预报。这里有一个例子:

A456157_1_En_9_Figa_HTML.gif

  • 输入顺序:3,5,8,12
  • 产量:17

序列分类

序列分类预测给定序列的类别标签。其用例是欺诈检测(使用交易序列作为输入来分类/预测账户是否被黑客攻击)和基于表现的学生分类(按时间顺序排列的过去六个月的考试分数序列)。这里有一个例子:

A456157_1_En_9_Figb_HTML.gif

  • 输入顺序:2,4,6,8
  • 产出:“增加”

序列生成

序列生成是指生成一个新的输出序列,它与输入语料库中的输入序列具有相同的属性。它的用例是文本生成(给定博客的 100 行,生成博客的下一行)和音乐生成(给定音乐示例,生成新的音乐作品)。这里有一个例子:

A456157_1_En_9_Figc_HTML.gif

  • 输入序列:[3,5,8,12],[4,6,9,13]
  • 输出:[5,7,10,14]

序列间预测

序列间预测是指预测给定序列的下一个序列。它的用例是文档摘要和多步时间序列预测(预测一个数字序列)。这里有一个例子:

A456157_1_En_9_Figd_HTML.gif

  • 输入顺序:[3,5,8,12,17]
  • 输出:[23,30,38]

如前所述,LSTM 用于商业中的时间序列预测。

让我们来看一个 LSTM 模型。假设给出了一个 CSV 文件,其中第一列是时间戳,第二列是值。它可以表示传感器(IoT)数据。

给定时间序列数据,你必须预测未来的值。

用 LSTM 模型进行时间序列预测

以下是 LSTM 时间序列预测的完整示例:

# Simple LSTM for a time series data
import numpy as np
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
import pylab

# convert an array of values into a timeseries data
def create_timeseries(series, ts_lag=1):
    dataX = []
    dataY = []
    n_rows = len(series)-ts_lag
    for i in range(n_rows-1):
        a = series[i:(i+ts_lag), 0]
        dataX.append(a)
        dataY.append(series[i + ts_lag, 0])

    X, Y = np.array(dataX), np.array(dataY)
    return X, Y
# fix random seed for reproducibility
np.random.seed(230)
# load dataset
dataframe = read_csv('sp500.csv', usecols=[0])
plt.plot(dataframe)
plt.show()

图 9-5 显示了数据的曲线图。

A456157_1_En_9_Fig5_HTML.jpg

图 9-5

Plot of the data

下面是更多的代码:

# Changing datatype to float32 type
series = dataframe.values.astype('float32')

# Normalize the dataset
scaler = StandardScaler()
series = scaler.fit_transform(series)

# split the datasets into train and test sets
train_size = int(len(series) * 0.75)
test_size = len(series) - train_size
train, test = series[0:train_size,:], series[train_size:len(series),:]

# reshape the train and test dataset into X=t and Y=t+1
ts_lag = 1
trainX, trainY = create_timeseries(train, ts_lag)
testX, testY = create_timeseries(test, ts_lag)

# reshape input data to be [samples, time steps, features]
trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1]))

# Define the LSTM model
model = Sequential()
model.add(LSTM(10, input_shape=(1, ts_lag)))
model.add(Dense(1))
model.compile(loss='mean_squared_logarithmic_error', optimizer="adagrad")

# fit the model
model.fit(trainX, trainY, epochs=500, batch_size=30)
# make predictions
trainPredict = model.predict(trainX)
testPredict = model.predict(testX)

# rescale predicted values
trainPredict = scaler.inverse_transform(trainPredict)
trainY = scaler.inverse_transform([trainY])
testPredict = scaler.inverse_transform(testPredict)
testY = scaler.inverse_transform([testY])

# calculate root mean squared error
trainScore = math.sqrt(mean_squared_error(trainY[0], trainPredict[:,0]))
print('Train Score: %.2f RMSE' % (trainScore))
testScore = math.sqrt(mean_squared_error(testY[0], testPredict[:,0]))
print('Test Score: %.2f RMSE' % (testScore))

# plot baseline and predictions
pylab.plot(trainPredictPlot)
pylab.plot(testPredictPlot)
pylab.show()

在图 9-6 中,您可以看到实际时间序列与预测时间序列的关系图。橙色部分是训练数据,蓝色部分是测试数据,绿色部分是预测输出。

A456157_1_En_9_Fig6_HTML.jpg

图 9-6

Plot of actual versus predicted time series

到目前为止,我们已经学习了 RNN、LSTM 和 LSTM 模型时间序列预测的概念。

LSTM 已被用于文本分类。我们使用 LSTM(香草 LSTM 或双向 LSTM)来构建文本分类器。首先,通过使用 word2vec 或 glove 等单词(语义)嵌入将文本语料库转换为数字。然后,通过 LSTM 进行序列分类。这种方法提供了比典型的单词包或 tf-idf 后跟 ML 分类器(如 SVM、随机森林)更高的准确性。在第十一章中,我们可以看到 LSTM 是如何被用作量词的。

十、语音到文本,反之亦然

在本章中,您将了解语音到文本和文本到语音转换的重要性。您还将了解进行这种类型的转换所需的函数和组件。

具体来说,我将介绍以下内容:

  • 为什么你想把语音转换成文本
  • 语音作为数据
  • 将语音映射到矩阵的语音特征
  • 光谱图,将语音映射成图像
  • 利用梅尔倒谱系数(MFCC)特征构建语音识别分类器
  • 通过频谱图建立语音识别的分类器
  • 语音识别的开源方法
  • 流行的认知服务提供商
  • 文本话语的未来

语音到文本转换

语音转文本,通俗地说就是一个 app 识别一个人说的话,把语音转换成文字。有很多原因让你想使用语音到文本的转换。

  • 盲人或残障人士可以仅使用语音控制不同的设备。
  • 您可以通过将口头对话转换为文本记录来保存会议和其他事件的记录。
  • 您可以转换视频和音频文件中的音频,以获得正在朗读的单词的字幕。
  • 通过对着设备用一种语言说话,然后将文本转换成另一种语言的语音,可以将单词翻译成另一种语言。

语音作为数据

制造任何自动语音识别系统的第一步是获取特征。换句话说,你识别出了对识别语言内容有用的音频成分,并删除了所有其他无用的背景噪音。

每个人的语音都被他们声道的形状以及舌头和牙齿过滤。发出什么声音取决于这个形状。为了准确地识别正在产生的音素,你需要准确地确定这个形状。你可以说声道的形状表明它自己形成了短时功率谱的包络。MFCCs 的工作是准确地表示这个包络。

语音也可以通过转换成声谱图来表示为数据(图 10-1 )。

A456157_1_En_10_Fig1_HTML.jpg

图 10-1

Speech as data

语音特征:将语音映射到矩阵

MFCCs 广泛用于自动语音和说话人识别。mel 标度将纯音的感知频率或音高与其实际测量频率相关联。

您可以使用以下公式将音频的频率标度转换为 mel 标度:

 $$ M(f)=1125\kern0.50em \ln \left(1+f/700\right) $$

要将其转换回频率,请使用以下公式:

 $$ {M}^{-1}(m)=700\left(\exp \left(m/1125\right)-1\right) $$

以下是 Python 中提取 MFCC 要素的函数:

def mfcc(signal,samplerate=16000,winlen=0.025,winstep=0.01,numcep=13, nfilt=26,nfft=512,lowfreq=0,highfreq=None,preemph=0.97, ceplifter=22,appendEnergy=True)

这些是使用的参数:

  • signal:这是需要计算 MFCC 特征的信号。应该是 N*1 的数组(读取 WAV 文件)。
  • 这是您正在工作的信号的采样率。
  • winlen:这是以秒为单位的分析窗口长度。默认情况下,它是 0.025 秒。
  • winstep:这是连续的窗口步骤。默认情况下是 0.01 秒。
  • numcep:这是函数应该返回的 ceptrum 的编号。默认情况下,它是 13。
  • nfilt:这是滤波器组中滤波器的数量。默认情况下是 26。
  • nfft:这是快速傅立叶变换(FFT)的大小。默认情况下,它是 512。
  • 这是最低的频带边缘,单位为赫兹。默认情况下,该值为 0。
  • 这是最高频带边缘,单位为赫兹。默认情况下,它是采样速率除以 2。
  • preemph:应用以preemph为系数的预加重滤波器。0 表示没有过滤器。默认情况下,它是 0.97。
  • ceplifter:将提升器应用于最终倒谱系数。0 表示没有升降机。默认情况下是 22。
  • appendEnergy:如果设置为真,则第零倒谱系数被替换为总帧能量的对数。

这个函数返回一个包含特性的 Numpy 数组。每行包含一个特征向量。

频谱图:将语音映射到图像

光谱图是光谱的照片或电子图像。这个想法是将音频文件转换成图像,并将图像传递到深度学习模型,如 CNN 和 LSTM,以进行分析和分类。

频谱图被计算为窗口数据段的 FFT 序列。一种常见的格式是具有两个几何维度的图形;一个轴代表时间,另一个轴代表频率。第三维度使用点的颜色或大小来表示特定时间特定频率的振幅。光谱图通常用两种方法之一制作。它们可以近似为由一系列带通滤波器产生的滤波器组。或者,在 Python 中,有一个将音频映射到声谱图的直接函数。

利用 MFCC 特征构建语音识别分类器

要构建语音识别的分类器,您需要安装 python_speech_features Python 包。

您可以使用命令pip install python_speech_features来安装这个包。

mfcc函数为音频文件创建一个特征矩阵。为了建立一个识别不同人声音的分类器,你需要以 WAV 格式收集他们的语音数据。然后使用mfcc函数将所有音频文件转换成一个矩阵。从 WAV 文件中提取特征的代码如下所示:

A456157_1_En_10_Figa_HTML.jpg

如果您运行前面的代码,您将获得以下形式的输出:

[[ 7.66608682  7.04137131  7.30715423 ...,  9.43362359  9.11932984
   9.93454603]
 [ 4.9474559   4.97057377  6.90352236 ...,  8.6771281   8.86454547
   9.7975147 ]
 [ 7.4795622   6.63821063  5.98854983 ...,  8.78622734  8.805521
   9.83712966]
 ...,
 [ 7.8886269   6.57456605  6.47895433 ...,  8.62870034  8.79965464
   9.67997298]
 [ 5.73028657  4.87985847  6.64977329 ...,  8.64089442  8.62887745
   9.90470194]
 [ 8.8449656   6.67098127  7.09752316 ...,  8.84914694  8.97807983
   9.45123015]]

这里,每一行代表一个特征向量。

尽可能多地收集一个人的录音,并在这个矩阵中附加每个音频文件的特征矩阵。

这将作为您的训练数据集。

对所有其他类重复相同的步骤。

一旦数据集准备好,你就可以将这些数据放入任何深度学习模型(用于分类)中,对不同人的声音进行分类。

Note

要查看使用 MFCC 功能的分类器的完整代码,您可以访问 www.navinmanaswi.com/SpeechRecognizer

通过声谱图建立用于语音识别的分类器

使用声谱图方法将所有音频文件转换为图像(图 10-2 ),因此您所要做的就是将训练数据中的所有声音文件转换为图像,并将这些图像馈送到深度学习模型,就像您在 CNN 中所做的那样。

A456157_1_En_10_Fig2_HTML.jpg

图 10-2

Spectogram of speech sample

下面是将音频文件转换为声谱图的 Python 代码:

A456157_1_En_10_Figb_HTML.jpg

开源方法

Python 有一些开源包可以执行语音到文本和文本到语音的转换。

以下是一些开源的语音到文本转换 API:

  • PocketSphinx
  • 谷歌语音
  • 谷歌云演讲
  • Wit.ai
  • Houndify
  • IBM 语音转文本 API
  • 微软必应语音

在使用了所有这些之后,我可以说它们工作得相当好;美国口音特别清晰。

如果您对评估转换的准确性感兴趣,您需要一个度量:单词错误率(WER)。

在下一节中,我将讨论前面提到的每个 API。

使用每个 API 的示例

让我们看一下每个 API。

使用 PocketSphinx

PocketSphinx 是一个用于语音到文本转换的开源 API。这是一个轻量级的语音识别引擎,专门针对手持和移动设备进行了调整,尽管它在桌面上也同样适用。只需使用命令pip install PocketSphinx安装软件包。

import speech_recognition as sr
from os import path
AUDIO_FILE = "MyAudioFile.wav"

r = sr.Recognizer()
with sr.AudioFile(AUDIO_FILE) as source:
 audio = r.record(source)

try:
   print("Sphinx thinks you said " + r.recognize_sphinx(audio))
except sr.UnknownValueError:
   print("Sphinx could not understand audio")
except sr.RequestError as e:
  print("Sphinx error; {0}".format(e))

===============================================================

使用谷歌语音 API

Google 提供了自己的语音 API,可以用 Python 代码实现,可以用来创建不同的应用。

# recognize speech using Google Speech Recognition
try:
    print("Google Speech Recognition thinks you said " + r.recognize_google(audio))
except sr.UnknownValueError:
    print("Google Speech Recognition could not understand audio")
except sr.RequestError as e:
    print("Could not request results from Google Speech Recognition service;{0}".format(e))

使用谷歌云语音 API

你也可以使用谷歌云语音 API 进行转换。在 Google Cloud 上创建一个帐户并复制凭证。

GOOGLE_CLOUD_SPEECH_CREDENTIALS = r"INSERT THE CONTENTS OF THE GOOGLE CLOUD SPEECH JSON CREDENTIALS FILE HERE" try:     print("Google Cloud Speech thinks you said " + r.recognize_google_cloud(audio, credentials_json=GOOGLE_CLOUD_SPEECH_CREDENTIALS))
except sr.UnknownValueError:
    print("Google Cloud Speech could not understand audio")
except sr.RequestError as e:
    print("Could not request results from Google Cloud Speech service; {0}".format(e))

使用 Wit.ai API

Wit.ai API 使您能够制作语音到文本转换器。您需要创建一个帐户,然后创建一个项目。复制你的 Wit.ai 密钥,开始编码。

#recognize speech using Wit.ai
WIT_AI_KEY = "INSERT WIT.AI API KEY HERE" # Wit.ai keys are 32-character uppercase alphanumeric strings
try:
    print("Wit.ai thinks you said " + r.recognize_wit(audio, key=WIT_AI_KEY))
except sr.UnknownValueError:
    print("Wit.ai could not understand audio")
except sr.RequestError as e:
    print("Could not request results from Wit.ai service; {0}".format(e))

使用 Houndify API

与前面的 API 类似,您需要在 Houndify 创建一个帐户,并获得您的客户机 ID 和密钥。这允许你建立一个对声音有反应的应用程序。

# recognize speech using Houndify
HOUNDIFY_CLIENT_ID = "INSERT HOUNDIFY CLIENT ID HERE" # Houndify client IDs are Base64-encoded strings
HOUNDIFY_CLIENT_KEY = "INSERT HOUNDIFY CLIENT KEY HERE" # Houndify client keys are Base64-encoded strings
try:
    print("Houndify thinks you said " + r.recognize_houndify(audio, client_id=HOUNDIFY_CLIENT_ID, client_key=HOUNDIFY_CLIENT_KEY))
except sr.UnknownValueError:
    print("Houndify could not understand audio")
except sr.RequestError as e:
    print("Could not request results from Houndify service; {0}".format(e))

使用 IBM 语音到文本 API

IBM 语音到文本 API 使您能够将 IBM 的语音识别功能添加到您的应用程序中。登录 IBM cloud 并启动您的项目,获取一个 IBM 用户名和密码。

# IBM Speech to Text
# recognize speech using IBM Speech to Text
IBM_USERNAME = "INSERT IBM SPEECH TO TEXT USERNAME HERE" # IBM Speech to Text usernames are strings of the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
IBM_PASSWORD = "INSERT IBM SPEECH TO TEXT PASSWORD HERE" # IBM Speech to Text passwords are mixed-case alphanumeric strings
try:
    print("IBM Speech to Text thinks you said " + r.recognize_ibm(audio, username=IBM_USERNAME, password=IBM_PASSWORD))
except sr.UnknownValueError:
    print("IBM Speech to Text could not understand audio")
except sr.RequestError as e:
    print("Could not request results from IBM Speech to Text service; {0}".format(e))

使用 Bing 语音识别 API

这个 API 实时识别来自麦克风的音频。在 Bing.com 上创建一个帐户,并获得阿炳语音识别 API 密钥。

# recognize speech using Microsoft Bing Voice Recognition
BING_KEY = "INSERT BING API KEY HERE" # Microsoft Bing Voice Recognition API key is 32-character lowercase hexadecimal strings
try:
    print("Microsoft Bing Voice Recognition thinks you said " + r.recognize_bing(audio, key=BING_KEY))
except sr.UnknownValueError:
    print("Microsoft Bing Voice Recognition could not understand audio")
except sr.RequestError as e:
    print("Could not request results from Microsoft Bing Voice Recognition service; {0}".format(e))

一旦你把演讲转换成文本,你就不能指望百分之百的准确。要测量精确度,可以使用 WER。

文本到语音转换

本章的这一节重点介绍如何将书面文本转换为音频文件。

使用 pyttsx

使用名为 pyttsx 的 Python 包,可以将文本转换成音频。

Do a pip install pyttsx. If you are using python 3.6 then do pip3 install pyttsx3.

import pyttsx
engine = pyttsx.init()
engine.say("Your Message")
engine.runAndWait()

使用 SAPI

在 Python 中,还可以使用 SAPI 进行文本到语音的转换。

from win32com.client import constants, Dispatch
Msg = "Hi this is a test"
speaker = Dispatch("SAPI.SpVoice")  #Create SAPI SpVoice Object
speaker.Speak(Msg)                  #Process TTS
del speaker

使用 SpeechLib

您可以从文本文件中获取输入,并使用 SpeechLib 将其转换为音频,如下所示:

from comtypes.client import CreateObject    
engine = CreateObject("SAPI.SpVoice")
stream = CreateObject("SAPI.SpFileStream")
from comtypes.gen import SpeechLib    
infile = "SHIVA.txt"
outfile = "SHIVA-audio.wav"
stream.Open(outfile, SpeechLib.SSFMCreateForWrite)
engine.AudioOutputStream = stream
f = open(infile, 'r')
theText = f.read()
f.close()
engine.speak(theText)
stream.Close()

很多时候,您必须编辑音频,以便从音频文件中删除声音。下一节将向您展示如何操作。

音频切割代码

制作一个包含音频详细信息的逗号分隔值的音频 CSV 文件,并使用 Python 执行以下操作:

import wave
import sys
import os
import csv
origAudio = wave.open('Howard.wav', 'r') #change path
frameRate = origAudio.getframerate()
nChannels = origAudio.getnchannels()
sampWidth = origAudio.getsampwidth()
nFrames   = origAudio.getnframes()

filename =  'result1.csv' #change path

exampleFile = open(filename)
exampleReader = csv.reader(exampleFile)
exampleData = list(exampleReader)

count = 0

for data in exampleData:
 #for selections in data:
    print('Selections ', data[4], data[5])
    count += 1
    if data[4] == 'startTime' and data[5] == 'endTime':
        print('Start time')
    else:
        start = float(data[4])
        end = float(data[5])
        origAudio.setpos(start*frameRate)
        chunkData = origAudio.readframes(int((end-start)*frameRate))

        outputFilePath = 'C:/Users/Navin/outputFile{0}.wav'.format(count) # change path
        chunkAudio = wave.open(outputFilePath, 'w')
        chunkAudio.setnchannels(nChannels)
        chunkAudio.setsampwidth(sampWidth)
        chunkAudio.setframerate(frameRate)
        chunkAudio.writeframes(chunkData)
        chunkAudio.close()

认知服务提供商

让我们看看一些帮助语音处理的认知服务提供商。

微软 Azure

Microsoft Azure 提供了以下功能:

  • 自定义语音服务:这克服了语音识别的障碍,如说话方式、词汇和背景噪音。
  • Translator Speech API:这支持实时语音翻译。
  • 说话人识别 API:它可以根据给定音频数据中每个说话人的语音样本来识别说话人。
  • Bing 语音 API:它将音频转换为文本,理解意图,并将文本转换回语音,以获得自然的响应。

亚马逊认知服务

亚马逊认知服务(Amazon Cognitive Services)提供亚马逊 Polly,一种将文本转化为语音的服务。Amazon Polly 允许您创建会说话的应用程序,使您能够构建全新类别的支持语音的产品。

  • 可以使用 47 种语音和 24 种语言,并提供印度英语选项。
  • 使用 Amazon effects,可以将耳语、愤怒等音调添加到讲话的特定部分。
  • 您可以指示系统如何以不同的方式发出特定短语或单词的发音。例如,“W3C”读作万维网联盟,但是您可以将其改为只读作缩写。您还可以提供 SSML 格式的输入文本。

IBM 沃森服务

IBM Watson 提供了两种服务。

  • 语音转文本:美国英语、西班牙语和日语
  • 文本到语音转换:美国英语、英国英语、西班牙语、法语、意大利语和德语

语音分析的未来

语音识别技术已经取得了很大的进步。每年,它都比前一年精确 10%到 15%。未来,它将为计算机提供迄今为止最具交互性的界面。

你很快就会在市场上看到许多应用,包括交互式书籍、机器人控制和自动驾驶汽车界面。语音数据提供了一些令人兴奋的新的可能性,因为它是行业的未来。语音智能使人们能够发送信息、接受或下达命令、提出投诉,以及做任何他们过去需要手动输入的工作。它提供了很好的客户体验,也许这就是为什么所有面向客户的部门和企业都倾向于大量使用语音应用程序。我可以预见语音应用开发者的美好未来。

十一、开发聊天机器人

通过文本或语音作为人机交互界面的人工智能系统被称为聊天机器人。

与聊天机器人的交互可能简单,也可能复杂。直接互动的一个例子是询问最新的新闻报道。比如说,在对你的 Android 手机进行故障诊断时,交互会变得更加复杂。聊天机器人这个词在过去的一年里非常流行,已经成为用户互动和参与的最受欢迎的平台。机器人是聊天机器人的高级形式,有助于自动执行“用户执行的”任务。

关于聊天机器人的这一章将作为一个全面的指南,介绍聊天机器人的内容、方式、地点、时间和原因!

具体来说,我将介绍以下内容:

  • 为什么你会想使用聊天机器人
  • 聊天机器人的设计和功能
  • 构建聊天机器人的步骤
  • 使用 API 开发聊天机器人
  • 聊天机器人的最佳实践

为什么是聊天机器人?

对于聊天机器人来说,理解用户在寻找什么信息,也就是所谓的意图,是非常重要的。假设一个用户想知道最近的素食餐馆;用户可以用许多可能的方式来问这个问题。聊天机器人(特别是聊天机器人内部的意图分类器)必须能够理解用户的意图,因为用户想要得到正确的答案。事实上,为了给出正确的答案,聊天机器人必须能够理解上下文、意图、实体和情感。聊天机器人甚至必须考虑会话中讨论的任何内容。例如,用户可能会问这样的问题“那里的鸡肉价格是多少?”尽管用户已经询问了价格,但是聊天引擎可能会误解并认为用户正在寻找一家餐馆。因此,作为响应,聊天机器人可以提供餐馆的名称。

聊天机器人的设计和功能

聊天机器人通过应用人工智能来刺激与人类的智能对话。

对话发生的界面通过口头或书面文本来实现。Facebook Messenger、Slack 和 Telegram 利用聊天机器人消息平台。它们有很多用途,包括网上订购产品、投资理财等等。聊天机器人的一个重要方面是它们使上下文对话成为可能。聊天机器人与用户交谈的方式类似于人类在日常生活中的交谈方式。尽管聊天机器人有可能根据上下文进行对话,但在根据上下文与任何事物进行交流方面,它们还有很长的路要走。但是聊天界面正在利用语言将机器与人连接起来,通过以上下文的方式提供信息,帮助人们以方便的方式完成事情。

此外,聊天机器人正在重新定义企业的经营方式。从接触消费者,到欢迎他们加入商业生态系统,再到向消费者提供各种产品及其功能的信息,聊天机器人都在提供帮助。它们正在成为及时和令人满意地与消费者打交道的最方便的方式。

构建聊天机器人的步骤

聊天机器人是为了与用户交流而构建的,让用户感觉他们是在与人交流,而不是与机器人交流。但是当用户输入时,通常他们不会以正确的方式输入。换句话说,他们可能会输入不必要的标点符号,或者可能会有不同的方式来问同一个问题。

例如,对于“我附近的餐馆?”用户可以输入“我旁边的餐馆?”或者“找一家附近的餐馆。”

因此,您需要对数据进行预处理,以便聊天机器人引擎能够轻松理解它。图 11-1 显示了该过程,这将在以下章节中详细描述。

A456157_1_En_11_Fig1_HTML.jpg

图 11-1

A flowchart to show how a chatbot engine processes an input string and gives a valid reply.

预处理文本和消息

文本和消息的预处理包括几个步骤,下面将介绍。

标记化

将句子分割成单个单词(称为标记)称为标记化。在 Python 中,通常字符串被标记化并存储在列表中。

  • 例如,“人工智能就是应用数学”这句话变成了下面这句话:
  • 【“人工”、“智能”、“是”、“所有”、“关于”、“应用”、“数学”】
  • 以下是示例代码:
from nltk.tokenize import TreebankWordTokenizer
l = "Artificial intelligence is all about applying mathematics"
token = TreebankWordTokenizer().tokenize(l)
print(token)

删除标点符号

也可以去掉句子中不必要的标点符号。

  • 例如,句子“我能得到送货上门的餐馆名单吗?”变成如下:
  • "我能得到送货上门的餐馆名单吗?"
  • 以下是示例代码:
from nltk.tokenize import TreebankWordTokenizer
from nltk.corpus import stopwords
l = "Artificial intelligence is all about applying mathematics!"
token = TreebankWordTokenizer().tokenize(l)
output = []
output = [k for k in token if k.isalpha()]
print(output)

删除停用词

停用词是存在于一个句子中的词,如果去掉,不会有太大的区别。尽管句子的格式改变了,但这对自然语言理解很有帮助(NLU)。

  • 比如那句“人工智能可以改变人民的生活方式。”删除停用词后,变为以下内容:
  • “人工智能改变人们的生活方式。”

以下是示例代码:

from nltk.tokenize import TreebankWordTokenizer
from nltk.corpus import stopwords
l = "Artificial intelligence is all about applying mathematics"
token = TreebankWordTokenizer().tokenize(l)
stop_words = set(stopwords.words('english'))
output= []
for k in token:
    if k not in stop_words:
        output.append(k)
print(output)

哪些词被认为是停用词可以有所不同。自然语言工具包(NLTK)、Google 等提供了一些预定义的停用词集。

命名实体识别

命名实体识别(NER),也称为实体识别,是将文本中的实体分类到预定义的类别(如国家名称、人名等)中的任务。您也可以定义自己的类。

  • 例如,将 NER 应用于句子“今天的印度对澳大利亚板球比赛棒极了。”为您提供以下输出:
  • [今天的]时间[印度]国家对[澳大利亚]国家[板球]比赛太精彩了。

要运行 NER 的代码,您需要下载并导入必要的包,如下面的代码所示。

使用斯坦福 NER

要运行代码,下载english.all.3class.distsim.crf.ser.gzstanford-ner.jar文件。

from nltk.tag import StanfordNERTagger
from nltk.tokenize import word_tokenize

StanfordNERTagger("stanford-ner/classifiers/english.all.3class.distsim.crf.ser.gz",
"stanford-ner/stanford-ner.jar")

text = "Ron was the founder of Ron Institute at New york"
text = word_tokenize(text)
ner_tags = ner_tagger.tag(text)

print(ner_tags)

使用米蒂 NER(预训练)

下载 MITIE 的ner_model.dat文件运行代码。

from mitie.mitie import *
from nltk.tokenize import word_tokenize

print("loading NER model...")
ner = named_entity_extractor("mitie/MITIE-models/english/ner_model.dat".encode("utf8"))

text = "Ron was the founder of Ron Institute at New york".encode("utf-8")
text = word_tokenize(text)

ner_tags = ner.extract_entities(text)
print("\nEntities found:", ner_tags)

for e in ner_tags:
       range = e[0]
       tag = e[1]
       entity_text = " ".join(text[i].decode() for i in range)

       print( str(tag) + " : " + entity_text)

使用米铁 NER(自学)

下载米铁( https://github.com/mit-nlp/MITIE )的total_word_feature_extractor.dat文件运行代码。

from mitie.mitie import *

sample = ner_training_instance([b"Ron", b"was", b"the", b"founder", b"of", b"Ron", b"Institute", b"at", b"New", b"York", b"."])

sample.add_entity(range(0, 1), "person".encode("utf-8"))
sample.add_entity(range(5, 7), "organization".encode("utf-8"))
sample.add_entity(range(8, 10), "Location".encode("utf-8"))

trainer = ner_trainer("mitie/MITIE-models/english/total_word_feature_extractor.dat".encode("utf-8"))

trainer.add(sample)

ner = trainer.train()

tokens = [b"John", b"was", b"the", b"founder", b"of", b"John", b"University", b"."]
entities = ner.extract_entities(tokens)
print ("\nEntities found:", entities)
for e in entities:
      range = e[0]
      tag = e[1]
      entity_text = " ".join(str(tokens[i]) for i in range)

      print ("    " + str(tag) + ": " + entity_text)

意图分类

意图分类是 NLU 的一个步骤,在这里你试图理解用户想要什么。以下是聊天机器人查找附近地点的两个输入示例:

  • "我需要买些杂货。":目的是寻找附近的杂货店。
  • “我想吃素食。”:目的是寻找附近的餐馆,最好是素食餐馆。

基本上,你需要理解用户在寻找什么,并相应地将请求归类到特定的意图类别中(图 11-2 )。

A456157_1_En_11_Fig2_HTML.jpg

图 11-2

General flow of intent classification, from sentences to vectors to a model

要做到这一点,你需要训练一个模型来使用算法将请求分类成意图,从句子到向量再到模型。

单词嵌入

单词嵌入是将文本转换成数字的技术。在文本中很难应用任何算法。因此,你必须把它转换成数字。

以下是不同类型的单词嵌入技术。

计数向量

假设您有三个文档(D1、D2 和 D3 ),文档组中有 N 个唯一的单词。您创建了一个(D×N)矩阵,称为 C,这就是众所周知的计数向量。矩阵的每个条目都是该文档中唯一单词的频率。

  • 让我们看一个例子。
  • D1: Pooja 非常懒。
  • D2:但是她很聪明。
  • 她几乎不来上课。

这里,D=3,N=12。

独特的词很难,懒惰,但,Pooja,她,聪明,来,非常,类,是。

因此,计数向量 C 将如下:

|   | 几乎不 | 懒惰的 | 但是 | 到 | 礼拜 | 她 | 聪明的 | 来 | 很 | 班级 | 存在 | | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | | D1 | Zero | one | Zero | Zero | one | Zero | Zero | Zero | one | Zero | one | | D2 | Zero | Zero | one | Zero | Zero | one | one | Zero | Zero | Zero | one | | D3 | one | Zero | Zero | one | Zero | one | Zero | one | Zero | one | Zero |
术语频率-逆文档频率(TF-IDF)

对于这种技术,根据单词在句子中出现的次数以及文档,为句子中的每个单词指定一个数字。在句子中出现多次而在文档中不出现多次的单词将具有高值。

例如,考虑一组句子:

  • “我是男生。”
  • “我是女生。”
  • “你住在哪里?”

TF-IDF 转换前面句子的特征集,如下所示:

|   | 是 | 男孩 | 女孩 | 在哪里 | 做 | 你们 | 活着 | | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | | 1. | Zero point six | Zero point eight | Zero | Zero | Zero | Zero | Zero | | 2. | Zero point six | Zero | Zero point eight | Zero | Zero | Zero | Zero | | 3. | Zero | Zero | Zero | Zero point five | Zero point five | Zero point five | Zero point five |

您可以导入 TFIDF 包并使用它来创建此表。

现在让我们看一些样本代码。您可以在请求字符串的 TF-IDF 转换特征上使用支持向量分类器。

#import required packages
import pandas as pd
from random import sample
from sklearn.preprocessing import LabelEncoder
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score, accuracy_score
# read csv file
data = pd.read_csv("intent1.csv")
print(data.sample(6))

在继续编写代码之前,这里有一个数据集示例:

| 描述(消息) | 意图 _ 标签(目标) | | :-- | :-- | | 我附近有一家不错的非蔬菜餐馆 | Zero | | 我正在找医院 | one | | 心脏手术的好医院 | one | | 国际儿童学校 | Two | | 我周围的非素食餐馆 | Zero | | 小孩子的学校 | Two |

在本例中,这些是要使用的值:

  • 0 表示寻找餐厅。
  • 1 表示找医院。
  • 2 表示找学校。

现在让我们处理数据集。

# split dataset into train and test.
X_train, X_test, Y_train, Y_test = train_test_split(data["Description"], data["intent_label"], test_size=3)
print(X_train.shape, X_test.shape, Y_train.shape, Y_test.shape)

# vectorize the input using tfidf values.
tfidf = TfidfVectorizer()
tfidf = tfidf.fit(X_train)
X_train = tfidf.transform(X_train)
X_test = tfidf.transform(X_test)

# label encoding for different categories of intents
le = LabelEncoder().fit(Y_train)
Y_train = le.transform(Y_train)
Y_test = le.transform(Y_test)

# other models like GBM, Random Forest may also be used

model = SVC()
model = model.fit(X_train, Y_train)
p = model.predict(X_test)
# calculate the f1_score. average="micro" since we want to calculate score for multiclass.
# Each instance(rather than class(search for macro average)) contribute equally towards the scoring.
print("f1_score:", f1_score( Y_test, p, average="micro"))
print("accuracy_score:",accuracy_score(Y_test, p))

Word2Vec

有不同的方法来获得一个句子的单词向量,但是所有技术背后的主要理论是给相似的单词一个相似的向量表示。所以,像男人,男孩和女孩这样的词会有相似的向量。可以设置每个向量的长度。Word2vec 技术的例子包括 GloVe 和 CBOW(有或没有 skip grams 的 n-gram)。

您可以通过为自己的数据集训练 Word2vec 来使用它(如果您有足够的数据来解决问题),或者您可以使用预训练的数据。Word2vec 在网上有售。经过预训练的模型已经在维基百科数据、推文等大型文档上接受了训练,它们几乎总是对问题有好处。

可以用来训练意图分类器的一些技术的一个例子是,对句子中的单词的单词向量使用 1D-CNN,附加在每个句子的列表中。

# import required packages
from gensim.models import Word2Vec
import pandas as pd
import numpy as np
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils.np_utils import to_categorical
from keras.layers import Dense, Input, Flatten
from keras.layers import Conv1D, MaxPooling1D, Embedding, Dropout
from keras.models import Model

from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score, accuracy_score
# read data
data = pd.read_csv("intent1.csv")

# split data into test and train
X_train, X_test, Y_train, Y_test = train_test_split(data["Description"], data["intent_label"], test_size=6)

# label encoding for different categories of intents
le = LabelEncoder().fit(Y_train)
Y_train = le.transform(Y_train)
Y_test = le.transform(Y_test)

# get word_vectors for words in training set
X_train = [sent for sent in X_train]
X_test = [sent for sent in X_test]
# by default genism.Word2Vec uses CBOW, to train word vecs. We can also use skipgram with it
# by setting the "sg" attribute to number of skips we want.
# CBOW and Skip gram for the sentence "Hi Ron how was your day?" becomes:
# Continuos bag of words: 3-grams {"Hi Ron how", "Ron how was", "how was your" ...}
# Skip-gram 1-skip 3-grams: {"Hi Ron how", "Hi Ron was", "Hi how was", "Ron how
# your", ...}

# See how: "Hi Ron was" skips over "how".
# Skip-gram 2-skip 3-grams: {"Hi Ron how", "Hi Ron was", "Hi Ron your", "Hi was
# your", ...}
# See how: "Hi Ron your" skips over "how was".
# Those are the general meaning of CBOW and skip gram.              
word_vecs = Word2Vec(X_train)
print("Word vectors trained")

# prune each sentence to maximum of 20 words.
max_sent_len = 20

# tokenize input strings
tokenizer = Tokenizer()
tokenizer.fit_on_texts(X_train)
sequences = tokenizer.texts_to_sequences(X_train)
sequences_test = tokenizer.texts_to_sequences(X_test)
word_index = tokenizer.word_index
vocab_size = len(word_index)

# sentences with less than 20 words, will be padded with zeroes to make it of length 20
# sentences with more than 20 words, will be pruned to 20.
x = pad_sequences(sequences, maxlen=max_sent_len)
X_test = pad_sequences(sequences_test, maxlen=max_sent_len)

# 100 is the size of wordvec.
embedding_matrix = np.zeros((vocab_size + 1, 100))

# make matrix of each word with its word_vectors for the CNN model.
# so each row of a matrix will represent one word. There will be a row for each word in
# the training set

for word, i in word_index.items():
        try:
            embedding_vector = word_vecs[word]
        except:
            embedding_vector = None
            if embedding_vector is not None:
                embedding_matrix[i] = embedding_vector
print("Embeddings done")
vocab_size = len(embedding_matrix)

# CNN model requires multiclass labels to be converted into one hot ecoding.
# i.e. each column represents a label, and will be marked one for corresponding label.
y = to_categorical(np.asarray(Y_train))

embedding_layer = Embedding(vocab_size,
                                100,
                                weights=[embedding_matrix],
                                input_length=max_sent_len,
                                trainable=True)
sequence_input = Input(shape=(max_sent_len,), dtype="int32")

# stack each word of a sentence in a matrix. So each matrix represents a sentence.
# Each row in a matrix is a word(Word Vector) of a sentence.
embedded_sequences = embedding_layer(sequence_input)

# build the Convolutional model.
l_cov1 = Conv1D(128, 4, activation="relu")(embedded_sequences)
l_pool1 = MaxPooling1D(4)(l_cov1)
l_flat = Flatten()(l_pool1)
hidden = Dense(100, activation="relu")(l_flat)
preds = Dense(len(y[0]), activation="softmax")(hidden)
model = Model(sequence_input, preds)
model.compile(loss='binary_crossentropy',optimizer='Adam')

print("model fitting - simplified convolutional neural network")
model.summary()

# train the model
model.fit(x, y, epochs=10, batch_size=128)

#get scores and predictions.
p = model.predict(X_test)
p = [np.argmax(i) for i in p]
score_cnn = f1_score(Y_test, p, average="micro")
print("accuracy_score:",accuracy_score(Y_test, p))
print("f1_score:", score_cnn)

模型拟合是一个简化的卷积神经网络,如下所示:

| 层(类型) | 输出形状 | 参数# | | :-- | :-- | :-- | | 输入 _20(输入层) | (无,20) | Zero | | 嵌入 _20(嵌入) | (无,20,100) | Two thousand eight hundred | | conv1d_19 (Conv1D) | (无,17,128) | Fifty-one thousand three hundred and twenty-eight | | max_pooling1d_19(最大池) | (无,4,128) | Zero | | 扁平化 _19(扁平化) | (无,512) | Zero | | 密集 _35(密集) | (无,100) | Fifty-one thousand three hundred | | 密集 _36(密集) | (无,3) | Three hundred and three |

以下是参数的数量:

  • 总参数:105731
  • 可训练参数:105,731
  • 不可训练的参数:0

下面是使用 Gensim 包的 Word2vec 的一些重要功能:

  • 这就是你如何导入 Gensim 并加载预训练模型:

    import genism
    #loading the pre-trained model
    model = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
    
    

    这是谷歌为英语语言提供的预训练模型,它有 300 个维度。

  • 这是如何从一个预先训练好的模型中找到一个单词的单词向量:

    # getting word vectors of a word
    lion = model['lion']
    print(len(lion))
    
    
  • 这是如何找到两个词之间的相似指数:

    #Calculating similarity index
    print(model.similarity('King', 'Queen'))
    
    
  • 这就是如何从一组单词中找出一个奇怪的单词:

    #Choose odd one out
    print(model.doesnt_match("Mango Grape Tiger Banana Strawberry".split()))
    
    
  • 这是如何找到最相似的单词:

    print(model.most_similar(positive=[Prince, Girl], negative=[Boy]))
    
    

    word 2 vec 的一个独特的特点是,你可以得到向量,从其他向量使用向量运算。例如,“王子”的向量减去“男孩”的向量加上“女孩”的向量将几乎等于“公主”的向量。因此,当你计算这个的时候,你会得到一个“公主”的向量

    Vec ("Prince") – Vec("boy") + Vec("girl") ≈ Vec("Princess")
    
    

    这只是一个例子。这种情况在许多其他情况下都是有效的。这是 Word2vec 的一个特点,在估计相似词、下一个词、自然语言生成(NLG)等方面非常有用。

表 11-1 显示了其他参数的预训练模型。

表 11-1

Different Pretrained Models with Other Parameters

| 模型文件 | 维度数量 | 语料库规模 | 词汇量 | 体系结构 | 上下文窗口大小 | 作者 | | :-- | :-- | :-- | :-- | :-- | :-- | :-- | | 谷歌新闻 | Three hundred | 100B | 3M | Word2Vec | 弓,~5 | 谷歌 | | 免费基本 id | One thousand | 100B | 1.4 米 | Word2Vec,Skip-gram | 弓,~10 | 谷歌 | | 免费基础名称 | One thousand | 100B | 1.4 米 | Word2Vec,Skip-gram | 弓,~10 | 谷歌 | | 维基百科+ Gigaword 5 | Fifty | 6B | Four hundred thousand | 手套 | 10+10 | 手套 | | 维基百科+ Gigaword 5 | One hundred | 6B | Four hundred thousand | 手套 | 10+10 | 手套 | | 维基百科+ Gigaword 5 | Two hundred | 6B | Four hundred thousand | 手套 | 10+10 | 手套 | | 维基百科+ Gigaword 5 | Three hundred | 6B | Four hundred thousand | 手套 | 10+10 | 手套 | | 普通爬行器 42B | Three hundred | 42B | 1.9 米 | 手套 | 阿达格拉德 | 手套 | | 公共爬行器 840B | Three hundred | 840B | 2.2 米 | 手套 | 阿达格拉德 | 手套 | | 维基百科依赖性 | Three hundred | - | One hundred and seventy-four thousand | Word2Vec | 句法依赖 | 利维-戈德堡公司 | | DBPedia 载体(wiki2vec) | One thousand | - | - | Word2Vec | 弓,10 | 白痴 |

构建响应

回复是聊天机器人的另一个重要部分。根据聊天机器人的回答,用户可能会被它吸引。无论何时制造聊天机器人,都应该记住一件事,那就是它的用户。你需要知道谁将使用它,以及它将用于什么目的。例如,一个餐馆网站的聊天机器人将只被询问餐馆和食物。所以,你或多或少知道会被问到什么问题。因此,对于每个意图,您存储多个答案,这些答案可以在识别意图后使用,这样用户就不会重复得到相同的答案。对于任何断章取义的问题,你也可以有一个意图;该意图可以有多个答案,并且随机选择,聊天机器人可以回复。

例如,如果意图是“你好”,你可以有多个回复,如“你好!你好吗?”和“你好!你过得怎么样?”和“嗨!有什么可以帮你的吗?”

聊天机器人可以随机选择任何一个来回答。

在下面的示例代码中,您从用户那里获取输入,但是在最初的聊天机器人中,意图是由聊天机器人根据用户提出的任何问题来定义的。

import random
intent = input()
output = ["Hello! How are you","Hello! How are you doing","Hii! How can I help you","Hey! There","Hiiii","Hello! How can I assist you?","Hey! What's up?"]
if(intent == "Hii"):
 print(random.choice(output))

使用 API 开发聊天机器人

创建聊天机器人不是一件容易的事情。你需要一双关注细节的眼睛和敏锐的思维来构建一个可以很好使用的聊天机器人。构建聊天机器人有两种方法。

  • 基于规则的方法
  • 一种机器学习方法,通过简化数据使系统自行学习

一些聊天机器人本质上是基础的,而另一些则是更高级的人工智能大脑。能够理解自然语言并做出反应的聊天机器人使用人工智能大脑,技术爱好者正在利用 Api.ai 等各种资源来创建这种人工智能丰富的聊天机器人。

程序员正在利用以下服务来构建机器人:

  • 微软机器人框架
  • Wit.ai
  • Api.ai
  • IBM 的沃森

其他编程技能有限或没有编程技能的 bot 构建爱好者正在利用如下 bot 开发平台来构建聊天机器人:

  • 聊天燃料
  • Texit.in
  • 辛烷 AI
  • Motion.ai

有不同的 API 来分析文本。三大巨头如下:

  • 微软 Azure 的认知服务
  • 亚马逊 Lex
  • 沃森机器人

微软 Azure 的认知服务

先说微软 Azure。

  • 语言理解智能服务(LUIS):这提供了简单的工具,使您能够构建自己的语言模型(意图/实体),允许任何应用程序/机器人理解您的命令并相应地采取行动。
  • 文本分析 API:它评估情感和主题,以了解用户想要什么。
  • Translator Text API:自动识别语言,然后实时将其翻译成另一种语言。
  • Web 语言模型 API:这将自动在缺少空格的字符串中插入空格。
  • Bing 拼写检查 API:这使用户能够纠正拼写错误;认识名字、品牌名称和俚语之间的区别;并且在他们打字的时候理解同音字。
  • 语言分析 API:这允许您使用词性标记来识别文本中的概念和动作,并使用自然语言解析器来查找短语和概念。这对于挖掘客户反馈非常有用。

亚马逊 Lex

Amazon Lex 是一项为任何使用语音和文本的应用程序构建对话界面的服务。不幸的是,没有同义词选项,也没有适当的实体提取和意图分类。

以下是使用 Amazon Lex 的一些重要好处:

  • 很简单。它指导你创建聊天机器人。
  • 它有深度学习算法。聊天机器人实现了 NLU 和自然语言处理等算法。Amazon 已经将这一功能集中起来,以便于使用。
  • 它具有易于部署和扩展的特性。
  • 它内置了与 AWS 平台的集成。
  • 这是有成本效益的。

沃森机器人

IBM 提供了 IBM Watson API 来快速构建您自己的聊天机器人。在实现中,接近旅程和旅程本身一样重要。通过沃森对话式人工智能学习对话式设计的企业基础知识及其对您业务的影响,对于制定成功的行动计划至关重要。这种准备工作将使您能够交流、学习和对照标准进行监控,从而使您的企业能够构建一个客户就绪的成功项目。

对话式设计是构建聊天机器人最重要的部分。首先要明白的是,用户是谁,想达到什么目的。

IBM Watson 有很多技术,你可以很容易地集成到你的聊天机器人中;其中一些是沃森对话,沃森声调分析器,语音到文本,等等。

聊天机器人开发的最佳实践

在构建聊天机器人时,了解可以利用某些最佳实践是很重要的。这将有助于创建一个成功的用户友好的机器人,它可以实现与用户进行无缝对话的目的。

在这种关系中,最重要的事情之一是充分了解目标受众。接下来是其他的事情,比如识别用例场景,设定聊天的基调,以及识别消息传递平台。

通过遵循以下最佳实践,确保与用户无缝对话的愿望可以成为现实。

了解潜在用户

彻底了解目标受众是构建成功 bot 的第一步。下一步是了解创建机器人的目的。

以下是需要记住的几点:

  • 知道具体 bot 的目的是什么。它可以是一个娱乐观众、方便用户交易、提供新闻或作为客户服务渠道的机器人。
  • 通过了解客户的产品,使机器人对客户更加友好。

阅读用户情感,让机器人在情感上更加丰富

聊天机器人应该像人类一样热情友好,这样才能让对话成为一次美好的经历。它必须聪明地阅读并理解用户的情绪,以推广能够提示用户继续对话的内容块。如果第一次的体验是丰富的,用户将被鼓励再次访问。

以下是需要记住的几点:

  • 推广你的产品或利用积极情绪将用户转化为品牌大使。
  • 迅速处理负面评论,以便在对话游戏中保持活力。
  • 只要有可能,使用友好的语言,让用户感觉他们在和一个熟悉的人交流。
  • 通过重复输入让用户感到舒服,并确保他们能够理解所讨论的一切。

十二、人脸检测和识别

人脸检测是在图像或视频中检测人脸的过程。

人脸识别是检测图像中的人脸,然后使用算法来识别人脸属于谁的过程。因此,人脸识别是一种身份识别形式。

你首先需要从图像中提取特征,用于训练机器学习分类器识别图像中的人脸。这些系统不仅是非主观的,而且是自动的——不需要手动标记面部特征。您只需从面部提取特征,训练您的分类器,然后使用它来识别后续的面部。

因为对于人脸识别,首先需要从图像中检测人脸,所以可以将人脸识别视为两个阶段。

  • 阶段 1:使用诸如 Haar cascades、HOG +线性 SVM、深度学习或任何其他可以定位人脸的算法来检测图像或视频流中的人脸的存在。
  • 第二阶段:取定位阶段检测到的每一张脸,了解这张脸属于谁——这是你实际上给一张脸命名的地方。

人脸检测、人脸识别和人脸分析

人脸检测、人脸识别和人脸分析是有区别的。

  • 人脸检测:这是一种在图像中找到所有人脸的技术。
  • 人脸识别:这是人脸检测之后的下一步。在人脸识别中,您可以使用现有的图像库来识别哪张脸属于哪个人。
  • 面部分析:检查一张脸,从中推断出年龄、肤色等等。

开放计算机视觉

OpenCV 提供了三种人脸识别方法(见图 12-1 ):

  • 特征脸
  • 局部二元模式直方图
  • 鱼脸

A456157_1_En_12_Fig1_HTML.jpg

图 12-1

Applying OpenCV methods to faces

这三种方法都是通过将人脸与一些已知人脸的训练集进行比较来识别人脸的。为了训练,你给算法提供人脸,并用他们所属的人给他们贴上标签。当你使用该算法来识别某个未知人脸时,它使用在训练集上训练的模型来进行识别。上述三种方法中的每一种使用的训练集都略有不同。

拉普拉斯人脸可以是识别人脸的另一种方式。

特征脸

eigenfaces 算法使用主成分分析来构建人脸图像的低维表示,您将使用它作为相应人脸图像的特征(图 12-2 )。

A456157_1_En_12_Fig2_HTML.jpg

图 12-2

Applying Eigenvalue decomposition and extracting 11 eigenfaces with the largest magnitude

为此,您可以收集一个人脸数据集,其中包含您想要识别的每个人的多张人脸图像,这就像您想要在图像分类中标记的一个图像类有多个训练样本一样。有了这个面部图像的数据集,假定它们具有相同的宽度和高度,并且理想情况下它们的眼睛和面部结构在相同的(x,y)坐标上对齐,您可以应用数据集的特征值分解,保留具有最大相应特征值的特征向量。

给定这些特征向量,人脸就可以表示为 Kirby 和 Sirovich 所说的特征脸的线性组合。特征脸算法查看整个数据集。

LBPH 值

您可以在 LBPH 中独立分析每张图像。LBPH 方法稍微简单一些,因为您可以在本地描述数据集中每个图像的特征;当提供新的未知图像时,您对其执行相同的分析,并将结果与数据集中的每个图像进行比较。分析图像的方法是描述图像中每个位置的局部模式。

本征脸算法依靠 PCA 来构建人脸图像的低维表示,而局部二进制模式(LBP)方法,顾名思义,依靠特征提取。

Ahonen 等人在 2006 年的论文“使用局部二进制模式进行人脸识别”中首次介绍了这种方法,该方法建议将人脸图像划分为 7×7 大小相等的网格(图 12-3 )。

A456157_1_En_12_Fig3_HTML.jpg

图 12-3

Applying LBPH for face recognition starts by dividing the face image into a 7x7 grid of equally sized cells

然后,从 49 个单元中的每一个提取局部二进制模式直方图。通过将图像划分为单元,您将局部性引入到最终的特征向量中。此外,中心的单元具有更大的权重,因此它们对整体表示的贡献更大。与网格中心的细胞(包含眼睛、鼻子和嘴唇结构)相比,角落的细胞携带的识别面部信息较少。最后,您连接来自 49 个单元的加权 LBP 直方图,以形成您的最终特征向量。

鱼脸

主成分分析(PCA)是本征脸方法的核心,它寻找使数据的总方差最大化的特征的线性组合。虽然这显然是表示数据的一种强有力的方法,但它没有考虑任何类,因此在丢弃组件时可能会丢失许多有区别的信息。想象一种情况,你的数据中的差异是由外部来源产生的,让它成为光。由 PCA 识别的成分不一定包含任何区别信息,因此投影的样本被涂抹在一起,分类变得不可能。

线性判别分析执行特定类别的维度缩减,由伟大的统计学家 R. A. Fisher 爵士发明。分类问题中多重测量的使用。为了找到在类之间分离得最好的特征组合,线性判别分析最大化类间与类内分散的比率,而不是最大化整体分散。这个想法很简单:相同的类应该紧密地聚集在一起,而不同的类在低维表示中彼此尽可能地远离。

检测人脸

执行人脸识别所需的第一个功能是检测当前图像中人脸出现的位置。在 Python 中,您可以使用 OpenCV 库的 Haar 级联过滤器来有效地做到这一点。

对于这里展示的实现,我将 Anaconda 与 Python 3.5、OpenCV 3.1.0 和 dlib 19.1.0 一起使用。要使用以下代码,请确保您拥有这些(或更新的)版本。

要进行面部检测,必须进行一些初始化,如下所示:

A456157_1_En_12_Figa_HTML.jpg

剩下的代码将是一个无限循环,不断从网络摄像头获取最新的图像,检测检索到的图像中的所有人脸,在检测到的最大人脸周围绘制一个矩形,然后最终在一个窗口中显示输入、输出图像(图 12-4 )。

A456157_1_En_12_Fig4_HTML.jpg

图 12-4

A sample output showing detected face

您可以在无限循环中使用以下代码来实现这一点:

A456157_1_En_12_Figd_HTML.jpg

A456157_1_En_12_Figc_HTML.jpg

A456157_1_En_12_Figb_HTML.jpg

跟踪面部

以前的人脸检测代码有一些缺点。

  • 该代码可能计算量很大。
  • 如果被检测的人稍微转头,哈尔级联可能检测不到面部。
  • 很难在帧间跟踪一张脸。

更好的方法是检测一次人脸,然后利用优秀的 dlib 库中的相关跟踪器来逐帧跟踪人脸。

为此,您需要导入另一个库并初始化其他变量。

A456157_1_En_12_Fige_HTML.jpg

在无限for循环中,您现在将确定 dlib 关联跟踪器当前是否正在跟踪图像中的一个区域。如果不是这种情况,您将使用与前面类似的代码来查找最大的面,但不是绘制矩形,而是使用找到的坐标来初始化相关性跟踪器。

A456157_1_En_12_Figg_HTML.jpg

A456157_1_En_12_Figf_HTML.jpg

现在,无限循环中的最后一点是再次检查相关性跟踪器是否正在主动跟踪人脸(即,它是否刚刚检测到具有先前代码的人脸,trankingFace=1?)。如果追踪器正在积极追踪图像中的人脸,您将更新追踪器。根据更新的质量(例如,追踪器对是否仍在追踪同一张脸有多大把握),您可以在追踪器指示的区域周围画一个矩形,或者指示您不再追踪一张脸。

A456157_1_En_12_Figh_HTML.jpg

从代码中可以看出,每次再次使用检测器时,都会向控制台打印一条消息。如果您在运行该应用程序时查看控制台的输出,您会注意到,即使您在屏幕上移动了相当多的距离,追踪器也会很好地跟踪检测到的人脸。

人脸识别

人脸识别系统通过将每帧视频中的人脸与训练图像进行匹配来识别视频帧中出现的人的姓名,如果帧中的人脸匹配成功,则返回标签(并写入 CSV 文件中)。现在你将看到如何一步一步地创建一个人脸识别系统。

首先,导入所有需要的库。face_recognition 是一个简单的库,使用 dlib 最先进的人脸识别技术构建,也是通过深度学习构建的。

A456157_1_En_12_Figi_HTML.jpg

Argparse 是一个 Python 库,允许您向文件中添加自己的参数;然后,它可以用于在执行时输入任何图像目录或文件路径。

A456157_1_En_12_Figj_HTML.jpg

在前面的代码中,在运行这个 Python 文件时,您必须指定以下内容:训练输入图像目录、我们将用作数据集的视频文件,以及用于在每个时间帧写入输出的输出 CSV 文件。

A456157_1_En_12_Figl_HTML.jpg

A456157_1_En_12_Figk_HTML.jpg

通过使用上述功能,可以读取指定文件夹中的所有图像文件。

以下函数使用已知的训练图像测试输入帧:

A456157_1_En_12_Figm_HTML.jpg

现在您定义函数来提取匹配的已知图像的标签。

A456157_1_En_12_Fign_HTML.jpg

读取输入视频以提取测试帧。

A456157_1_En_12_Figo_HTML.jpg

现在定义训练集的标签。然后匹配从给定输入视频中提取的帧,以获得所需的结果。

A456157_1_En_12_Figp_HTML.jpg

基于深度学习的人脸识别

导入必要的包。

A456157_1_En_12_Figq_HTML.jpg

初始化变量。

A456157_1_En_12_Figr_HTML.jpg

label_img()函数用于创建标签数组,detect_faces()函数检测图像中的人脸部分。

A456157_1_En_12_Figs_HTML.jpg

create_train_data()函数用于预处理训练数据。

A456157_1_En_12_Figt_HTML.jpg

process_test_data()函数用于对测试数据进行预处理。

A456157_1_En_12_Figu_HTML.jpg

然后创建模型,并在模型中拟合训练数据。

A456157_1_En_12_Figv_HTML.jpg

最后,您准备测试数据并预测输出。

A456157_1_En_12_Figw_HTML.jpg

迁移学习

迁移学习利用在解决一个问题时获得的知识,并将其应用于另一个不同但相关的问题。

在这里,您将看到如何使用名为 Inception v3 模型的预训练深度神经网络对图像进行分类。

Inception 模型能够从图像中提取有用的信息。

为什么要转学?

众所周知,卷积网络需要大量的数据和资源来训练。

使用迁移学习和微调(也就是说,将在以前的项目(如 ImageNet)中训练的网络权重转移到新的任务中)已经成为研究人员和实践者的规范。

您可以采取两种方法。

  • 迁移学习:你可以拿一个已经在 ImageNet 上预先训练好的 CNN,去掉最后一个完全连接的层,然后把 CNN 的其余部分当作新数据集的特征提取器。一旦提取了所有图像的特征,就可以为新的数据集训练一个分类器。
  • 微调:您可以在 CNN 上替换和重新训练分类器,还可以通过反向传播微调预训练网络的权重。

迁移学习示例

在这个例子中,首先您将尝试通过直接加载 Inception v3 模型来对图像进行分类。

导入所有需要的库。

A456157_1_En_12_Figx_HTML.jpg

现在为模型定义存储目录,然后下载 Inception v3 模型。

A456157_1_En_12_Figy_HTML.jpg

加载预训练的模型并定义函数来对任何给定的图像进行分类。

A456157_1_En_12_Figz_HTML.jpg

现在模型已经定义好了,让我们检查一些图片。

A456157_1_En_12_Figaa_HTML.jpg

这给出了 91.11%的正确结果,但是现在如果你检查某个人,你会得到这样的结果:

A456157_1_En_12_Figab_HTML.jpg

是 48.50%的网球!

不幸的是,盗梦空间模型似乎无法对人的图像进行分类。这样做的原因是用于训练初始模型的数据集,它对于类有一些令人困惑的文本标签。

相反,您可以重用预训练的初始模型,仅仅替换最终分类的层。这就是所谓的迁移学习。

首先,您使用 Inception 模型输入并处理一个图像。就在初始模型的最终分类层之前,您将所谓的转移值保存到一个缓存文件中。

使用缓存文件的原因是,使用 Inception 模型处理图像需要很长时间。当新数据集中的所有图像都已经通过初始模型进行了处理,并且所得到的传递值被保存到缓存文件中时,那么您可以使用这些传递值作为另一个神经网络的输入。然后,您将使用新数据集中的类来训练第二个神经网络,以便网络学习如何基于来自初始模型的转移值来对图像进行分类。

这样,初始模型用于从图像中提取有用的信息,然后另一个神经网络用于实际的分类。

计算转移价值

从初始文件中导入transfer_value_cache函数。

A456157_1_En_12_Figad_HTML.jpg

A456157_1_En_12_Figac_HTML.jpg

到目前为止,传输值存储在缓存文件中。现在您将创建一个新的神经网络。

定义网络。

A456157_1_En_12_Figae_HTML.jpg

下面是优化方法:

A456157_1_En_12_Figaf_HTML.jpg

下面是分类精度:

A456157_1_En_12_Figag_HTML.jpg

下面是 TensorFlow 运行:

A456157_1_En_12_Figah_HTML.jpg

下面是执行批量训练的帮助器函数:

A456157_1_En_12_Figai_HTML.jpg

为了优化,下面是代码:

A456157_1_En_12_Figak_HTML.jpg

A456157_1_En_12_Figaj_HTML.jpg

为了绘制混淆矩阵,下面是代码:

A456157_1_En_12_Figal_HTML.jpg

以下是计算分类的辅助函数:

A456157_1_En_12_Figaq_HTML.jpg

A456157_1_En_12_Figap_HTML.jpg

A456157_1_En_12_Figao_HTML.jpg

A456157_1_En_12_Figan_HTML.jpg

A456157_1_En_12_Figam_HTML.jpg

现在让我们运行它。

from datetime import timedelta

optimize(num_iterations=1000)

Global Step:  13100, Training Batch Accuracy: 100.0%
Global Step:  13200, Training Batch Accuracy: 100.0%
Global Step:  13300, Training Batch Accuracy: 100.0%
Global Step:  13400, Training Batch Accuracy: 100.0%
Global Step:  13500, Training Batch Accuracy: 100.0%
Global Step:  13600, Training Batch Accuracy: 100.0%
Global Step:  13700, Training Batch Accuracy: 100.0%
Global Step:  13800, Training Batch Accuracy: 100.0%
Global Step:  13900, Training Batch Accuracy: 100.0%
Global Step:  14000, Training Batch Accuracy: 100.0%
Time usage: 0:00:36

print_test_accuracy(show_example_errors=True,
show_confusion_matrix=True)

Accuracy on Test-Set: 83.2% (277 / 333)
Example errors:
Confusion Matrix:
[108 3 5] (0) Aamir Khan
[0 83 22] (1) Salman Khan
[4 22 86] (2) Shahrukh Khan
 (0) (1) (2)

蜜蜂

许多易于使用的 API 也可用于人脸检测和人脸识别任务。

以下是面部检测 API 的一些示例:

  • piclab
  • Trueface.ai
  • 决定的吉时
  • 微软计算机视觉

以下是面部识别 API 的一些示例:

  • Face++
  • 拉姆达实验室
  • KeyLemon
  • piclab

如果你想从一个提供商那里获得人脸检测、人脸识别和人脸分析,目前有三大巨头在这方面领先。

  • 亚马逊的亚马逊识别 API
  • 微软 Azure 的 Face API
  • IBM Watson 的视觉识别 API

亚马逊的亚马逊识别 API 可以做四种类型的识别。

  • 对象和场景检测:识别识别各种有趣的对象,如车辆、宠物或家具,并提供置信度得分。
  • 面部分析:您可以在图像中定位面部并分析面部属性,如面部是否微笑或眼睛是否睁开,并具有一定的置信度。
  • 面部对比:亚马逊的亚马逊识别 API 可以让你测量两张图片中的面部是同一个人的可能性。不幸的是,同一个人的两张脸的相似性度量取决于照片拍摄时的年龄。此外,面部照明的局部增加会改变面部比较的结果。
  • 面部识别:API 使用私有存储库识别给定图像中的人。它又快又准。

微软 Azure 的 Face API 将返回一个置信度分数,以确定这两张脸属于一个人的可能性有多大。微软还有其他 API,如下所示:

  • 计算机视觉 API:这个特性返回图像中可视内容的信息。它可以使用标记、描述和特定于领域的模型来识别内容并满怀信心地对其进行标记。
  • 内容审核 API:这可以检测潜在的攻击性或不需要的图像、各种语言的文本和视频内容。
  • Emotion API:它分析人脸来检测一系列的感觉,并个性化你的应用程序的响应。
  • 视频 API:这产生稳定的视频输出,检测运动,创建智能缩略图,检测和跟踪人脸。
  • 视频索引器:这可以在视频中发现一些见解,例如语音实体、语音的情感极性和音频时间轴。
  • 定制视觉服务:这将根据内置模型或通过您提供的训练数据集构建的模型来标记新图像。

IBM Watson 的视觉识别 API 可以进行一些特定的检测,例如:

  • 它可以确定人的年龄。
  • 它可以确定人的性别。
  • 它可以确定一个面周围的边界框的位置。
  • 它可以返回在图像中检测到的名人的信息。(未检测到名人时不返回此信息。)
posted @ 2024-10-01 21:02  绝不原创的飞龙  阅读(7)  评论(0编辑  收藏  举报