Python Web 深度学习实用指南(二)_请同学们结合所学python web知识按照以下项目运行效果图,完成相关程序设计(注:每
原文:
annas-archive.org/md5/ba1cfcea7397d362b4cda60b175c7bb2
译者:飞龙
协议:CC BY-NC-SA 4.0
第六章:开始使用 TensorFlow.js
到目前为止,我们已经轻松地了解了深度学习的奇妙世界,并对深度学习在使现代 Web 应用更加智能方面的潜力有了一个大致的了解。在第一章,揭开人工智能的神秘面纱与机器学习基础中,我们详细了解了 AI 突破前后的 Web 应用概况。在第三章,创建你的第一个深度学习 Web 应用中,我们使用一个简单的神经网络构建了一个基于图像分类的 Web 应用。
Web 应用无处不在,已经成为我们日常生活中不可或缺的一部分。在构建 Web 应用时,JavaScript 的使用几乎是无法忽视的。那么,如果我们只使用 JavaScript,而不依赖其他脚本语言,来构建一个智能的 Web 应用会怎样呢?在本章中,我们将展示如何使用一个名为 TensorFlow.js(TF.js)的 JavaScript 库,构建一个支持深度学习的 Web 应用——这一切都将在 Web 浏览器中完成。
在本章中,我们将涵盖以下主题:
-
TF.js 的基本原理及其功能
-
使用 TF.js 开发深度学习模型并进行推理
-
在浏览器中直接使用预训练模型
-
构建一个用于识别花卉种类的 Web 应用
-
TF.js 的优势与局限
技术要求
你可以访问本章使用的代码,地址为 github.com/PacktPublishing/Hands-On-Python-Deep-Learning-for-Web/tree/master/Chapter4
。
要完成本章的内容,你需要以下软件:
-
TF.js 0.15.1+
-
来自 NPM 仓库的
@tensorflow/tfjs-node
0.3.0+ 包
TF.js 的基本原理
在本节中,我们将简要回顾一些 TF.js 的基本概念。我们将从介绍 TensorFlow 开始,然后继续研究 TF.js 的不同组件。
什么是 TensorFlow?
在我们开始讨论 TF.js 之前,我们必须了解什么是 TensorFlow。TensorFlow 是一个由 Google 开发和维护的开源库。它基于一种称为张量的数据结构构建。张量是标量和向量的广义形式。TensorFlow 提供了许多高效的工具,适用于广泛的科学领域中的高性能数值计算。TensorFlow 还提供了一套非常灵活的工具,用于进行机器学习和深度学习的开发与研究。你可以访问 TensorFlow 的官方网站 www.tensorflow.org/
获取更多信息。
什么是 TF.js?
TF.js 是一个 JavaScript 库,提供了一个构建和部署机器学习模型的生态系统。它提供了以下功能:
-
使用 JavaScript 开发机器学习模型
-
使用预训练的机器学习模型
-
部署机器学习模型
TF.js 为你提供了机器学习项目所需的所有元素。它有专门的模块用于数据预处理、张量处理、模型构建、模型评估等,但所有这些都是用 JavaScript 完成的。在深入了解这些之前,让我们快速理解 TF.js 的必要性。
为什么选择 TF.js?
正如我们在前一章节中看到的那样,在线训练和托管一个模型、将其封装在一个 REST API 中,然后在任何前端使用 API 来展示我们的结果是非常简单和直观的。那么,为什么还会需要使用 TF.js 呢?
这个问题的简单答案是:如果浏览器中有 AI!想象一下一个游戏,它需要使用一个 AI 代理,这个代理通过学习人类玩家的玩法方式,在游戏进程中变得更强或更弱。如果在每一瞬间,游戏都不断向服务器发送请求,来传输数据到游戏和服务器之间,这就过于冗余了。更重要的是,这可能很容易导致拒绝服务(DoS)攻击。
因此,在浏览器中拥有一个可以自行生存并实时学习的 AI 是有意义的,尤其是当代理需要实时不断学习时。它也可以是两种方式的混合:
-
如果在代理渲染期间加载了一个预训练模型,并且从那里开始,代理会在服务器上间隔性地学习并更新模型。
-
如果多个版本的 AI 代理同时在几个系统上运行,并且它们从各自的系统互动中学习。而且,如果它们的集体学习被汇总到服务器上,代理将在间隔时从服务器获取更新。
因此,使用 TF.js 大大减少了对人类用户与服务器进行每一步通信时依赖页面的强度。
现在我们可以构建一个小项目,展示 TF.js 的强大功能。现在不用担心 TF.js 生态系统——我们会在过程中涵盖项目的所有元素。
TF.js 的基本概念
以下是我们将在项目中使用的 TF.js 组件:
-
张量
-
变量
-
操作
-
模型
-
层
让我们详细看看它们每个。
张量
与 TensorFlow 一样,TF.js 中的中央数据处理单元是张量。Goodfellow 等人(在他们的深度学习书中)做出了以下观察:
一般来说,按规则网格排列的数字数组,具有可变数量的轴,被称为张量。
简单来说,张量是一个容器,包含一维或多维数组。以下是一些你可能已经知道的张量示例:
-
标量(一个秩为零的张量)
-
向量(一个一维或秩为一的张量)
-
矩阵(一个二维或秩为二的张量)
我们可以根据给定的形状在 TF.js 中创建一个张量,如下所示:
const shape = [2, 3]; // 2 rows, 3 columnsconst a = tf.tensor([4.0, 2.0, 5.0, 15.0, 19.0, 27.0], shape);
a
是一个已创建的张量,其内容可以使用以下命令打印出来:
a.print()
以下输出被打印:
Output: [[4 , 2 , 5 ], [15, 19, 27]]
a
是一个矩阵(一个二阶张量)。TF.js 还提供了专门的函数,如 tf.scalar
、tf.tensor1d
、tf.tensor2d
、tf.tensor3d
和 tf.tensor4d
,用于创建具有特定形状的张量,而无需显式指定 shape
参数。这也提高了可读性。在 TF.js 中,张量是不可变的。
变量
与张量不同,变量在 TF.js 中是可变的。变量在神经网络训练过程中尤为重要,因为它们包含了大量中间数据存储和更新。以下是如何在 TF.js 中使用变量的示例:
const initialValues = tf.ones([5]);const weights = tf.variable(initialValues); // initialize weightsweights.print(); // output: [1, 1, 1, 1, 1]const updatedValues = tf.tensor1d([0, 1, 0, 1, 0]);weights.assign(updatedValues); // update values of weightsweights.print(); // output: [0, 1, 0, 1, 0]
现在我们来看一下运算符。
运算符
运算符让你对数据进行数学运算。TF.js 提供了各种用于操作张量的运算符。由于张量本质上是不可变的,运算符不会改变张量中的数据——它们会返回新的张量作为结果。你可以对张量执行二元操作,如加法、乘法和减法。你甚至可以链式调用多个操作。以下示例展示了如何在 TF.js 中使用两个不同的运算符进行链式操作:
const e = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]); const f = tf.tensor2d([[3.0, 4.0], [5.0, 6.0]]); const sq_sum = tf.square(tf.add(e, f));sq_sum.print();
我们首先创建了两个二维张量,并将它们分别赋值给e
和f
。接着,我们对它们进行了相加并求平方。
这会产生以下输出:
// Output: [[16 , 36],// [64, 100]]
接下来,我们将讨论模型和层。
模型与层
在深度学习文献中,模型指的是神经网络本身,特别是神经网络架构。如在第二章《使用 Python 入门深度学习》中所讨论,神经网络由基本组件组成,如层、神经元以及层之间的连接。TF.js 提供了两个创建这些模型的函数——tf.model
和 tf.sequential
。tf.model
帮助你构建更复杂的架构,例如跳过某些层,而 tf.sequential
提供了一种创建线性层堆栈的方式,不涉及跳过、分支等操作。
TF.js 提供了多种专用层类型,用于不同任务的需求——tf.layers.dense
、tf.layers.dropout
、tf.layers.conv1d
、tf.layers.simpleRNN
、tf.layers.gru
和 tf.layers.lstm
。以下示例通过 tf.sequential
和 tf.layers.dense
展示了一个简单的神经网络模型:
const model = tf.sequential();model.add(tf.layers.dense({units: 4, inputShape: [4], activation: \'relu\'}));model.add(tf.layers.dense({units: 1, activation: sigmoid}));
上述示例创建了一个简单的神经网络,其特点如下:
-
两个层(记住,在计算总层数时我们不考虑输入层)。该网络接受一个具有四个特征的输入(
inputShape
参数有助于指定这一点)。 -
第一层包含四个神经元(因此是
units: 4
)。第二层(输出层)只有一个神经元。 -
第一个层使用
relu
激活函数,输出层使用sigmoid
激活函数。
鼓励您访问 js.tensorflow.org/api/latest/index.html
了解 TF.js 的前述组件。
使用 TF.js 的案例研究
我们将遵循通常涉及到的机器学习项目中的所有步骤(我们在 第一章 中讨论过,揭秘人工智能和机器学习基础)。一个好的项目从一个清晰定义的问题陈述开始。因此,让我们快速浏览一下,并据此决定后续步骤。
我们 TF.js 小项目的问题陈述
在这里我们将要探讨的问题可能是你在机器学习初学时遇到的最著名的挑战之一——通过学习鸢尾花数据集中的特征来分类和预测鸢尾花的类型。训练和预测将在浏览器中执行。
我们已经为项目定义了问题陈述。接下来将进行数据准备步骤。数据已经可用,因此我们不需要自行收集。但是,在准备数据之前,了解数据本身的更多信息会很有帮助。
鸢尾花数据集
由统计学家兼生物学家罗纳德·费舍尔于 1936 年引入的鸢尾花数据集包含 150 行数据,大约有 3 种不同的鸢尾花品种。列名如下:
-
萼片长度(cm)
-
萼片宽度(cm)
-
花瓣长度(cm)
-
花瓣宽度(cm)
-
种类:
-
山鸢尾
-
变色鸢尾
-
维吉尼亚
-
您可以在 archive.ics.uci.edu/ml/datasets/Iris
获取原始数据集并了解更多。
您的第一个 TF.js 深度学习 Web 应用程序
在本节中,我们将使用 TF.js 开发一个 Web 应用程序。此应用程序将包括标准的全栈深度学习支持的 Web 项目步骤。我们将从准备数据开始,然后简要研究项目架构,然后按需构建所需的组件。
准备数据集
鸢尾花数据集原始形式是一个包含 150 行数据的 CSV 文件,以逗号分隔的格式,每个条目以新行分隔。
然而,为了更轻松地与 JavaScript 运行,我们将使用数据的 JSON 格式。JSON 格式的数据集可以从 gist.github.com/xprilion/33cc85952d317644c944274ee6071547
下载。
您可以使用任何语言中的简单函数,将 CSV 文件转换为 JSON 文件,按照以下约定更改列名:
-
萼片长度:
sepal_length
-
萼片宽度:
sepal_width
-
花瓣长度:
petal_length
-
花瓣宽度:
petal_width
-
种类:
species
在模型构建时,我们将使用这些属性名称的 JSON 格式。
项目架构
在本项目中,我们将使用 Node.js 来创建一个服务器。这样做是为了能够通过 Node.js 后端使用 TF.js,从而获得更快的计算性能。我们将创建一个非常基础的前端,用户可以通过它来发出命令,训练由 TF.js 构建的神经网络,并使用另一个按钮发出命令,根据用户提供的输入预测一朵鸢尾花的特征向量的类别。
以下图显示了项目的组成部分及其相互作用:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/8e47dac3-cf66-406f-8222-dbf2905cd686.png
现在我们了解了架构,接下来让我们开始项目的开发。
启动项目
要开始进行项目开发,首先需要安装 Node.js 和Node 包管理器(NPM)的最新版本。虽然标准的做法是阅读 Node.js 官网提供的文档,我们建议使用Node 版本管理器(NVM)来安装 Node.js 和 NPM。
安装说明和文件可以在githu
b.com/creationix/nvm.
一旦安装了 Node.js 和 NPM,我们就可以开始进行项目的开发了:
-
创建一个名为
tfjs-iris
的文件夹。 -
打开终端,并使用以下命令初始化该项目的包管理器:
npm init -y
这应该会在项目目录中创建一个package.json
文件。前面的命令输出如下:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/d566a0e8-10d6-4418-9e82-a59447d8f27a.png
请注意,输出格式为 JSON 格式。main
键定义了在作为模块导入时程序的入口文件。在本项目中,main
的默认值设置为index.js
。不过,这个文件尚未创建。让我们来创建index.js
文件。
我们将使用 Node.js 的express
模块来创建我们的服务器。你可以在expressjs.com
上了解更多关于express
的信息。
- 要使用
express
,我们需要将这个模块添加到我们的项目中。为此,请使用以下代码:
npm install express --save
这将把express
模块的依赖添加到package.json
文件中,并将其安装到项目的node_modules
目录中。
- 在项目仓库的根目录下创建一个名为
index.js
的文件,并添加以下代码:
var express = require(\'express\');var app = express();
这将创建一个express
应用程序对象。接下来,我们将把 TF.js 添加到项目中。最简单的方法是通过 NPM 安装。完整的安装说明可以在js.tensorflow.org/setup/
找到。
- 使用以下命令在终端中安装
TF.js
模块:
npm install @tensorflow/tfjs --save
- 现在我们可以继续将该模块添加到我们的
index.js
文件中了:
const tf = require(\'@tensorflow/tfjs\');
- 我们还需要 Express.js 中的
body-parser
模块来处理来自客户端的查询数据,这些数据将通过 AJAXPOST
请求发送。为此,我们使用以下命令:
npm install body-parser --save
- 我们现在创建一个
body-parser
对象,并使用以下代码将其绑定到应用程序:
var bodyParser = require(\'body-parser\');app.use(bodyParser.urlencoded({ extended: false }));
在此阶段,package.json
应包含列出项目依赖项的以下代码片段:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/64f57e1d-2a8d-481d-b2bc-27ed8c7d89fd.png
请注意,前面的版本可能会发生变化。我们现在可以导入iris.json
文件,这是我们将要训练的模型数据:
const iris = require(\'./iris.json\');
初始设置完成后,我们现在可以继续编写 TF.js 代码,在可用数据集上进行训练。
创建 TF.js 模型
首先,我们通过将存储在iris
变量中的数据读取到一个tensor2d
对象中:
- 在你的
index.js
文件中,添加以下代码:
const trainingData = tf.tensor2d(iris.map(item=> [ item.sepal_length, item.sepal_width, item.petal_length, item.petal_width]),[144,4])
我们目前还没有任何测试数据;这些将由用户提供。
- 接下来,我们创建一个可能的三种花卉品种的独热编码:
const outputData = tf.tensor2d(iris.map(item => [ item.species === \'setosa\' ? 1 : 0, item.species === \'virginica\' ? 1 : 0, item.species === \'versicolor\' ? 1 : 0]), [144,3])
我们现在可以开始创建训练模型的代码。以下代码可能让你想起我们在上一章中为 MNIST 手写数字数据集创建模型时使用的代码。这仅仅是因为我们仍然在使用 TensorFlow 的概念,只不过是用不同的语言!
- 我们首先声明一个顺序的 TensorFlow 模型:
const model = tf.sequential();
- 接下来,让我们为模型添加一层神经元:
model.add(tf.layers.dense({ inputShape: 4, activation: \'sigmoid\', units: 10 }));
inputShape
参数表示将添加到该层的输入的形状。units
参数设置该层中使用的神经元数量。我们使用的激活函数是sigmoid
函数。
- 现在让我们添加输出层:
model.add(tf.layers.dense({ inputShape: 10, units: 3, activation: \'softmax\'}));
在这里,我们将输出层中有 3 个神经元,且该层的输入为 10,这与前一层中的神经元数量相匹配。
除了输入层外,我们只有一个隐藏层和输出层。由于数据集较小且预测简单,因此在此应用中是可以接受的。请注意,我们在这里使用了softmax
激活函数,它会输出类别概率。
这在我们的案例中特别有用,因为问题是一个多类分类问题。
- 完成这一切后,我们现在可以准备编译我们的模型。为此,我们使用以下代码:
model.compile({ loss: \"categoricalCrossentropy\", optimizer: tf.train.adam()});
由于我们手头有一个分类问题,其中有多个可能的标签,因此我们使用categoricalCrossentropy
作为loss
函数。为了优化,我们使用adam
优化器。鼓励你尝试其他超参数值。
- 我们可以使用以下代码生成模型的摘要:
model.summary();
接下来,我们将训练我们的 TF.js 模型。
训练 TF.js 模型
我们现在将编写一个 async
函数。这样做的原因是为了让客户端 JavaScript 调用我们的函数时,不会因为等待结果而卡住。我们程序中需要一定时间才能完成的函数是 train_data()
函数。该函数负责模型的训练:
async function train_data(){ console.log(\"Training Started\"); for(let i=0;i<50;i++){ let res = await model.fit(trainingData, outputData, {epochs: 50}); console.log(`Iteration ${i}: ${res.history.loss[0]}`); } console.log(\"Training Complete\");}
train_data()
函数可以异步运行。它还会在每个训练周期输出损失值到我们运行服务器的控制台中。现在,让我们创建一个 API 来调用 train_data()
函数。
首先,我们创建一个名为 doTrain
的 中间件,它将在训练 API 之前运行,并返回任何数据。
你可以在 expressjs.com/en/guide/using-middleware.html
阅读更多关于中间件的内容。
doTrain()
中间件在其参数中接受对 Node.js 服务器发出的请求、用于响应的变量,以及在执行完中间件中定义的代码块后用来转发程序执行的函数:
var doTrain = async function (req, res, next) { await train_data(); next();}
doTrain
中间件调用 train_data()
函数并等待其结果。train_data()
函数返回一个 Promise,以便执行可以继续而不会冻结。next()
函数在 train_data()
函数完成后立即运行,它只是将程序的执行传递给下一个链式调用的中间件函数,如下所示:
app.use(doTrain).post(\'/train\', function(req, res) { res.send(\"1\");});
我们现在将 \'/train\'
路由绑定到 express
应用中,然后将 doTrain
中间件链接到它。现在,每当调用 \'/train\'
API 时,中间件会首先运行,然后执行会传递到 API 的主代码块。这个代码块简单地返回一个任意值,表示训练已完成。
使用 TF.js 模型进行预测
训练完成后,我们还需要创建一个 API 来调用预测函数并返回预测结果。我们将 API 绑定到 \'/predict\'
路由,并使用 POST
方法发起对该 API 的请求,如下所示:
app.post(\'/predict\', function(req, res) { var test = tf.tensor2d([parseFloat(req.body.sepLen), parseFloat(req.body.sepWid), parseFloat(req.body.petLen), parseFloat(req.body.petWid)], [1,4]); var out = model.predict(test); var maxIndex = 0; for (let i=1;i<out.size; i++){ if (out.buffer().get(0, i) > out.buffer().get(0, maxIndex)){ maxIndex = i; } } ans = \"Undetermined\"; switch(maxIndex) { case 0: ans = \"Setosa\"; break; case 1: ans = \"Virginica\"; break; case 2: ans = \"Versicolor\"; break; } console.log(ans); res.send(ans);});
理解预测 API 的代码非常简单。让我们分部分讨论:
app.post(\'/predict\', function(req, res) {
这一行将 \'/predict\'
路由绑定到 POST
请求方法,并打开处理请求代码块,处理所有对该路由的请求:
var test = tf.tensor2d([parseFloat(req.body.sepLen), parseFloat(req.body.sepWid), parseFloat(req.body.petLen), parseFloat(req.body.petWid)], [1,4]); var output = model.predict(test);
这些行创建了一个 TF.js tensor2d
对象,数据是从客户端接收到的。接着,它在模型上运行 predict
方法,并将结果存储在 output 变量中:
var maxIndex = 0; for (let i=1;i<out.size; i++){ if (out.buffer().get(0, i) > out.buffer().get(0, maxIndex)){ maxIndex = i; } }
这个代码块仅仅是找出在 tensor2d
变量 output 中对应最大元素的索引。记住,在 softmax
激活输出中,最高值对应着预测的索引。
在确定输出的最大索引之后,我们使用一个简单的 switch-case 语句来决定从 API 发送到客户端的输出内容。请求数据也会记录在服务器的控制台中。最后,我们使用以下代码将 Node.js 应用绑定到监听 3000
端口:
app.listen(3000);
接下来,我们将创建一个简单的客户端。
创建一个简单的客户端
为了处理应用程序中的 \'/\'
路由,我们向 index.js
添加以下代码行,它仅渲染一个静态文件 index.html
,该文件位于 public 文件夹中:
app.use(express.static(\'./public\')).get(\'/\', function (req, res) { res.sendFile(\'./index.html\');});
现在,让我们通过以下步骤创建静态的 index.html
文件:
- 首先,创建一个文件夹,
public
,并在其中创建index.html
文件。将以下代码添加到index.html
文件中:
<html> <head> <title>TF.js Example - Iris Flower Classficiation</title> </head> <body> <h1> TF.js Example - Iris Flower Classification </h1> <hr> <p> First, train the model. Then, use the text boxes to try any dummy data. </p> <button id=\"train-btn\">Train</button> <hr><br> <label for=\"sepLen\">Sepal Length: </label> <input type=\"number\" id=\"sepLen\" value=\"1\" /><br> <label for=\"sepWid\">Sepal Width: </label> <input type=\"number\" id=\"sepWid\" value=\"1\" /><br> <label for=\"petLen\">Petal Length: </label> <input type=\"number\" id=\"petLen\" value=\"1\" /><br> <label for=\"petWid\">Petal Width: </label> <input type=\"number\" id=\"petWid\" value=\"1\" /><br> <br> <button id=\"send-btn\" disabled=\"=\"true\">Predict!</button> <hr> <h3> Result </h3> <h4 id=\"res\"></h4> <script src=\"img/jquery.min.js\"></script>
- 在为客户端设置了一个简单的 UI,调用我们使用 TF.js 创建的 API 后,我们准备好定义功能并从客户端部署它们。请注意,
\"/train\"
和\"/predict\"
两个 API 都将通过POST
请求进行调用:
<script> $(\'#train-btn\').click(function(){ $(\'#train-btn\').prop(\'disabled\', true); $(\'#train-btn\').empty().append(\"Training...\"); $.ajax({ type: \'POST\', url: \"/train\", success: function(result) { console.log(result); $(\'#send-btn\').prop(\'disabled\', false); $(\'#train-btn\').empty().append(\"Trained!\"); } }); }); $(\'#send-btn\').click(function(){ var sepLen = $(\'#sepLen\').val(); var sepWid = $(\'#sepWid\').val(); var petLen = $(\'#petLen\').val(); var petWid = $(\'#petWid\').val(); $.ajax({ type: \'POST\', url: \"/predict\", data: {sepLen: sepLen, sepWid: sepWid, petLen: petLen, petWid: petWid}, success: function(result) { console.log(result); $(\'#res\').empty().append(result); } }); }); </script> </body></html>
现在让我们运行 TF.js Web 应用。
运行 TF.js Web 应用
完成所有应用编码后,我们现在准备运行应用程序。首先,打开终端,并将包含 package.json
文件的 tfjs-iris
文件夹设置为工作目录。
运行以下代码行以启动 Node.js 服务器:
node index.js
该命令产生的输出类似于以下截图:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/36c2cc46-bbf1-471e-beb4-5bde0c30efe1.png
现在,随着此输出,服务器在 3000
端口启动,我们可以在浏览器中查看相同内容。打开浏览器并在地址栏输入 http://localhost:3000/
来显示以下输出:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/d9ca1b9a-3a54-4848-be67-d133f21e5e88.png
首先,你必须点击训练按钮以调用\'/train\'
API,这将开始训练,并且按钮会变为禁用状态。一旦预测按钮启用,训练完成,用户就可以向服务器发送虚拟数据进行预测。假设我们选择数据集中的第 50 行数据,并将其发送给服务器,期望的输出是Setosa
。
以下截图展示了我们项目最终版本的一小部分:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/89c50dc0-72c8-4ccf-83db-1e588b47c268.png
我们看到为提供的输入生成了正确的输出。
TF.js 的优点和限制
现在让我们总结一些 TF.js 相比 TensorFlow 的优势,除了我们在本章中已经讨论的那些:
-
自动 GPU 支持:使用 TF.js 时,你无需单独安装 CUDA 或 GPU 驱动程序即可利用系统中的 GPU。这是因为浏览器本身实现了 GPU 支持。
-
集成:将 TF.js 集成到使用 Node.js 的 Web 开发项目中相当简单,然后将预训练模型导入到项目并在浏览器中运行它们。
然而,它也有几个缺点,无论何时开发用于生产的时候都需要牢记。其中一些如下:
-
速度:TF.js 适合小数据集。在大规模数据集上,计算速度显著下降,几乎慢了 10 倍。
-
缺少 TensorBoard:这个伟大的工具,用于可视化 TensorFlow 模型,在 JavaScript 版的框架 TF.js 中缺失,因为 TF.js 仅仅是一个 API。
-
API 的支持不完整:并非所有 TensorFlow 的 API 在 TF.js 中都可用,因此在开发 TF.js 时,您可能需要重新考虑代码逻辑或创建自己的函数来使用某些功能。
总结
在这一章中,我们学习了使用 TF.js 创建模型是多么容易。你不仅可以使用整个 JavaScript 生态系统,而且还可以使用 TF.js 中的所有预训练 TensorFlow 模型。我们使用鸢尾花数据集开发了一个简单的 Web 应用程序,在此过程中,我们了解了 TF.js 提供的几个组件。到目前为止,我们已经构建了两个简单的端到端基于深度学习的 Web 应用程序。
我们的进展确实显而易见。在接下来的章节中,我们将构建我们自己的深度学习 API,并使用它们创建智能 Web 应用程序。但在此之前,让我们在下一章中对 API 的整体概念有所了解。
第七章:使用不同深度学习 API 进行网页开发入门
本节讲解了 API 在软件开发中的一般使用,并展示了如何利用不同的最先进深度学习 API 来构建智能网页应用。我们将涵盖包括自然语言处理(NLP)和计算机视觉在内的领域。
本节包括以下章节:
-
第五章,通过 API 进行深度学习
-
第六章,在 Google Cloud 平台上使用 Python 进行深度学习
-
第七章,在 AWS 上使用 Python 进行深度学习:物体检测与家居自动化
-
第八章,在 Microsoft Azure 上使用 Python 进行深度学习
第八章:通过 API 进行深度学习
到目前为止,我们已经熟悉了深度学习项目中遵循的基本流程。在之前的章节中,我们使用 Keras 和 TensorFlow.js 库完成了两个基本的端到端项目。我们已经熟悉了 Python 库,如 NumPy、pandas 和 Keras,我们也看到如何使用 JavaScript 开发深度学习模型。我们还使用 Flask 框架将深度学习模型转换成 API。在 第四章,开始使用 TensorFlow.js 中,我们使用了第三方 应用程序编程接口(API)来创建 web 应用程序。
在本章中,我们将详细学习 API 的整个概念。从 API 的一个非正式定义开始,我们将探讨所有与深度学习相关的 API。我们首先会看看一些广为人知的深度学习 API,然后再了解一些鲜为人知的深度学习 API。我们还将学习如何选择深度学习 API 提供商。
在本章中,我们将涵盖以下主题:
-
什么是 API?
-
API 与库有什么不同?
-
一些广为人知的深度学习 API
-
一些鲜为人知的深度学习 API
-
选择深度学习 API 提供商
什么是 API?
让我们首先考虑一个问题场景。
假设你正在开发一个需要集成图像识别模块的 web 应用程序。但是你对计算机视觉和深度学习并不熟悉,你有一个非常严格的项目截止日期。你不能花时间去学习深度学习然后再完成图像识别模块的开发。你现在应该怎么办?你的项目能按时完成吗?
当然不能!然而,借助 API 的力量,你将能够轻松地将图像识别模块集成到你的 web 应用程序中。现在,让我们更详细地讨论一下 API 的概念。
API 是一组函数(虽然从技术上讲,一个 API 也可以只包含一个函数),可以集成到应用程序中执行特定任务。通常,作为开发者,我们会希望将我们喜欢的网站上的某些实用工具集成到我们自己的应用程序中。例如,Twitter 提供了一个 API,用于检索与特定关键词匹配的推文。我们可以使用这个 API 来收集数据,分析数据,最终得出一些有趣的见解。
像 Facebook、Google、Stack Overflow 和 LinkedIn 等公司提供了用于特定任务的 API,对于开发者来说,了解这些 API 非常值得。API 几乎可以类比为网站。当我们点击网站中的某个内容时,我们会被重定向到另一个页面/部分。在大多数情况下,我们会看到一个网页作为输出。但是 API 通常不会生成好看的网页作为输出。API 的设计目的是在代码中使用,它们的输出通常是某种流行的数据交换格式,如 JSON 或 XML。然后,输出会根据应用程序的需求进行处理。API 让您通过提供一套实用工具或一个生态系统来完成您想做的任务,而无需担心细节问题。
如今,您可以测试一个 API,而无需编写一行代码。例如,您可以使用像 Postman 这样的 API 客户端,测试您喜欢的开放 API,而无需编写任何代码来实现这一点。
API 更神奇的一点在于,您可以用 Java 编写代码,并使用一个用 Python 开发的 API。这在团队协作中尤为有用,尤其是当团队成员对使用的编程语言非常讲究时。一个团队成员可能非常熟悉 Java,而另一个成员则可能是 Python 专家。因此,在这些情况下,API 的概念非常实用。
我们接下来将讨论一些由 Google AI、Facebook AI Research 等公司提供的深度学习 API。我们将在接下来的章节中看到如何使用这些 API 来开发智能 web 应用。
使用 API 的重要性
除了在需要快速生产或最小工作产品演示时,节省您大量的精力来创建和部署自己的深度学习模型外,API 还可以带来以下几种好处:
-
标准、稳定的模型:
- 深度学习的 API 通常是由一整个开发者团队共同创建的,这些开发者使用行业标准的技术和研究工具,而这些工具可能并不是所有开发者都能接触到的。此外,通过商业 API 部署的模型通常非常稳定,提供了最先进的功能,包括可扩展性、定制性和准确性。因此,如果您在准确性方面遇到问题,这是深度学习模型中常见的情况,选择 API 是一个不错的选择。
-
高性能模型:
- 商业深度学习 API 通常运行在非常强大的服务器上,并经过高度优化,能够非常快速地执行任务。因此,如果您希望加速深度学习生态系统的学习,这类 API 非常方便。
-
开发者的共同平台:
- 虽然从零开始编写代码非常简单,但当最初编写代码的人离开并且没有提供适当的文档,而新的人必须接手时,事情就变得很难了。商业 API 定义了一套标准操作,使用这些 API 构建的应用程序容易维护,因为 API 提供商通常会提供详尽的文档,意味着开发者可以事先了解 API。
-
定期和无缝更新:
- 对于一个处于初创阶段的公司来说,一旦他们开发出了第一个版本的深度学习模型,尤其是当他们的整个商业模式并不完全以人工智能为中心时,承担开发时间以改进深度学习模型往往是昂贵的。任何类似的应用场景都会从 API 的使用中大大受益,因为 API 是由那些定期推送更新和新功能的人来维护的。
考虑到这一切,使用 API 能够提供最新的技术、高性能和不断发展的模型,这些模型可以一次集成到应用程序中,并且多年使用而不必再考虑这些 API。
现在,你可能会问 API 和库有什么区别。让我们在下一节中解答这个问题。
API 和库有什么不同?
如今,库和API这两个术语经常互换使用。它们之间有许多相似之处,但在许多方面也有所不同。就像 API 一样,库也提供了一组函数和类,可以根据需要使用。以下是一些帮助你区分库和 API 的要点:
-
库通常是特定于编程语言的。例如,如果你使用 PHP 编程环境,就无法使用 SciPy Python 库。然而,你可以开发一个使用 SciPy 的 API,然后通过 PHP 代码调用这个 API。
-
开发者无法直接访问 API。API 的使用方式与库有所不同。许多 API 在开发者实际使用之前要求进行某种身份验证。而当使用库时,这种情况并不常见。你可以轻松地重载和重写库的函数或类,并根据自己的需要使用它们。
-
库和 API 可以一起使用。许多库内部使用不同的 API,反之亦然。
这些应该能让你对库和 API 之间的基本区别有一定的了解。不过,如果你仍然觉得难以区分,不用担心:我们会看很多例子,到你看完这些例子时,你一定能够区分 API 和库。
现在,我们将介绍一些广泛用于开发深度学习应用程序的 API,其中一些非常知名,另一些则不那么流行。
一些广为人知的深度学习 API
在本节中,我们将看看一些最广泛使用的 API,这些 API 部署在多种深度学习任务中,如图像识别、从图像中检测情感、情感分类、语音转文本转换等。为了限制本节的讨论,我们将深度学习任务分为两个大类:
-
计算机视觉和图像处理
-
自然语言处理
然后,我们将列出与这些分类相关的一些常见任务,并讨论可以用来完成这些任务的 API。
现在我们快速列出一些常见的深度学习任务,并将其归类:
-
计算机视觉和图像处理:
-
图像搜索:就像 Google 搜索一样,图像搜索引擎允许我们搜索与某一特定图像相似的图像。
-
图像检测:这是检测图像内容的功能,也被称为标签检测。
-
对象定位:给定一张包含多个不同对象的图像,这涉及检测图像中特定的对象。
-
内容审核:给定一张图像,这涉及检测图像中的不当内容。
-
图像属性提取:给定一张图像,这涉及提取图像的不同特征。
-
-
自然语言处理:
-
词性标注:给定一段文本,这涉及提取该文本中包含的词性。
-
主题摘要:给定一段文本,这涉及确定该文本所涉及的主题。
-
情感分类:给定一段文本,这涉及预测该文本所传达的情感。
-
命名实体识别:这涉及自动识别给定句子中的不同实体。
-
语音转文本转换:这涉及从语音中提取包含的文本。
-
这里列出的所有任务在我们的日常生活中都极为有用,令人兴奋的是,我们可以利用即将讨论的 API 开发出能为我们完成这些任务的应用程序。
还有其他用于大规模推理的深度学习 API,但暂时我们可以忽略它们,集中讨论两大最受深度学习影响的领域。
以下表格汇总了一些在行业中最广泛使用的深度学习 API:
上表中显示的是使用过的、经过良好测试并且具有可扩展性的最流行的深度学习 API。然而,还有一些其他名字虽然还未像这些一样流行,但也正在成长。在下一节中,我们将看看它们。
一些较少为人知的深度学习 API
下表给出了一些较少为人知的 API 的详细信息:
现在,在这片广阔(嗯,几乎)API 的海洋中,如何为特定任务选择一个特定的提供商呢?这可能会很棘手,需要深入讨论。在本节中,我们将讨论一些策略,帮助我们有效地做出这些决定。
选择深度学习 API 提供商
在长长的深度学习 API 提供商列表中,选择所需的 API 可能是一个令人生畏的任务。然而,你可以遵循一些简单的规则,帮助你找到最适合你需求的 API,我们将在这里详细讨论其中的一些规则:
-
平台:
-
听起来很简单,但在选择 API 提供商时,这可能是最重要的因素。大多数情况下,如果你正在开发一个基于 Google 技术的产品,例如,你可能会倾向于使用 Google 提供的深度学习 API,因为它们与开发应用程序的接口能够无缝集成。
-
更多时候,开发环境还提供使用其深度学习 API 的模板化解决方案,设置起来非常简单。有时,提供商还会为使用其 API 开发新产品提供额外的奖励。
-
-
性能:
- 在可以访问多个提供商的 API 来执行单一任务时,你可以比较它们的性能后进行选择。在这种情况下,选择比较和评判不同 API 时使用的度量标准由你决定。
-
成本:
- 不同的提供商使用不同的计费方式,这在决定使用哪个提供商时起着至关重要的作用。某个提供商可能对免费 API 调用次数有一个相对宽松的限制,因此可能是一个很有吸引力的选择。开发者和学生通常选择那些在成本方面最具优势的提供商进行试验。
除了这三个因素,还有一些其他不可忽视的因素,比如公司要求使用某个特定的 API 或者你自己对某个 API 提供商的偏好。然而,除非是大规模应用,否则所选择的提供商通常没有太大影响,因为它们在中小规模的使用中提供的性能差异并不明显。
总结
在本章中,我们详细讨论了术语 API。在第三章,创建你的第一个深度学习 web 应用程序中,我们看到了如何使用 Flask 在 Python 中编写 API,并且了解了如何在 web 应用程序中使用该 API。现在我们知道了 API 与语言库的区别,以及利用 API 的重要性。我们也熟悉了一些顶级组织提供的各种深度学习 API。
随着我们继续深入接下来的章节,我们将看到如何利用这些 API 来构建强大且智能的 web 应用程序。我们将在下一章开始使用 Google Cloud Platform 提供的深度学习 API。
第九章:在 Google Cloud Platform 上使用 Python 进行深度学习
在上一章,我们看到了一些由各个组织提供的深度学习 API。我们还看到它们的应用范围大致可以分为两类——第一类是计算机视觉和图像处理,第二类是自然语言处理。我们将在本章继续探索深度学习 API。本章将介绍 Google Cloud Platform (GCP) 及其在深度学习领域提供的三个 API。
本章我们将涵盖以下主题:
-
设置你的 GCP 账户
-
在 GCP 上创建你的第一个项目
-
在 Python 中使用 Dialogflow API
-
在 Python 中使用 Cloud Vision API
-
在 Python 中使用 Cloud Translation API
技术要求
你可以从 github.com/PacktPublishing/Hands-On-Python-Deep-Learning-for-Web/tree/master/Chapter6
获取本章的代码。
要运行本章的代码,你的系统需要安装 Python 3.6 及以上版本。
本章过程中还会介绍其他必需的安装。
设置你的 GCP 账户
在使用 GCP 提供的 API 之前,你必须先设置 GCP 账户。假设你已经有一个 Google 账户——首先,前往 cloud.google.com/
。如果你是第一次注册 GCP,GCP 会提供 $300 的信用额度(有效期为 12 个月);这笔信用额度足够支持许多良好的项目并让你试用 GCP 的服务。完成后,我们可以按照以下步骤操作:
- 在 GCP 首页的右上角,你应该能找到一个“免费试用”按钮。点击它:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/8d0065fb-e97a-457a-bca4-8a70e70fa661.png
- 如果你尚未登录 Google 账户,系统会要求你登录。根据提示选择你的国家,并确保勾选服务条款框。之后,点击同意并继续。你会看到如下截图页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/c2b7f7a6-bbb5-4daf-8a80-e52ef7edd315.png
- 然后,系统会要求你输入所选择的支付方式的详细信息。即使你有免费的信用额度,为了使用 GCP 的服务,你也需要设置一个有效的计费账户。但不用担心,除非你允许 GCP 否则不会从你的计费账户中扣费。在免费试用期间,你在 GCP 上使用的所有计费服务将仅从你的免费信用额度中扣除。一旦免费信用额度用尽,GCP 会向你发送提醒。
完成计费手续后,你应该会进入 GCP 的控制台页面,界面如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/469c0188-c363-4a28-a15f-d060ca342a01.png
这是你的 GCP 仪表板,它会给你一个 GCP 使用情况的总体概览。GCP 还允许你自定义在控制台上显示的标签。
现在你应该已经完成了 GCP 账户的设置。为了能够使用 GCP 中的工具,你需要创建一个带有有效计费账户的 GCP 项目。在接下来的章节中,你将看到如何操作。
在 GCP 上创建你的第一个项目
项目帮助你系统地组织所有的 GCP 资源。创建 GCP 项目只需几个点击步骤:
- 在登录你的 Google 账户后,使用
console.cloud.google.com
打开 GCP 控制台。在左上角,你应该看到 Google Cloud Platform,并且就在旁边,你可以看到一个下拉列表,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/97baa6ef-0c5a-4258-b4d2-f1910f97cc82.png
- 如果你在注册 GCP 时或之前创建了任何项目,那么你的项目将出现在标记区域(我在 GCP 上创建了 fast-ai-exploration 和 gcp-api 两个项目)。现在,点击下拉箭头,应该会弹出一个窗口:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/d3f3ccc7-fc1e-4338-9fb3-f5704b19b0f7.png
- 点击 “NEW PROJECT” 继续。你将进入一个页面,如下图所示,页面会要求你指定项目名称。GCP 会自动为你创建项目的 ID,但你也可以根据自己的需求编辑该 ID:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/d1652d62-c16c-4b05-b638-cbbaaebcb4b0.png
- 在你指定了项目的初步细节后,只需点击 “CREATE” 项目即可创建。创建完成后,项目应该会出现在项目列表中。你可以随时通过 GCP 控制台页面提供的下拉菜单访问该列表。你可以在下图中看到这个界面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/eec5591a-a3f9-4e1a-b6aa-bbe3b0be234a.png
如果你想了解更多关于 GCP 项目的信息,可以查看官方文档 cloud.google.com/storage/docs/projects
。GCP 提供了一整套广泛的实用工具,你可以在 cloud.google.com/products/
找到它们。我们鼓励你查看并根据个人兴趣进行探索。
GCP 为我们提供了广泛的 API,可以用于多种任务,包括深度学习。在接下来的几个章节中,我们将看到如何使用 Python 代码调用一些最常用的深度学习 API。我们将从 Dialogflow 开始。
在 Python 中使用 Dialogflow API
在我们开始学习如何在 Python 中使用 Dialogflow API 之前,让我们先了解一下 Dialogflow 是什么。
Dialogflow(前身为api.ai)提供了一套用于构建自然且丰富的对话界面的工具,如语音助手和聊天机器人。它由深度学习和自然语言处理技术驱动,并被大量公司使用。它与网站、移动应用程序以及许多流行的平台(如 Facebook Messenger、Amazon Alexa 等)无缝集成。Dialogflow 为我们提供了构建对话式用户界面的三个主要组件:
-
可以轻松应用于任何对话式用户界面的最佳实践和流程
-
添加任何构建对话式用户界面所需的自定义逻辑的功能
-
用于训练代理的功能,以便优化界面的整体体验
现在,我们将看到如何使用 Dialogflow 创建一个简单的 Python 应用程序。您可以访问 dialogflow.com
了解更多关于 Dialogflow 的信息。
我们将从创建一个 Dialogflow 帐户开始。
创建一个 Dialogflow 帐户
创建一个 Dialogflow 帐户非常简单。整个过程包含以下步骤:
- 访问
console.dialogflow.com/api-client/#/login
,您将看到以下界面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/397707d9-086c-4cdf-902b-4ec2d5944ec1.png
-
点击“使用 Google 登录”按钮后,系统将要求您选择一个要与 Dialogflow 一起使用的 Google 帐户。
-
选择帐户后,可能会要求您允许 Dialogflow 的帐户权限,并接受 Dialogflow 的条款和条件。
创建一个新代理
创建帐户后,您将看到一个仪表板,仪表板将显示您的活动 Dialogflow 项目,或者提示您创建一个新的代理并进行显示——但是,什么是代理呢?
代理——在 Dialogflow 的术语中——是一个软件,负责接收用户输入,这些输入可能是文本、音频、图片或视频格式。然后,它尝试确定意图,即与输入对应的预定义的适当操作。匹配的意图可能会执行一个动作,或者仅仅返回一个超文本响应,回应用户的查询。最后,代理将结果返回给用户。
要创建一个新代理,请在 Dialogflow 控制台的左侧导航菜单中点击“创建代理”。
您将看到如下所示的界面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/9023d9b6-88bb-447f-aeb6-17b44aae03b8.png
我们将代理命名为 DemoBot,并将默认语言设置为英语。此外,我们还需要为该代理选择一个 Google 项目。
Google 项目——或简而言之,项目——是你在学习 GCP 时遇到的一个术语。项目包含了为任何使用这些资源的软件项目分配的所有资源,这些资源由 GCP 上的一个单一账单账户进行融资。在没有为资源定义项目的情况下,无法分配任何资源。此外,在没有添加有效账单选项的情况下,无法创建项目。
现在你将能够看到如下截图中显示的界面,其中为你的代理提供了一些默认意图:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/768479fc-f213-41d9-898d-927c60d1869b.png
在左侧,你可以看到导航菜单,提供了所有可以组合在一起,以便软件提供更具人性化交互的各种模块。在右侧面板中,你可以随时测试你的代理,输入任何你提供的内容。这在响应开发和测试输入匹配意图时会非常有用。
创建一个新意图
要为我们的代理创建一个新意图,按照以下步骤操作:
-
点击中间区域右上角的创建意图按钮。
-
你需要为这个意图提供一个名称——我们称之为
Dummy Intent
。 -
然后我们需要提供一些训练短语,这些短语会触发此意图。假设我们提供了三个训练短语,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/a4a2458f-1671-4689-b374-e77d590feef0.png
现在,我们可以预期,当系统遇到训练中提到的短语(或类似短语)时,这个意图会被调用。
- 现在我们可以添加一些响应,当这个意图被调用时,代理将作出响应,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/384b2f86-2a4f-40e0-8d34-b77951aa764d.png
- 在中间区域的右上角,点击保存按钮以保存新意图,系统会通知你代理训练已开始。
对于一个小型代理,训练在几秒钟内完成,系统会显示“代理训练完成”的通知。
我们现在准备测试我们的代理是否能够执行这个意图。
测试你的代理
在你 Dialogflow 控制台的右侧区域,你可以测试你的代理。在顶部文本框中输入你的查询。在我们的代理中,调用Dummy Intent
时,我们输入Talk to the dummy
。
如果意图正确匹配,你将能够看到来自Dummy Intent
的响应,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/9846d629-256f-4200-a012-02f6dba24730.png
在前面的截图中,你会看到用户的输入是Talk to the dummy
,生成的响应是我们为Dummy Intent
定义的两个响应之一。你可以看到,匹配到输入的意图是Dummy Intent
。
现在我们来看看如何使用 Python 调用代理。
安装 Dialogflow Python SDK
在本节中,我们将演示如何使用 Dialogflow Python API V2 与您的 Dialogflow 代理配合使用,将互动性带入您使用 Python 构建的应用程序。首先,让我们通过以下图表理解 DialogFlow 生态系统的多个组件如何交互:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/48741d83-0b89-4933-a7f4-df36291f5f9a.png
用户创建输入内容,并通过集成 API、网站或应用将其发送给代理。代理将用户输入与可用的意图进行匹配,并生成 查询 的响应。响应通过 Webhook 发送回用户界面,并展示给用户。
集成 API 很可能会包含 Dialogflow 以外的服务。您可以创建一个应用程序,将相同的用户查询传播到多个代理,并汇总它们的响应。
或者,开发者可以引入中间件处理程序或集成,这些程序会对用户查询和代理响应进行预处理或后处理:
- 要安装 Dialogflow Python SDK,我们在终端使用以下命令:
pip install dialogflow
强烈建议在使用之前的命令之前,使用 virtualenv
创建一个虚拟环境,以便拥有干净且不间断的依赖关系。要了解有关 virtualenv
的更多信息,请参考 virtualenv.pypa.io/en/latest/
。
- 安装完成后,您可以使用以下导入代码将 Dialogflow API 导入到您的项目中:
import dialogflow
现在我们将创建一个 GCP 服务账户来认证我们的 Python 脚本,以便使用我们创建的 Dialogflow 代理。
创建 GCP 服务账户
GCP 服务账户管理用于访问 GCP 资源的权限。我们创建的 Dialogflow 代理是一个 GCP 资源,因此要通过 Python API 使用它,我们需要一个服务账户:
-
在 GCP 控制台中,从左侧导航菜单中,前往 APIs | Services | Credentials。
-
点击“创建凭证”按钮,获取以下选项:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/6bbe0df1-e132-459f-bc1b-f48cfb9be413.png
-
点击“服务账户密钥”。在接下来的页面中,选择 Dialogflow 集成作为服务账户,JSON 作为密钥类型。点击“创建”后,一个 JSON 文件将下载到您的计算机。
-
记下此 JSON 文件的地址,例如
/home/user/Downloads/service-account-file.json
。文件名可能会有所不同,因为它是由 GCP 控制台在您下载文件到计算机时提供的。 -
打开此文件以获取项目 ID。
-
现在,在终端使用以下命令——根据您系统上的实际情况进行适当替换——将凭证导出到环境变量中:
-
- 在 Linux(终端)中:
export GOOGLE_APPLICATION_CREDENTIALS=\"\"export DIALOGFLOW_PROJECT_ID=\"\"
-
- 在 Windows(命令提示符)中:
set GOOGLE_APPLICATION_CREDENTIALS=<your_service_account_file_location>set DIALOGFLOW_PROJECT_ID=<your_project_id>
完成此步骤后,我们现在准备编写调用 Dialogflow 代理的 Python 脚本。
请注意,上述命令仅设置当前会话的变量。每次重新启动会话时,您需要运行这些命令。
使用 Python API 调用 Dialogflow 代理
在这个示例中,我们将创建一个简单的基于 Python 的 API,调用我们在 Dialogflow 控制台中创建的代理来调用 Dummy Intent
,如下面所示:
- 首先,我们必须将 Dialogflow 模块导入项目。为此,请使用以下代码:
import dialogflow
- 要将项目 ID 引入脚本中,我们可以从运行时环境变量中获取它。为此,请使用以下代码:
import osproject_id = os.getenv(\"DIALOGFLOW_PROJECT_ID\")
- 我们还将声明一个唯一的会话 ID,以存储与用户进行的任何单个会话的对话记录:
session_id=\"any_random_unique_string\"
- 现在我们将创建一个方便的函数,允许我们反复执行一组调用 Dialogflow 代理所需的预处理语句:
def detect_intent(project_id, session_id, text, language_code): session_client = dialogflow.SessionsClient() session = session_client.session_path(project_id, session_id) text_input = dialogflow.types.TextInput(text=text, language_code=language_code) query_input = dialogflow.types.QueryInput(text=text_input) response = session_client.detect_intent(session=session, query_input=query_input) return response.query_result.fulfillment_text
在上述代码中,我们首先初始化一个 SessionsClient
对象。会话记录用户与 Dialogflow 代理在一次不间断对话中的完整互动。接下来,我们必须设置会话路径,即将项目映射到一个唯一的会话 ID。
上面函数定义的接下来的两行代码用于创建一个包含 Dialogflow TextInput
对象的 QueryInput
对象。query_input
变量保存用户输入的消息,用于 Dialogflow 代理。
下一行代码调用了 SessionsClient
对象的 detect_intent()
方法。会话 ID-项目 ID 映射及输入作为参数传递给该方法。Dialogflow 代理的响应存储在响应变量中。该函数返回满足文本响应。
- 现在让我们使用这个方法。首先,声明一个消息并传递给 Dialogflow 代理。回想一下我们为
Dummy Intent
提供的训练短语。我们将传递一个类似于训练短语的消息:
message = \"Can I talk to the dummy?\"fulfillment_text = detect_intent(project_id, session_id, message, \'en\')print(fulfillment_text)
我们将获得一个输出,它是我们为 Dummy Intent
定义的两个响应之一。
- 在
detect_intent()
方法中生成响应变量,可以通过在detect_intent()
函数中添加以下代码行来实现:
def detect_intent(project_id, session_id, text, language_code): ... response = session_client.detect_intent(session=session, query_input=query_input) print(response) ### <--- ADD THIS LINE return response.query_result.fulfillment_text
您将获得以下 JSON:
response_id: \"d1a7b2bf-0000-0000-0000-81161394cc24\"query_result { query_text: \"talk to the dummy?\" parameters { } all_required_params_present: true fulfillment_text: \"Congratulations, dummy intent user!\" fulfillment_messages { text { text: \"Congratulations, dummy intent user!\" } } intent { name: \"projects/gcp-api-232806/agent/intents/35e15aa5-0000-0000-0000-672d46bcefa7\" display_name: \"Dummy Intent\" } intent_detection_confidence: 0.8199999928474426 language_code: \"en\"}
您将观察到,匹配到的意图名称是 Dummy Intent
,而我们在这次调用代理中获得的输出是 恭喜,虚拟意图用户!
。
使用 Python 调用 Dialogflow API 的方式有很多种,包括—但不限于—音视频输入和基于传感器的输入。Dialogflow 代理可以与主要平台集成,例如 Google Assistant、Facebook Messenger、Slack、Telegram、WhatsApp 等,具体如下:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/1d530c5f-6145-41e3-8de2-e80c9a4b511e.png
Dialogflow 生态系统正在快速推出新功能,并且越来越朝着提供能够同时执行多项任务的基于 AI 的完整聊天机器人方向发展。
在接下来的章节中,我们将探索另一个可以用于预测图像和视频内容的 GCP API。
在 Python 中使用 Cloud Vision API
计算机视觉是使计算机理解图像并从中提取信息的领域。常见的计算机视觉任务包括图像分类、图像检测、图像分割等。如前几章所述,计算机视觉领域受到深度学习在实现人类水平(有时甚至更好)性能方面的有效性影响很大。
Cloud Vision API 提供了许多工具来执行计算机视觉任务。Cloud Vision 允许我们使用预训练模型,也可以构建我们自己的定制化生产就绪模型,以满足我们的需求(例如 AutoML Vision Beta)。现在让我们简要看看 Cloud Vision API 提供的功能:
-
标签检测
-
光学字符识别
-
手写识别
-
地标检测
-
物体定位
-
图像搜索
-
产品搜索
除了前面提到的功能,Cloud Vision 还允许我们提取给定图像的不同属性。下图展示了这个功能:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/278c72a8-1139-4273-a4e3-2d4f2274343d.png
如我们所见,当提供一张图像时,Cloud Vision API 会自动提取其属性。你也可以通过访问cloud.google.com/vision/
来尝试这个功能。
我们之前在章节中提到过预训练模型这一术语。我们也看到,Cloud Vision API 让我们能够使用这些预训练模型。深入了解“预训练模型”这一术语非常值得,这有助于我们理解使用它们的重要性。
使用预训练模型的重要性
使用预训练模型通常被称为迁移学习。迁移学习并不是深度学习中非常基础的内容,它只是一种方法论。它并不指代某个特定的深度学习模型,但迁移学习的含义在深度学习中非常有效,尤其是在深度学习的背景下。
我们人类并不是从零开始学习每一项任务;我们尝试利用过去的经验来完成类似的任务。这就是迁移学习。我们倾向于将过去经验的知识转移到我们遇到的相似任务中。
但这如何应用于深度学习呢?让我们来看看。
当神经网络为某个特定任务进行训练时,它会试图估计最佳权重矩阵的值。现在,当你尝试为类似任务训练另一个网络时,事实证明你可以使用之前任务的权重。在这里,“相似性”的定义很宽泛,可以暂时忽略不提。但你可能会好奇,这里有什么优势。好吧,优势是多方面的,下面是几个例子:
-
你不需要从头开始训练神经网络,这为你节省了大量时间。
-
它利用了使用与你的任务相似的领域问题的最先进成果的机会。
在文献中,你使用网络权重的任务被称为源任务,你应用权重的任务被称为目标任务。你使用权重的网络模型被称为预训练模型。Goodfellow 等人在其著作《Deep Learning》中对迁移学习给出了非常微妙的定义:
“[A] 在一个环境中学到的知识被用来改善另一个环境中的泛化能力。”
迁移学习在自然语言处理(NLP)、计算机视觉等深度学习应用中已展现出卓越的成果。然而,迁移学习也有其局限性:
-
当源任务与迁移学习所用任务没有充分的相关性时,迁移学习可能会导致性能下降。
-
有时候很难确定从源任务到目标任务需要多少迁移。
为了深入研究迁移学习,推荐你阅读 Dipanjan 等人所著的《Hands-On Transfer Learning with Python》一书。接下来,我们将通过一个示例学习如何使用 Python 使用 Cloud Vision API。
设置 Vision Client 库
Cloud Vision API 通过一组适用于不同编程语言的库提供,这些库被称为 Vision Client 库。
该系列库中提供的一个库是 Python Cloud Vision Client 库,我们将在示例中使用它:
- 要安装 Python Cloud Vision Client 库,我们在终端中使用以下命令:
pip install --upgrade google-cloud-vision
强烈建议使用 Python 虚拟环境来安装 Vision Client 库。
-
安装完成后,我们需要设置一个服务账户来使用 API。
-
如前所述,设置服务账户的步骤如下:
-
打开 Google Cloud 控制台。
-
进入“APIs | Services | Credentials”。
-
点击“创建凭证”。
-
在下拉菜单中选择“新建服务账户”以选择服务账户。
-
为服务账户填写任何名称。
-
取消勾选“角色”。在使用 Cloud Vision API 时不需要此项设置。
-
点击“创建”。确认任何出现的警告框。
-
service account credentials
JSON 文件会被下载到你的计算机中。
-
-
现在,像之前一样,将下载的文件导出到系统环境中。为此,使用以下命令:
-
- 在 Linux(终端)中:
export GOOGLE_APPLICATION_CREDENTIALS=\"/home/user/Downloads/service-account-file.json\"
-
- 在 Windows(命令提示符)中:
set GOOGLE_APPLICATION_CREDENTIALS=/home/user/Downloads/service-account-file.json
-
在使用 Cloud Vision API 之前的最后一步,我们需要在创建服务账户的项目中启用该 API。为此,请执行以下操作:
-
在 Google Cloud 控制台的左侧导航面板中,点击“APIs 和 Services”。
-
点击“启用 APIs 和 Services”。
-
在出现的列表中找到 Cloud Vision API。
-
点击“启用”。
-
在此之后,我们准备好在脚本中使用 Python 调用 Cloud Vision API。
使用 Python 调用 Cloud Vision API
让我们创建一个新的 Python 脚本(或 Jupyter notebook)。为了使用 Cloud Vision API,我们首先需要导入 Cloud Vision 客户端库。
- 为此,我们使用以下代码:
from google.cloud import vision
- 有了这些,我们就准备好继续使用客户端库了。在我们的示例中,我们将对一张图像进行标注。图像标注服务是通过 Vision 库中的
imageAnnotatorClient()
函数提供的。我们将创建该方法的一个对象:
client = vision.ImageAnnotatorClient()
- 现在,让我们将要进行标注的文件加载到程序中:
with open(\"test.jpg\", \'rb\') as image_file: content = image_file.read()
请注意,test.jpg
文件应该与工作目录中的其他文件放在同一位置,才能正常工作。
- 该文件目前是程序的原始二进制数据文件。为了让 Cloud Vision API 正常工作,我们需要将其转换为 Vision 客户端可以接受的图像类型:
image = vision.types.Image(content=content)
- 最后,我们通过 Cloud Vision API 调用 GCP 来对图像进行标注:
response = client.label_detection(image=image)labels = response.label_annotations
打印由 Vision API 设置的标签后,我们将能够看到 Cloud Vision API 能够在提供的图片中检测到的所有可能的物体和特征,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/20979113-d6cc-4b94-be0e-1fc2f49ba1c0.png
如果打印 labels
,结果应该如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/fccb87ea-584c-4f34-8559-40f1e95c5206.png
预测的标签是 Sky
(天空)、Horizon
(地平线)、Atmosphere
(大气)、Sunrise
(日出)、Sunset
(日落)、Morning
(早晨)、Ocean
(海洋)、Calm
(平静)、Wing
(机翼)和 Evening
(傍晚)。
上述预测结果非常接近前面照片中捕捉到的实际场景。那是日出时分,从飞机的窗户拍摄的照片。
在 Python 中使用 Cloud Translation API
Cloud Translation API 帮助开发人员轻松将语言翻译功能集成到他们的应用程序中。它由先进的神经机器翻译技术提供支持,可以将其视为深度学习和机器翻译的结合体。Cloud Translation API 提供了使用预训练模型和构建生产级自定义模型的编程接口。
许多开发人员使用 Cloud Translation API 的预训练模型动态将给定文本翻译成目标语言。Cloud Translate API 支持 100 多种语言。但是这个语言库正在不断发展,以增强开发者社区的能力。以下截图展示了将一段英文文本翻译成孟加拉语的例子:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/eb0bdcce-a7ea-47a3-bd8f-4f49cb6251a6.png
你可以随时在 cloud.google.com/translate/
上尝试这个功能。但是有时,给定文本的语言本身可能是未知的。Cloud Translation API 提供了一项叫做 标签检测 的服务来处理这种情况。
Cloud Translation API 的 AutoML 变体允许我们根据需要构建针对语言对(源语言和目标语言)的自定义模型。
设置 Cloud Translate API 以供 Python 使用
要在 Python 中使用 Cloud Translation API,首先我们需要安装 Google Cloud Translate Python 库。
- 为此,请在终端中使用以下
pip
命令:
pip install google-cloud-translate
-
现在,像之前一样,创建一个服务账户并下载凭证文件。将此文件导出到
GOOGLE_APPLICATION_CREDENTIALS
环境变量的路径中。 -
接下来,在启用的 API 列表中找到
Cloud Translate API
。完成后,我们就可以直接通过 Python 使用 GCP 进行翻译。
使用 Google Cloud Translation Python 库
创建一个新的 Jupyter 笔记本或 Python 脚本。接下来,我们将把 Google Cloud Translate API 导入到我们的项目中。
- 为此,请使用以下代码:
from google.cloud import translate_v2 as translate
- 我们需要创建一个 Cloud Translate API 对象来进行服务调用。我们可以按如下方式操作:
translate_client = translate.Client()
- 现在,让我们开始翻译过程。首先,我们需要一条要翻译的消息:
original = u\'नमस्ते\'
这将创建一个包含单词 Namaste(印度语问候语)的 Unicode 字符串。让我们看看它转换成英语是什么!
我们使用以下代码调用 API 将文本翻译成英语:
translation = translate_client.translate(original, target_language=\"en\")
如果你观察 translation
变量,你会发现它包含了以下详细信息:
{ \'translatedText\': \'Hello\', \'detectedSourceLanguage\': \'hi\', \'input\': \'नमस्ते\'}
从这个字典中可以简单地推断出检测到的语言是印地语(用 hi
表示)。输入以其输入格式显示。translatedText
存储了 Hello
,这是 Namaste 的准确翻译。
总结
在本章中,我们探讨了 GCP 提供的一些著名且具有突破性的基于深度学习的服务。我们学习了如何使用 Python 的 Dialogflow 构建能够随着时间学习的对话型聊天机器人。我们使用 Cloud Vision API 来预测任何图像中识别到的物体。我们可以轻松地将此方法扩展到视频中,并获得类似的结果。最后,我们介绍了 Cloud Translate API,通过该服务进行深度基于 NLP 的翻译。GCP 提供的所有主要服务都可以通过 API 访问,这使得它们在任何项目中都易于替换。由高素质专业人员创建的模型的准确性值得称赞,这使得在构建 AI 驱动的 Web 解决方案时,Web 开发者的工作变得更加轻松。
在下一章中,我们将介绍亚马逊网络服务(AWS)提供的功能,使用 Python 将 AI 集成到 Web 应用程序中。
第十章:使用 Python 在 AWS 上进行 DL:对象检测和家庭自动化
我们熟悉了来自 Google Cloud Platform 的几个基于深度学习的产品,并学习了它们如何在第六章中使用 Python 在 Google Cloud Platform 上进行深度学习。现在,我们已经对云计算有了相当好的概述,在本章中,我们将介绍另一个云计算平台,Amazon Web Services(AWS),它也提供一些高性能和高可靠性的基于深度学习的解决方案,以便更轻松地解决问题。在本章中,我们将以 API 的形式介绍其中的两个,并学习如何从 Python 程序中使用它们。
我们将从设置 AWS 账户并在 Python 中配置 boto3 开始。然后,我们将学习如何在 Python 中使用 Rekognition API 和 Alexa API。
在本章中,我们将涵盖以下主题:
-
设置您的 AWS 账户
-
AWS 的简介
-
在 Python 中配置 boto3
-
使用 Python 中的 Rekognition API
-
使用 Python 中的 Alexa API
技术要求
您可以在github.com/PacktPublishing/Hands-On-Python-Deep-Learning-for-Web/tree/master/Chapter7
获取本章的代码。
要运行本章的代码,您需要以下软件:
-
Python 3.6+
-
Python PIL 库
其他安装步骤将在本章中介绍。
在 AWS 开始使用
在使用任何 AWS 服务或 API 之前,您必须创建您的 AWS 账户。在本节中,我们将快速浏览创建 AWS 账户的步骤:
- 首先,打开
aws.amazon.com/
。您应该会看到类似以下的页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/6c5749db-c62e-4e24-b514-9ca21e1afe34.png
- 然后点击“创建 AWS 账户”按钮,将带您到以下页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/69673107-63a9-4cbd-99da-9d9d8fc6876b.png
-
填写字段并点击“继续”。
-
门户将向您索取更多强制信息。它还将要求您注册支付方式以验证您的详细信息。
如果您不提供这些信息,您将无权使用 AWS 设施的免费层。
- 在注册的最后一步,您将被要求在三个计划(免费、开发者和商业)之间选择。根据您的需求选择适当的计划并继续。
像 Google Cloud Platform 一样,AWS 也提供免费层访问。首次注册 AWS 时,您可以免费使用多种 AWS 服务和产品,但只能使用一定的配额。您可以访问aws.amazon.com/free/
了解更多信息。
如果您按照上述步骤进行操作,应该会看到以下页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/5ff22c05-d2b5-4d25-9f60-b37da3ec231c.png
AWS 具有一个很棒的功能,可以为用户推荐解决方案和服务。为了充分利用此功能,您需要输入两项内容——您的角色和兴趣领域。您可以在上图中看到这一点。输入这两个信息并点击“提交”以获取一些定向的产品推荐。
- 下一步是点击“登录到控制台”按钮。
成功登录 AWS 控制台后,您应该会看到如下窗口:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/fe00e39b-59ba-4a1f-a61c-0f67d4cca381.png
AWS 控制台是您可以找到所有 AWS 提供的服务和解决方案的地方。可以随意通过点击“服务”标签浏览完整的服务集合。您也可以通过搜索框查找特定的服务。
到现在为止,我们的 AWS 账户应该已经准备好,可以开始动手了。在接下来的章节中,我们将简要回顾 AWS 的服务,以便更好地了解该平台。
AWS 服务简短概览
AWS 提供了多种领域的服务和解决方案。以下是 AWS 提供的不同类型的模块(括号中的为 AWS 提供的不同服务名称):
-
计算(EC2、Lambda 等)
-
存储(S3、Storage Gateway 等)
-
机器学习(Amazon SageMaker、AWS DeepLens 等)
-
数据库(RDS、DynamoDB 等)
-
迁移与传输(Snowball、DataSync 等)
-
网络与内容交付(CloudFront、VPC 等)
-
开发者工具(CodeStar、CodeCommit 等)
-
机器人技术(AWS RoboMaker)
-
区块链(Amazon Managed Blockchain)
-
分析(Athena、CloudSearch 等)
还有很多其他服务,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/e773d1e1-5b71-45f0-b465-66fc5d2902dd.png
这个列表其实非常广泛,但我们暂时将焦点限制在机器学习(也称为深度学习)服务上。
AWS 控制台中的搜索框还允许您搜索可能已经听说过的 AWS API。让我们在其中输入 Rekognition
并按 Enter。您应该会看到 Rekognition 的主页,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/4df1029c-865e-4d73-8f88-fcb487bf9849.png
我们将在本章稍后的部分详细探讨 Rekognition API。在接下来的章节中,我们将学习如何使用 boto3(一个提供 Python 编程接口的 AWS SDK)与不同的 AWS 资源进行交互。
使用 boto3 入门
boto3 是 AWS 官方提供的库,用于与 AWS API 通信。您可以在 aws.amazon.com/sdk-for-python/
找到该库,并可以通过以下命令安装:
pip install boto3
安装完成后,你需要配置 boto3 以供你的项目使用。配置 boto3 的第一步是从身份和访问管理(IAM)控制台获取你的 AWS 访问密钥。按照以下步骤进行配置:
- 访问你的 AWS IAM 控制台:
console.aws.amazon.com/iam
。页面应该如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/53fc5106-5219-4269-9ace-5c45edc32c8b.png
在上面的仪表板中,你将能够看到访问密钥。
- 点击删除根访问密钥,然后点击管理安全凭证。系统将展示以下窗口:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/3bb72eab-b62e-42b6-9dee-6cd77653770d.png
- 展开**访问密钥(访问密钥 ID 和秘密访问密钥)**标签并从中获取访问密钥。密钥生成成功后,你应该看到如下信息:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/2426808b-f6a7-462d-9692-8162fc50efbd.png
- 下载密钥文件并将其保存在安全的位置,因为在配置 boto3 时需要用到此文件。
配置环境变量并安装 boto3
一旦你获得了访问密钥,创建两个环境变量,aws_access_key_id
和 aws_secret_access_key
。现在,根据你获得的密钥,设置它们的值。密钥包含的信息将帮助你区分密钥 ID 和秘密访问密钥。配置好必要的环境变量后,我们可以开始在 Python 中加载环境变量。
在 Python 中加载环境变量
一旦库成功安装,你可以通过以下代码行加载刚才创建的环境变量:
import osaws_access_key_id= os.environ[\'aws_access_key_id\']aws_secret_access_key = os.environ[\'aws_secret_access_key\']
一旦环境变量正确加载,我们就可以调用 boto3 来与 AWS 资源进行交互。例如,如果你想列出 AWS 账户中的 S3 存储桶,并将一张图片上传到某个存储桶。S3 是你想要访问的 AWS 资源。如果你在 AWS 账户中没有任何 S3 存储桶,不用担心,你可以快速创建一个。
创建 S3 存储桶
你可以通过以下步骤快速创建一个 S3 存储桶:
- 访问 S3 控制台主页:
s3.console.aws.amazon.com/s3
。页面应该如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/2f02b3a1-2449-470f-a1ab-2ee93093e353.png
- 点击创建存储桶。系统会要求你输入以下信息:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/e9399ac7-840c-447c-93be-18677c3b69ea.png
- 为你的存储桶命名,保持其他设置不变,然后点击创建。存储桶创建成功后,你将在 S3 控制台中看到它:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/86871ff5-e121-4939-b639-80c9587e7c56.png
接下来,我们将学习如何使用 boto3 从 Python 代码访问 S3。
使用 boto3 从 Python 代码访问 S3
现在,你可以通过 Python 代码访问你的 S3 存储桶。以下代码行将展示可用的存储桶:
import boto3s3 = boto3.resource( \'s3\', aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key)
你在 resource()
的第一个参数中指定了你有兴趣访问 S3。你可以通过访问 bit.ly/2VHsvnP
来阅读相关文档。现在,你可以通过以下代码找到可用的存储桶:
for bucket in s3.buckets.all(): print(bucket.name)
你应该会得到一个列表作为输出。现在,假设你想将一张图片上传到某个存储桶。如果你想上传的图片就在当前工作目录中,以下代码行应将图像上传到指定的 S3 存储桶:
data = open(\'my_image.jpeg\', \'rb\')s3.Bucket(\'demo-bucket-sayak\').put_object(Key=\'my_image.jpeg\', Body=data)
前面的代码包含了以下功能:
-
my_image.jpeg
是你想上传的图像路径。 -
在
Bucket()
方法中,指定的是你希望上传图片的 S3 存储桶的名称。
如果代码成功执行,你应该会收到以下输出:
s3.Object(bucket_name=\'demo-bucket-sayak\', key=\'my_image.jpeg\')
你可以通过访问 AWS S3 控制台,进入你上传图像的存储桶,来验证图像是否上传成功。你应该能在其中看到类似以下内容:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/ea5a0e67-5997-4205-836e-532a4560ee54.png
现在你已经成功在 Python 中配置了 boto3,我们可以继续学习如何使用 boto3 在 Python 中调用 Rekognition 和 Alexa API。
在 Python 中使用 Rekognition API
Amazon Rekognition 是一个启用了深度学习的视觉分析服务,可以帮助你无缝搜索、验证和分析数十亿张图像。首先让我们简单回顾一下 Rekognition API,然后我们将直接开始在 Python 中使用它。首先访问 Rekognition API 的主页 console.aws.amazon.com/rekognition/home
。我们已经在本章的早些章节中看过 Rekognition 的主页。
正如你可能已经从导航栏中注意到的,Rekognition API 提供了很多功能:
-
物体和场景检测:此功能可以自动为给定图像标注物体、标签和场景,并提供置信度分数。
-
图像审核:这个功能可以帮助你检测图像中的显性或暗示性成人内容,并提供置信度分数。
-
名人识别:使用这个功能,你可以自动识别图像中的名人,并提供置信度分数。
-
人脸比对:这个功能可以用于查看两个面孔的相似度百分比,以判断它们之间的匹配程度。
除了这些功能外,它还具有更多其他功能。
Rekognition API 提供的解决方案已经被许多组织证明是非常有用的,因为它们真正解决了一些现实世界中的挑战性问题。你可以通过点击 API 主页上相应的解决方案,快速尝试列表中提到的任何解决方案。我们来试试名人识别解决方案。
首先,访问 console.aws.amazon.com/rekognition/home?region=us-east-1#/celebrity-detection
(注意区域可能有所不同)。它应当看起来像下面的图片:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/5d0a60f8-7ee3-4e21-84ec-0679a3475f7f.png
门户将允许你上传自己的图片并进行测试。让我们测试我的图片(我们本可以使用名人媒体图片,但这些图片有版权保护)。你可以看到预期的结果:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/48570a56-c2cb-48b9-8d36-309bf77bcf96.png
也可以尝试其他解决方案。现在让我们看看如何从 Python 代码中使用 Rekognition API:
- 创建一个新的 Jupyter Notebook。首先,你需要创建一个新的 Jupyter notebook,例如命名为
Sample.ipynb
。你还需要提供一张你希望测试的图像,用于通过 AWS Rekognition API 进行名人识别,下面是 Jupyter 目录结构截图:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/036c3c11-7381-44b9-83a5-f2c6f4f0b71f.png
- 导入 AWS 账户凭证的环境变量。你需要将之前在 boto3 配置部分获得的账户凭证导入到脚本中。为此,可以使用以下代码:
import osaws_access_key_id= os.environ[\'aws_access_key_id\']aws_secret_access_key = os.environ[\'aws_secret_access_key\']
- 使用 boto3 创建 AWS Rekognition API 客户端。我们现在准备实例化一个 boto3 Rekognition API 客户端对象。为此,我们需要将要使用的 API 和所需的 AWS 区域名称传递给
boto3
对象。还需要传入之前步骤中获取的凭证,代码如下:
import boto3client=boto3.client(\'rekognition\', region_name=\'us-east-1\', aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key)
- 从磁盘读取图像并将其传递给 API。使用 boto3 SDK 将文件传递给 AWS API 有两种方法。首先,你可以直接从你有权限的 S3 存储桶发送它们,或者可以将图像作为
Bytes
数组从本地磁盘发送。我们已经在前面的部分展示了如何从 S3 存储桶查找图像。
现在我们将展示一个示例,其中我们从本地磁盘获取多张图片并传递给 API 调用:
- 首先,使用 Python 的原生方法将图像读取到一个变量中,代码如下:
image = open(\"image.jpg\", \"rb\")
- 现在,通过我们之前实例化的客户端将其传递给 API,使用以下代码行:
response = client.recognize_celebrities(Image={\'Bytes\':image.read()})
- 观察响应。一旦 API 调用成功,你的
response
变量将保存 API 返回的信息。要查看该信息,可以打印该变量:
{\'CelebrityFaces\': [{\'Urls\': [\'www.imdb.com/name/nm1682433\'], \'Name\': \'Barack Obama\', \'Id\': \'3R3sg9u\', \'Face\': {\'BoundingBox\': {\'Width\': 0.3392857015132904, \'Height\': 0.27056020498275757, \'Left\': 0.324404776096344, \'Top\': 0.06436233967542648}, \'Confidence\': 99.97088623046875, \'Landmarks\': [{\'Type\': \'eyeLeft\', \'X\': 0.44199424982070923, \'Y\': 0.17130307853221893}, {\'Type\': \'eyeRight\', \'X\': 0.5501364469528198, \'Y\': 0.1697501391172409}, {\'Type\': \'nose\', \'X\': 0.4932120144367218, \'Y\': 0.2165488302707672}, {\'Type\': \'mouthLeft\', \'X\': 0.43547138571739197, \'Y\': 0.25405779480934143}, {\'Type\': \'mouthRight\', \'X\': 0.552975058555603, \'Y\': 0.2527817189693451}], \'Pose\': {\'Roll\': -1.301725149154663, \'Yaw\': -1.5216708183288574, \'Pitch\': 1.9823487997055054}, \'Quality\': {\'Brightness\': 82.28946685791016, \'Sharpness\': 96.63640594482422}}, \'MatchConfidence\': 96.0}], \'UnrecognizedFaces\': [], \'ResponseMetadata\': {\'RequestId\': \'ba909ea2-67f1-11e9-8ac8-39b792b4a620\', \'HTTPStatusCode\': 200, \'HTTPHeaders\': {\'content-type\': \'application/x-amz-json-1.1\', \'date\': \'Fri, 26 Apr 2019 07:05:55 GMT\', \'x-amzn-requestid\': \'ba909ea2-67f1-11e9-8ac8-39b792b4a620\', \'content-length\': \'813\', \'connection\': \'keep-alive\'}, \'RetryAttempts\': 0}}
API 识别我们的图像为 Barack Obama(巴拉克·奥巴马)。它还提供了许多其他有用的信息,例如面部匹配的 BoundingBox
(边界框)、预测的 Confidence
(置信度)、眼睛、嘴巴和鼻子的位置信息等。我们可以使用这些信息对图像进行进一步操作——例如,简单地裁剪出匹配的部分。
- 获取图像的匹配部分。为了准备图像中已识别区域的裁剪版本,我们可以使用以下代码:
from PIL import Imagefrom IPython.display import displayim=Image.open(\'image.jpg\')w, h = im.sizeceleb = response[\'CelebrityFaces\'][0][\'Face\'][\'BoundingBox\']x1 = (celeb[\"Left\"])*wy1 = (celeb[\"Top\"])*hx2 = (celeb[\"Left\"] + celeb[\"Width\"])*wy2 = (celeb[\"Top\"] + celeb[\"Height\"])*hbox=(x1,y1,x2,y2)im1=im.crop(box)display(im1)
你应该会看到以下图像作为最终结果,这是 API 生成的用于进行名人识别的边界框:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/175087bb-bb71-47a3-80ae-81095e96551f.png
进一步探索 AWS 的 boto3 API 后,你会发现它能够处理所有 AWS 服务,而不仅仅是 Rekognition API。这意味着,根据 API 规范要求,前面的示例代码几乎可以用于所有可用的 API,只需做一些小修改。
在接下来的部分,我们将介绍 Alexa,这是亚马逊推出的旗舰产品,用于构建语音接口,其功能范围从聊天机器人到虚拟个人助手不等。我们将学习如何使用 Alexa 构建一个简单的家庭自动化解决方案。
在 Python 中使用 Alexa API
亚马逊 Alexa 是由亚马逊开发的基于语音的个人助手。该产品最初作为 Amazon Echo 设备的接口推出,后来启发了 Google 推出的 Google Home 设备,后者使用 Google Assistant。Alexa 的其他竞争者包括微软的 Cortana 和苹果的 Siri。作为一个虚拟助手,Alexa 可以轻松进行拨打电话、安排会议或播放歌曲等操作。Alexa 能执行的各种任务被称为技能,我们将在本节中使用这一术语。
Alexa 中的技能是将功能引入平台的核心。每个技能需要通过 Alexa 的主要接口调用,然后该技能将接管整个功能,直到程序逻辑完成或用户明确要求技能结束。技能应用了执行任务所需的逻辑,因此该逻辑需要存储在某个地方,可能还需要与数据库和执行运行时一起存储。虽然许多技能托管在多个服务上,例如 Heroku、PythonAnywhere、GCP 等,但在 AWS Lambda 函数中托管技能和逻辑代码是非常常见的。
在本节中,我们将使用 Alexa 的 Python SDK 创建一个示例的家庭自动化 Alexa 技能,并将其托管在 AWS Lambda 上。
项目所需的前提条件和框架图
在你开始构建 Alexa 技能之前,你需要在 AWS 和 Amazon Developer 分别拥有以下两种账户:
-
一个 AWS 账户(免费套餐可用)—aws.amazon.com
-
一个 Amazon 开发者账户(免费)—developer.amazon.com
一旦你创建了这些账户——这部分内容超出了本书的范围——你就可以继续创建我们的家庭自动化技能了。我们将要创建的家庭自动化技能架构如下面的框架图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/dc3b9bf7-c327-4b8b-ab37-7039b36c77f6.png
在构建此技能时,我们将使用以下服务,你可以通过访问以下列表中的链接了解更多信息:
-
Amazon Alexa Skills Kit:
developer.amazon.com/alexa-skills-kit
-
使用 Amazon 登录:
developer.amazon.com/docs/login-with-amazon/minitoc-lwa-overview.html
-
AWS CloudWatch:
aws.amazon.com/cloudwatch/
-
Amazon DynamoDB:
aws.amazon.com/dynamodb/
-
AWS Lambda:
aws.amazon.com/lambda/
为技能创建配置
技能需要在服务之间建立一定的连接才能工作。此外,部署在 AWS Lambda 上的技能逻辑需要配置为可以在 Alexa 上使用。请在工作文件夹的根目录中创建一个名为setup.txt
的文件,内容如下。随着我们逐步完成本节中的步骤,我们将不断添加内容:
[LWA Client ID]amzn1.application-oa2-client.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX[LWA Client Secret]XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX[Alexa Skill ID]amzn1.ask.skill.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX[AWS Lambda ARN]arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:skill-sample-language-smarthome-switch[APIs]https://pitangui.amazon.com/api/skill/link/XXXXXXXXXXXXXXhttps://layla.amazon.com/api/skill/link/XXXXXXXXXXXXXXhttps://alexa.amazon.co.jp/api/skill/link/XXXXXXXXXXXXXX
在接下来的各个部分中,我们将提到此文件为setup.txt
。它实际上只包含有关你的技能的信息。你也可以在其他文本编辑器中实现此文件,例如 Google 文档。
设置“使用 Amazon 登录”
对于家庭自动化技能,你需要启用“使用 Amazon 登录”服务。为此,请按照以下步骤操作:
- 访问
developer.amazon.com/lwa/sp/overview.html
。你将看到如下截图所示的页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/4afa1398-744c-4718-bb55-0a9209e8ed04.png
-
点击页面加载后的“创建新的安全配置文件”按钮。
-
将安全配置文件名称设置为
Smart Home Automation Profile
。 -
提供配置文件的描述。
-
对于内容隐私声明 URL,你需要一个有效的隐私政策网页,以便将技能推向生产环境。创建并托管隐私政策,并在此字段中提供该链接。创建隐私政策的一个非常实用的工具可以在
app-privacy-policy-generator.firebaseapp.com/
找到。 -
点击“保存”。
-
在下一个页面中,点击齿轮菜单中的“安全配置文件”选项。你将被带到“安全配置文件管理”页面,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/6baa4f01-2672-49cb-9e03-6dd1f0902cac.png
-
在安全配置文件列表中,点击“Web 设置”选项卡,显示“客户端 ID 和客户端密钥”链接以供家庭自动化配置文件使用。
-
复制显示的客户端 ID 和客户端密钥值,并将其保存到工作目录中的
setup.txt
文件中,分别替换[LWA Client ID]
和[LWA Client Secret]
格式示例条目。
保持此标签页打开,以便进行后续步骤。在新的浏览器标签页中查看下一部分的步骤。
创建技能
现在我们可以继续创建技能:
- 登录
developer.amazon.com/alexa/console/ask
开始该过程。你将看到一个类似于以下的页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/e055cf24-cc4d-4caf-87a6-b5187a26a92a.png
-
点击创建技能(Create Skill)。
-
将名称设置为
Home Automation Skill
,或者选择你喜欢的名称。 -
在“选择一个模型添加到你的技能”部分,点击智能家居模型(Smart Home model)。你的选择现在应该类似于以下内容:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/15bd4a33-02ec-4ab9-b0fc-7cd83f015eec.png
-
点击创建技能(Create Skill)以完成技能创建的初始阶段。
-
在下一个页面中,你将看到技能 ID。将此技能 ID 复制到本地工作目录中的
setup.txt
文件。
不要关闭此标签页,因为这里还有字段需要填写。打开一个新的浏览器标签页,在下一部分继续工作。
配置 AWS Lambda 函数
在我们将 Lambda 函数的 ARN 添加到技能端点配置之前,我们必须先为 Lambda 函数创建配置。你可以通过以下步骤完成:
- 访问
console.aws.amazon.com/iam/home#/policies
,你将看到一个类似于以下截图的页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/0fdc474a-3051-4bab-9698-8a9d883cb2f6.png
-
点击创建策略(Create policy)。
-
在创建策略编辑器的 JSON 选项卡中输入以下 JSON:
{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \"Action\": [ \"logs:CreateLogStream\", \"dynamodb:UpdateItem\", \"logs:CreateLogGroup\", \"logs:PutLogEvents\" ], \"Resource\": \"*\" } ] }
-
点击审核策略(Review policy),并将策略的名称设置为
HomeAutomationPolicy
。 -
点击创建策略(Create policy)。
-
接下来,在页面的左侧导航菜单中,点击角色(Roles)。
-
点击创建角色(Create role)。
-
选择 AWS 服务和 Lambda,然后点击下一步:权限(Next: Permissions)。
-
在过滤字段中搜索 HomeAutomationPolicy,勾选该策略。你的屏幕应该类似于以下内容:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/38f026ca-5a81-427f-ad3c-dc5efa7357de.png
-
点击下一步:标签(Next: Tags)。
-
点击下一步:审核(Next: Review)。
-
将角色名称设置为
lambda_home_automation
。 -
点击创建角色(Create role)。
现在我们来创建 Lambda 函数。
创建 Lambda 函数
配置好 Lambda 函数的适当设置后,我们现在可以创建 Lambda 函数本身。为此,请在 AWS 控制台中,访问console.aws.amazon.com/lambda/home
,并按以下步骤操作:
-
点击创建函数(Create function)。
-
将函数名称设置为
homeAutomation
。 -
选择
Python 3.6
运行时。 -
在执行角色中的现有角色下,从下拉菜单中选择
lambda_home_automation
角色。 -
点击
创建函数
(Create function)。 -
复制下一个页面中显示的 Lambda ARN,该页面上有一个恭喜创建 Lambda 函数的消息。将此 ARN 放入我们本地工作目录的
setup.txt
文件中的[AWS Lambda ARN]字段。此时,屏幕应该类似于以下截图:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/c27dff75-763d-479c-aea9-4846c6cd2e08.png
请注意,您屏幕上显示的触发器和目标可能与前面的截图有所不同。
- 在左侧导航栏中,点击“添加触发器”,弹出 Lambda 函数的可用触发器下拉列表,如下截图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/4c5d75a8-1315-43f1-87d7-961a97ea98c4.png
-
点击 Alexa Skills Kit 以打开该触发器的配置对话框。
-
在技能 ID 字段中粘贴 Alexa 技能 ID。我们之前已将此值存储在
setup.txt
中,它的形式类似于amzn1.ask.skill.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
。 -
点击“添加”以添加触发器,并返回 Lambda 函数管理屏幕。
-
点击页面右上角的“保存”。
完成最后一步后,触发器部分将显示已连接的 Alexa 技能的详细信息。如果没有显示,您应该检查是否正确按照前述步骤操作。
配置 Alexa 技能
现在,我们需要配置我们在浏览器的另一个标签页中保持打开的技能。我们将通过以下步骤进行配置:
-
返回该标签页并在默认端点字段中填写 Lambda 函数的 ARN。
-
点击“保存”。
-
点击页面底部的“设置账户链接”。
-
对于授权 URL,输入
https://www.amazon.com/ap/oa
。 -
对于访问令牌 URL,输入
https://api.amazon.com/auth/o2/token
。 -
对于客户端 ID 字段,复制
[LWA Client ID]
来自setup.txt
文件。 -
对于客户端密钥字段,复制
[LWA Client Secret]
来自setup.txt
文件。 -
点击“添加作用域”,并输入
profile:user_id
。 -
复制页面底部的重定向 URL,并将其粘贴到
setup.txt
文件中的[APIs]部分。这些 URL 类似于:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/81841ec1-c702-47ac-84d3-11fc81c679bd.png
-
点击“保存”。
-
在安全配置管理的浏览器标签页中,点击“Web 设置”标签。
-
点击“编辑”,并将三个重定向 URL 添加到“允许返回 URL”字段中。您需要点击“添加另一个”以输入多个 URL。
-
点击“保存”。
现在,让我们为技能设置 Amazon DynamoDB。
为技能设置 Amazon DynamoDB
为了让技能能够保存用户数据,它需要一个数据库。我们将使用 Amazon DynamoDB 服务。设置此服务的步骤如下:
-
访问
console.aws.amazon.com/dynamodb/home?region=us-east-1
。 -
点击“创建表格”按钮。
-
输入表格名称为
SmartHome
。 -
对于主键,输入
ItemId
。 -
保持所有默认设置不变,然后点击“创建”。此时,您的屏幕应该显示如下截图:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/c1615057-9eee-451a-aa6e-49226c642255.png
然后,您可以进入 DynamoDB 控制台,查看刚创建的表格;不过,这可能需要几分钟。
部署 AWS Lambda 函数的代码
剩下的就是最后一个设置部分——为 AWS Lambda 函数提供逻辑的代码。进入你的 Lambda 函数配置页面,并向下滚动至编辑器。
你会注意到编辑器有一个两栏界面:左侧栏显示 Lambda 函数存储中的文件,右侧栏则可以编辑这些文件,具体如下截图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/83315a84-c753-4f37-980c-a9b5dd4e5ed8.png
点击 lambda_function.py
开始编辑文件,并按以下步骤进行操作:
- 导入必要的模块。为了使函数正常工作,我们需要一些常见库的支持,具体代码如下:
import boto3import jsonimport randomimport uuidimport time
boto3 API 用于连接我们设置的 Amazon DynamoDB 实例。JSON 模块帮助生成 Alexa 技能的响应。其余模块帮助生成响应内容。
- 创建
AlexaResponse
类。为了能够完全复制 Alexa 技能期望的响应格式,我们可以快速设置一个辅助类,用于生成 Lambda 函数调用的响应。我们将其命名为AlexaResponse
;类的初始化如下代码片段所示:
class AlexaResponse: def __init__(self, **kwargs): self.context_properties = [] self.payload_endpoints = [] # Set up the response structure self.context = {} self.event = { \'header\': { \'namespace\': kwargs.get(\'namespace\', \'Alexa\'), \'name\': kwargs.get(\'name\', \'Response\'), \'messageId\': str(uuid.uuid4()), \'payloadVersion\': kwargs.get(\'payload_version\', \'3\') }, \'endpoint\': { \"scope\": { \"type\": \"BearerToken\", \"token\": kwargs.get(\'token\', \'INVALID\') }, \"endpointId\": kwargs.get(\'endpoint_id\', \'INVALID\') }, \'payload\': kwargs.get(\'payload\', {}) } if \'correlation_token\' in kwargs: self.event[\'header\'][\'correlation_token\'] = kwargs.get(\'correlation_token\', \'INVALID\') if \'cookie\' in kwargs: self.event[\'endpoint\'][\'cookie\'] = kwargs.get(\'cookie\', \'{}\') if self.event[\'header\'][\'name\'] == \'AcceptGrant.Response\' or self.event[\'header\'][\'name\'] == \'Discover.Response\': self.event.pop(\'endpoint\')
前面的 AlexaResponse
类初始化方法设置了预期的输出格式及各种常量设置,比如有效负载的版本号,以及一些输出对象的基本验证。接下来,我们创建了添加内容属性的方法和用于设置响应中 cookies 的另一个方法。最后,另一个方法被添加用于设置有效负载的端点:
def add_context_property(self, **kwargs): self.context_properties.append(self.create_context_property(**kwargs))def add_cookie(self, key, value): if \"cookies\" in self is None: self.cookies = {} self.cookies[key] = valuedef add_payload_endpoint(self, **kwargs): self.payload_endpoints.append(self.create_payload_endpoint(**kwargs))
-
现在来定义我们在上一阶段创建的三个处理方法。上一阶段声明的方法依赖于它们自己的内部方法。这些大多是辅助函数,与本章的主要内容关系不大,因此我们将把这些留给你根据 AWS Lambda 函数和 Alexa 技能的响应体文档自行实现。可以参考我们本章代码库中的示例实现,位于
lambda_function.py
文件的第 65 行至 102 行,链接:tiny.cc/HOPDLW_CH7_lfpy
。 -
接下来,我们将设置方法以生成
AlexaResponse
类的最终响应。最后,我们创建方法将所有不同的部分——上下文、事件、有效负载、端点和 cookies——合并为一个准备好与 Alexa 技能交互的对象:
def get(self, remove_empty=True): response = { \'context\': self.context, \'event\': self.event } if len(self.context_properties) > 0: response[\'context\'][\'properties\'] = self.context_properties if len(self.payload_endpoints) > 0: response[\'event\'][\'payload\'][\'endpoints\'] = self.payload_endpoints if remove_empty: if len(response[\'context\']) < 1: response.pop(\'context\') return response def set_payload(self, payload): self.event[\'payload\'] = payload def set_payload_endpoint(self, payload_endpoints): self.payload_endpoints = payload_endpoints def set_payload_endpoints(self, payload_endpoints): if \'endpoints\' not in self.event[\'payload\']: self.event[\'payload\'][\'endpoints\'] = [] self.event[\'payload\'][\'endpoints\'] = payload_endpoints
AlexaResponse
类现在已完成。接下来我们将使用以下代码连接到 DynamoDB 服务:
aws_dynamodb = boto3.client(\'dynamodb\')
- 接下来,我们定义文件的主要方法和入口点——
lambda_handler
方法:
def lambda_handler(request, context): # JSON dump for the request print(\'Request: \') print(json.dumps(request)) if context is not None: print(\'Context: \') print(context)
我们将继续为此步骤的其余部分添加到前面的代码中。在前面的代码行中,我们声明了 lambda_handler
方法,该方法接受来自 Alexa 技能的 request
和 context
对象。然后,它对请求进行 JSON 转储,以便我们可以稍后从 Amazon CloudWatch 仪表板观察它。接下来,它还对请求中附加的上下文进行转储(如果有的话):
# Validate we have an Alexa directive if \'directive\' not in request: aer = AlexaResponse( name=\'ErrorResponse\', payload={\'type\': \'INVALID_DIRECTIVE\', \'message\': \'Missing key: directive, Is the request a valid Alexa Directive?\'}) return send_response(aer.get())
我们接下来验证请求中是否包含有效的 Alexa 指令,如果没有找到,则生成错误信息并作为响应返回。请注意这里使用了 AlexaResponse
类对象。我们将来会使用它来生成来自该脚本的响应:
# Check the payload version payload_version = request[\'directive\'][\'header\'][\'payloadVersion\'] if payload_version != \'3\': aer = AlexaResponse( name=\'ErrorResponse\', payload={\'type\': \'INTERNAL_ERROR\', \'message\': \'This skill only supports Smart Home API version 3\'}) return send_response(aer.get())
类似地,还进行另一个检查,以确保请求的负载版本是 3。这是因为我们只为 Alexa 的智能家居 API 版本 3 开发了它:
- 首先,我们打开请求并查看请求了什么:
name = request[\'directive\'][\'header\'][\'name\'] namespace = request[\'directive\'][\'header\'][\'namespace\']
- 然后,我们根据
namespace
处理来自 Alexa 的请求。请注意,这个示例接受任何grant
请求,但在您的实现中,您将使用代码和令牌来获取并存储访问令牌:
if namespace == \'Alexa.Authorization\': if name == \'AcceptGrant\': grant_code = request[\'directive\'][\'payload\'][\'grant\'][\'code\'] grantee_token = request[\'directive\'][\'payload\'][\'grantee\'][\'token\'] aar = AlexaResponse(namespace=\'Alexa.Authorization\', name=\'AcceptGrant.Response\') return send_response(aar.get())
前面的条件作用于 Alexa 授权请求。
- 对于发现和关闭开关的操作,我们使用以下代码:
if namespace == \'Alexa.Discovery\': if name == \'Discover\': adr = AlexaResponse(namespace=\'Alexa.Discovery\', name=\'Discover.Response\') capability_alexa = adr.create_payload_endpoint_capability() capability_alexa_powercontroller = adr.create_payload_endpoint_capability( interface=\'Alexa.PowerController\', supported=[{\'name\': \'powerState\'}]) adr.add_payload_endpoint( friendly_name=\'Sample Switch\', endpoint_id=\'sample-switch-01\', capabilities=[capability_alexa, capability_alexa_powercontroller]) return send_response(adr.get()) if namespace == \'Alexa.PowerController\': endpoint_id = request[\'directive\'][\'endpoint\'][\'endpointId\'] power_state_value = \'OFF\' if name == \'TurnOff\' else \'ON\' correlation_token = request[\'directive\'][\'header\'][\'correlationToken\']
这个示例始终返回 success
响应,无论是 TurnOff
还是 TurnOn
请求。
- 现在,我们在设置状态时检查是否有错误:
state_set = set_device_state(endpoint_id=endpoint_id, state=\'powerState\', value=power_state_value) if not state_set: return AlexaResponse( name=\'ErrorResponse\', payload={\'type\': \'ENDPOINT_UNREACHABLE\', \'message\': \'Unable to reach endpoint database.\'}).get() apcr = AlexaResponse(correlation_token=correlation_token) apcr.add_context_property(namespace=\'Alexa.PowerController\', name=\'powerState\', value=power_state_value) return send_response(apcr.get())
-
最后,我们提取指令名称和指令的命名空间,以确定要发送回的响应类型。根据发送的指令,生成不同的响应,并最终通过
AlexaResponse
类对象发送回去。 -
注意前一步代码中
send_response
方法的使用。我们需要定义这个方法。它的任务是以 JSON 格式发送AlexaResponse
对象,并将其记录以便在 Amazon CloudWatch 中观察:
def send_response(response): print(\'Response: \') print(json.dumps(response)) return response
- 更新
device state
方法。由于我们正在为使用 Alexa 的简单开关设备构建自动化,我们需要维护开关的状态信息。我们通过将其状态存储在 DynamoDB 中来实现这一点。我们将为此添加一个更新方法,如下所示:
def set_device_state(endpoint_id, state, value): attribute_key = state + \'Value\' response = aws_dynamodb.update_item( TableName=\'SmartHome\', Key={\'ItemId\': {\'S\': endpoint_id}}, AttributeUpdates={attribute_key: {\'Action\': \'PUT\', \'Value\': {\'S\': value}}}) print(response) if response[\'ResponseMetadata\'][\'HTTPStatusCode\'] == 200: return True else: return False
接下来,我们将测试 Lambda 函数。
测试 Lambda 函数
现在,我们可以检查函数是否正确响应。为此,我们必须通过以下步骤在 Lambda 函数的仪表板中创建一个测试:
-
在我们在前面创建的 Lambda 函数页面的右上角,点击 Test。
-
将弹出一个对话框,提供写入新测试或使用现有测试的选项。选择“创建新测试事件”选项。
-
在事件模板中,确保选择了 Hello World。
-
接下来,提供
directiveDiscovery
的事件名称。 -
在编辑器中输入以下 JSON:
{ \"directive\": { \"header\": { \"namespace\": \"Alexa.Discovery\", \"name\": \"Discover\", \"payloadVersion\": \"3\", \"messageId\": \"1bd5d003-31b9-476f-ad03-71d471922820\" }, \"payload\": { \"scope\": { \"type\": \"BearerToken\", \"token\": \"access-token-from-skill\" } } }}
此时,您的屏幕应该类似于以下内容:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/72352241-b56d-4536-b083-daebba4c21cf.png
-
向下滚动并点击 Create。
-
返回 Lambda 函数仪表板后,在右上角,从下拉菜单中选择
directoryDiscover
测试。 -
点击测试(Test)。
完成后,测试将显示响应状态和 Lambda 函数的响应。你可以在 Lambda 函数仪表板顶部的页面上看到结果,结果会类似以下截图:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/ff23d8a3-8380-4e37-949f-efd3614544ca.png
如果测试失败,请确保你已经仔细按照前述步骤操作,并确保各个服务所在的区域一致。
测试 AWS Home Automation 技能
作为本项目的最后阶段,我们将在 Alexa 测试模拟器中测试我们的技能。为此,请按照以下步骤操作:
-
访问
alexa.amazon.com
并登录。 -
在左侧菜单中点击技能(Skills)。
-
点击页面右上角的“你的技能”(Your Skills)。
-
选择 DEV SKILL 标签。
-
点击 HomeAutomationSkill。你应该会看到以下界面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/246d6e58-cde0-45cd-9ad1-0f7dd1f02154.png
-
点击启用按钮。系统会要求你允许访问你的开发者账户权限。
-
返回到 Alexa 开发者控制台,点击发现设备(Discover devices)。一个名为 Sample Switch 的新设备将会显示为可用,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/77383ecb-ff77-43fa-99ae-c06f245dd01e.png
-
现在,进入 Alexa Skills Kit 开发页面的测试(Test)选项卡,选择 HomeAutomation 技能。
-
在模拟器中输入
alexa, turn on the sample switch
。如果请求被接受,你将收到 Alexa 的OK
响应,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/40856d4c-4de8-458c-b4e7-83073a821f59.png
为了检查技能是否正常工作,你可以进入你的 DynamoDB 表格 SmartHome,并切换到表格的 Items 选项卡。你应该能看到以下记录:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/f0949a1c-45e6-49d6-af20-309f9b4dd0a3.png
恭喜你成功构建了一个简单的 Home Automation 技能!你可以尝试使用这个技能并为 Alexa 创建你自己的家庭自动化技能。当你准备好将其发布给更广泛的观众时,可以参考 developer.amazon.com/docs/alexa-for-business/create-and-publish-private-skills.html
上的文档进行操作。
总结
在本章中,我们介绍了如何使用其 Python API——boto3 来使用 AWS。我们探索了使用该 API 的各种选项和配置要求,并通过一个示例展示了如何使用它与 Rekognition API 进行名人识别。接着,我们深入探讨了如何为家庭自动化创建 Alexa 技能,设置一个简单的开关开/关任务。这可以很容易地推广到其他智能家居设备。我们还了解了如何将 Alexa 技能逻辑托管在 AWS Lambda 上,并通过 AWS CloudWatch 进行观察。我们还探索了将动态设备数据存储在 Amazon DynamoDB 中的方法。
在接下来的章节中,我们将看到如何在微软的 Azure 平台上使用 Python 进行深度学习。
第十一章:使用 Python 在微软 Azure 上进行深度学习
本章将结束我们的云 API 探索之旅。到目前为止,我们已经轻松地了解了 API 的精彩世界,特别是那些让我们轻松进行深度学习的 API。我们已经看到了如何使用 REST API 并通过编程方式使用它们。像谷歌云平台(GCP)和亚马逊云服务(AWS)一样,微软也提供了自己的云服务平台,称为 Azure。与前几章一样,我们将重点介绍 Azure 提供的基于深度学习的解决方案。我们将稍微调整一下方向,还将介绍微软的认知工具包(CNTK),它是一个类似于 Keras 的深度学习框架。
本章我们将涵盖以下主题:
-
在 Azure 中设置你的账户
-
快速了解 Azure 提供的深度学习解决方案
-
在 Python 中使用人脸 API
-
在 Python 中使用文本分析 API
-
CNTK 简介
技术要求
你可以从github.com/PacktPublishing/Hands-On-Python-Deep-Learning-for-Web/tree/master/Chapter8
访问本章的代码。
为了运行本章使用的代码,你需要以下软件:
-
Python 3.6+
-
Python PIL 库
-
Matplotlib 库
所有其他安装步骤,如 CNTK 和 Django,将在本章中进一步介绍。
在 Azure 中设置你的账户
根据你之前使用云平台的经验,你可能已经意识到,所有一切都始于在云服务提供商处设置账户和账单。这是一个相当标准的工作流程,Azure 也不例外。因此,让我们前往azure.microsoft.com
,并按照以下步骤操作:
- 点击“开始免费试用”按钮,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/01908bbd-6abc-4f1b-8b26-2d05cab0472d.png
请注意,你需要一个微软账户才能继续进行以下步骤。如果你没有账户,可以在account.microsoft.com/account
创建一个。
- 你将被重定向到另一个页面,页面中会再次显示一个“开始免费试用”按钮。点击它。
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/e67d8ec9-75a8-48a3-aa96-a76668954eb7.png
- 你将被要求登录微软账户才能继续。根据提示输入账户信息,应该能看到如下截图的页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/89e7d103-9c26-4a97-aaa8-78989fd0b407.png
如果你是首次使用,你将获得价值 200 美元的信用额度(根据你的货币不同),可以免费使用 30 天,探索 Azure 提供的不同服务。
- 填写你的详细信息,包括通过银行卡验证身份。
你可能需要支付一笔非常小的费用。务必查看 Azure 免费套餐的条款和条件,详情请见 azure.microsoft.com/en-in/offers/ms-azr-0003p/
。
一旦这个过程完成,你就已经设置好了,可以进入你的 Azure 门户 (portal.azure.com
),它的功能与前几章中提到的 GCP 和 AWS 控制台类似。
Azure 门户界面如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/be9a0fa6-08a0-474a-8d62-b28113ea7fcf.png
现在你已经设置好了 Azure 账户,让我们在下一节中探索 Azure 基于深度学习的服务。
对 Azure 提供的深度学习服务的逐步讲解
Azure 的深度学习(以及一般的机器学习)服务大致分为三大部分:
- Azure 机器学习服务 (
azure.microsoft.com/en-in/services/machine-learning-service/
),提供完整的机器学习生命周期,包括模型构建、训练和部署:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/5e49fe53-bc9e-41e1-b544-97bdfb6d9e0a.png
- 机器学习 API (
gallery.azure.ai/machineLearningAPIs
),提供广泛的学习任务 API,例如内容审核、翻译、异常检测等:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/3172ed87-5c07-4de6-bcb3-8a1c49c9ac02.png
- Azure AI (
azure.microsoft.com/en-in/overview/ai-platform/
),专注于知识挖掘、决策挖掘以及计算机视觉和语言建模领域的其他许多类似机器学习能力:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/a33df20e-bf48-44a2-b065-44b02e2bf715.png
接下来,我们将分别研究两个 API,一个用于计算机视觉任务,一个用于自然语言理解任务。我们还将学习如何从 Python 中使用这些 API。让我们深入了解。
使用 Face API 和 Python 进行物体检测
物体检测是计算机视觉的经典应用,广泛应用于许多现实世界问题中,如视频监控系统。在本节中,我们将使用 Face API 从给定图像中检测面孔。这在设计视频监控系统时有直接应用。你可以通过 azure.microsoft.com/en-us/services/cognitive-services/face/
了解更多关于 Face API 的信息。
初始设置
Azure 还允许你在 7 天内免费试用该 API。但是,由于你已经拥有 Azure 账户(假设你有免费的信用额度),我们可以采用另一种方式,如下所示:
-
登录你的 Azure 账户。
-
访问
azure.microsoft.com/en-us/services/cognitive-services/face/
。 -
点击“已经在使用 Azure?现在免费试用此服务”。
现在您应该看到如下截图的窗口:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/f1b88b0e-e960-4830-9440-3e4ffa4ab083.png
- 填写相关信息并点击“创建”完成。您将看到一个弹出窗口,显示“正在提交部署”。
部署完成后,您应该看到如下截图的页面:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/8d44a941-a39a-4c25-8b07-1457bef65c63.png
- 点击“前往资源”,您将被重定向到资源页面,其中包含许多详细信息:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/08af55b4-5b80-44b4-9943-282a9618ff8d.png
只需稍微向下滚动,您就可以看到 Face API 的端点。请注意,它会根据您在创建部署时输入的配置细节而有所不同。该端点看起来像这样:eastus.api.cognitive.microsoft.com/face/v1.0
。请记下它。
现在,为了能够通过编程使用 Face API,您需要创建相应的 API 密钥。在同一页面的顶部,有一个部分写着获取您的密钥:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/15e48360-dd9c-48f2-b123-c6e1680e2514.png
- 在该部分下,点击“密钥”,您将看到类似如下截图的内容:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/6166e10e-a211-4053-9236-f678e04822cc.png
现在您已经拥有了 Face API 的 API 密钥,准备好使用它了。
从 Python 代码中调用 Face API
当您的程序包含诸如 API 密钥之类的安全凭证时,通常的最佳做法是将这些密钥定义为环境变量,并在程序中调用它们。因此,创建一个环境变量来存储 Face API 的一个 API 密钥。
要将环境变量添加到计算机中,可以参考这篇文章:www.twilio.com/blog/2017/01/how-to-set-environment-variables.html
。
就我而言,我将环境变量命名为 face_api_key
。您可以上传任何包含面孔的图像。对于这个示例,我将使用此图像:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/5429ceba-947a-43c2-abbe-7e92043a3fdf.jpg
创建一个新的 Jupyter Notebook 并按照以下步骤操作:
- 现在,使用 Python 加载环境变量,如下所示:
import osface_api_key = os.environ[\'face_api_key\']
-
现在,将您的 Face API 端点(用于物体检测)分配给一个变量。
-
同时,将您想要测试的图像上传到一个在线文件服务器,如 Imgur,并获取允许从 Imgur 提取原始图像的 URL。
就我而言,我已将图像上传到 GitHub 仓库,并使用相应的 URL:
face_api_url = \'https://eastus.api.cognitive.microsoft.com/face/v1.0/detect\'image_url= \'https://raw.githubusercontent.com/PacktPublishing/Hands-On-Python-Deep-Learning-for-Web/master/Chapter8/sample_image.jpg\'
请注意,在前面的 API 中,URL 末尾的端点名称会发生变化。在大多数情况下,端点名称前面的部分在您使用认知服务时会保持不变,除非 Azure 平台本身要求进行更改。
- 现在,导入
requests
模块,并按如下所示设置 API 负载:
import requestsparams = {\'returnFaceId\': \'true\',\'returnFaceLandmarks\': \'false\',\'returnFaceAttributes\': \'age,gender\',}
- 现在,我们已经准备好向 Face API 发出请求。
以下代码行将为您执行此操作:
# Define the header paramheaders = { \'Ocp-Apim-Subscription-Key\': face_api_key }# Define the body paramsparams = {\'returnFaceId\': \'true\',\'returnFaceLandmarks\': \'false\',\'returnFaceAttributes\': \'age,gender\',}
- 我们现在可以显示从 API 接收到的响应:
# Make the call to the APIresponse = requests.post(face_api_url, params=params, headers=headers, json={\"url\": image_url})# Get the response and logfaces = response.json()print(\'There are {} faces im the given image\'.format(str(len(faces))))
在这种情况下,返回的代码如下:
There are 2 faces in the given image
请注意 returnFaceAttributes
这个请求体参数,它让你可以指定面部的多个属性,Face API 将根据这些属性分析给定的人脸。欲了解更多关于这些属性的信息,请查看文档:bit.ly/2J3j6nM
。
让我们以一种可展示的方式将从 API 获得的响应嵌入图像中。我们将显示检测到的人脸的可能性别和可能年龄。我们将使用 matplotlib
、PIL
和 io
库,并将在 Jupyter notebook 中进行以下代码段的工作。我们将首先导入这些库:
%matplotlib inline #Only for Jupyter Notebookimport matplotlib.pyplot as pltfrom PIL import Imagefrom matplotlib import patchesfrom io import BytesIO
要在图像上显示 API 返回的叠加信息,我们使用以下方法:
- 存储 API 响应:
response = requests.get(image_url)
- 从响应内容创建图像:
image = Image.open(BytesIO(response.content))
- 创建一个空白的图形:
plt.figure(figsize=(8,8))
- 显示使用响应创建的图像:
ax = plt.imshow(image, alpha=0.6)
- 遍历前面部分指定的人脸并提取必要的信息:
for face in faces: # Extract the information fr = face[\"faceRectangle\"] fa = face[\"faceAttributes\"] origin = (fr[\"left\"], fr[\"top\"]) p = patches.Rectangle(origin, fr[\"width\"], fr[\"height\"], fill=False, linewidth=2, color=\'b\') ax.axes.add_patch(p) plt.text(origin[0], origin[1], \"%s, %d\"%(fa[\"gender\"].capitalize(), fa[\"age\"]), fontsize=20, weight=\"bold\", va=\"bottom\")# Turn off the axis_ = plt.axis(\"off\") plt.show()
你应该有一张这样的图片:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/6602861e-76f7-4378-afcc-db74b1161cf8.png
鼓励你尝试 API 提供的不同参数。接下来,我们将研究 自然语言理解(NLU)API。
使用文本分析 API 和 Python 提取文本信息
无论是有意还是无意,我们都一定遇到过一些令人惊叹的自然语言处理应用案例。无论是自动更正、下一个单词的建议,还是语言翻译,这些应用案例都非常重要,不容忽视。在本节中,我们将使用文本分析 API(azure.microsoft.com/en-us/services/cognitive-services/text-analytics/
)从给定的文本中提取有意义的信息。
你可以通过之前提到的链接免费试用 API,看看它的强大功能。在以下示例中,我输入了短语 I want to attend NeurIPS someday and present a paper there
,Text Analytics API 从中提取了四个有意义的信息:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/e67aa8f4-cd9d-4d88-922a-4c94bd55d0b0.png
观察 API 如何优雅地提取出短语中的所有关键信息。
现在我们将看到如何使用 Python 进行编程操作。设置步骤与之前完全相同。只需访问 portal.azure.com/#create/Microsoft.CognitiveServicesTextAnalytics
,并按照那里的步骤操作。一旦获得了用于访问 Text Analytics API 的 API 密钥,就可以进入下一个子部分。别忘了记下相应的端点。该端点应以 eastus.api.cognitive.microsoft.com/text/analytics/v2.0
开头。这个 URL 单独使用时无法正常工作,它需要一个后缀指向需要调用的方法。
从 Python 代码中使用 Text Analytics API
本节将展示如何在您自己的 Python 代码中使用 Text Analytics API。以下是使用它的步骤:
- 我们将通过导入所需的库来开始本节内容:
import requestsimport osfrom pprint import pprint
- 然后,我们将从环境变量中加载 Text Analytics API 的 API 密钥:
api_key = os.environ[\'text_api_key\']
- 现在,我们指定一些 URL 来存储 API 端点:
text_analytics_base_url = \\\'https://eastus.api.cognitive.microsoft.com/text/analytics/v2.0\'language_api_url = text_analytics_base_url + \"/languages\"sentiment_api_url = text_analytics_base_url + \"/sentiment\"key_phrase_api_url = text_analytics_base_url + \"/keyPhrases\"
- 现在,我们通过提供 API 密钥来定义
headers
参数:
headers = {\"Ocp-Apim-Subscription-Key\": api_key}
- 我们还将定义 body 参数。在我的示例中,我将保持与之前在基于 GUI 的演示中展示的相同的短语:
documents = { \'documents\': [{ \'id\': \'1\', \'text\': \'I want to attend NeurIPS someday and present a paper there.\' }]}
- 我们现在可以调用 Text Analytics 的相应 API。首先让我们开始检测语言:
response = requests.post(language_api_url, headers=headers, json=documents)language = response.json()pprint(language)
我们根据此得到相应的响应,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/16b55881-1edf-4f83-9814-5cd3c785a8da.png
请注意,我已经突出显示了语言部分。现在,让我们继续进行情感分析:
response = requests.post(sentiment_api_url, headers=headers, json=documents)sentiment = response.json()pprint(sentiment)
显示的情感如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/37049f4f-493f-4703-a41c-52f3a69aeb73.png
请注意,这里使用的短语既不包含正面情感也不包含负面情感,因此得出了这样的评分。现在我们将从给定的文本中提取关键短语:
response = requests.post(key_phrase_api_url, headers=headers, json=documents)phrases = response.json()print(phrases)
关键短语如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/6e957a31-82f6-4670-8ad7-eaded45163f1.png
注意到端点根据任务的不同发生了变化。您可以在 bit.ly/2JjLRfi
了解更多关于我们在前面示例中使用的端点参数。
CNTK 简介
CNTK 是 Microsoft 提供的一个框架。该框架是 ONNX 格式计划的一部分,允许在不同的神经网络工具包框架之间轻松转换模型。该框架负责微软软件和平台上深度学习生产工作负载的很大一部分。该框架于 2016 年推出,并且是 TensorFlow、PyTorch 等流行框架的竞争者。该框架完全开源,您可以在 github.com/microsoft/CNTK
上找到它。
CNTK 驱动了企业服务,如 Cortana 和 Bing,以及广告服务,如 Skype 翻译、Microsoft Cognitive Services 等。已证明它在多个应用中比 TensorFlow 和 PyTorch 等竞争者运行得更快。
在本节中,我们将学习一些 CNTK 的基础知识,然后继续创建一个 Django 应用程序,将基于 CNTK 的模型迁移到网页上。
开始使用 CNTK
由于 CNTK 的语法简单,并且能够无需像 TensorFlow 中的会话(session)概念就能工作,因此它是最容易入门的框架之一。大多数学习者对 TensorFlow 中的会话概念感到困惑。让我们看看如何在本地机器或 Google Colaboratory 上设置 CNTK。
在本地机器上安装
CNTK 框架支持 64 位和 32 位架构的机器。然而,目前它仅支持 Python 版本最高到 3.6。您可以在 pypi.org/project/cntk/
验证最新的支持版本。此外,CNTK 目前不提供 macOS 的已编译二进制版本。
要安装该框架,您可以使用 pip
包管理器,或者通过 Anaconda 使用已编译的二进制文件进行安装。假设已设置 Python 环境,您可以使用以下命令在 Windows 和 Linux 上安装 CNTK:
- 如果没有 Anaconda,请使用以下命令安装 CPU 版本:
# For CPU versionpip install cntk
- 使用以下命令安装 GPU 支持版本:
# For the GPU enabled versionpip install cntk-gpu
- 在启用 Anaconda 的机器上,可以使用
pip
和以下命令安装 CNTK 框架:
pip install <url>
可从 CNTK 网站
tiny.cc/cntk
获取。
该命令将类似于以下内容:
pip install https://cntk.ai/PythonWheel/CPU-Only/cntk-2.6-cp35-cp35m-win_amd64.whl
我们现在可以开始在 Google Colaboratory 上进行安装了。
在 Google Colaboratory 上安装
CNTK 框架在 Google Colaboratory 平台上默认不可用,因此必须与其他必要的模块一起安装。要在 Google Colaboratory 运行时安装 CNTK,请在脚本顶部使用以下命令:
!apt-get install --no-install-recommends openmpi-bin libopenmpi-dev libopencv-dev python3-opencv python-opencv && ln -sf /usr/lib/x86_64-linux-gnu/libmpi_cxx.so /usr/lib/x86_64-linux-gnu/libmpi_cxx.so.1 && ln -sf /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi.so /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi.so.12 && ln -sf /usr/lib/x86_64-linux-gnu/libmpi.so /usr/lib/x86_64-linux-gnu/libmpi.so.12 && pip install cntk
请注意,前面的命令是单行命令。如果将其拆分成多行,您应该确保对命令进行必要的修改。
一旦前面的步骤成功执行,在该运行时中您将不再需要使用此命令。因此,未来运行程序时,可以注释掉该命令。
通常,通过 C
别名将 CNTK 导入 Python 项目。我们使用以下代码将库导入到项目中:
import cntk as C
我们可以使用以下命令检查安装的 CNTK 版本:
print(C.__version__)
将 CNTK 导入项目后,我们可以继续进行创建深度学习模型的前期要求。
创建一个 CNTK 神经网络模型
在本节中,我们将完成创建预测神经网络之前所需的步骤,然后我们将创建神经网络本身:
- 我们首先将必要的模块导入到项目中:
import matplotlib.pyplot as plt%matplotlib inlineimport numpy as npfrom sklearn.datasets import fetch_openmlimport randomimport cntk.tests.test_utilsfrom sklearn.preprocessing import OneHotEncoderimport cntk as C # if you have not done this before in the project
sklearn
模块的 fetch_openml()
方法帮助我们直接下载本示例中使用的数据集——MNIST 手写数字数据集。OneHotEncoder
方法用于标签的独热编码。
- 接下来,设置程序执行期间需要的几个常量:
num_samples = 60000batch_size = 64learning_rate = 0.1
我们将在 60,000 个样本上进行训练,初始学习率为0.1
。在训练过程中,这个学习率可以动态更新。
- 我们接下来需要创建一个生成随机小批量数据的训练方法:
class Batch_Reader(object): def __init__(self, data , label): self.data = data self.label = label self.num_sample = data.shape[0] def next_batch(self, batch_size): index = random.sample(range(self.num_sample), batch_size) return self.data[index,:].astype(float),self.label[index,:].astype(float)
每次调用前述方法时,会生成与先前步骤中设置的大小相等的批量数据——例如,每个批次包含 64 个样本。这些样本会从数据集中随机抽取。
- 现在需要获取数据集;为此,我们使用以下代码行:
mnist = fetch_openml(\'mnist_784\')
数据获取完成后,可以将其分为训练集和测试集,如下所示:
train_data = mnist.data[:num_samples,:]train_label = mnist.target[:num_samples]test_data = mnist.data[num_samples:,:]test_label = mnist.target[num_samples:]
- 数据集中的标签在输入训练模型之前需要进行 one-hot 编码。为此,我们使用以下代码:
enc = OneHotEncoder()enc.fit(train_label[:,None])train_encoded = enc.transform(train_label[:,None]).toarray()
- 现在我们可以为训练批量生成器创建一个生成器对象,如下所示:
train_reader = Batch_Reader(train_data, train_encoded)
- 让我们快速地对
test
数据集执行上述步骤:
enc = OneHotEncoder()enc.fit(test_label[:,None])test_encoded = enc.transform(test_label[:,None]).toarray()test_reader = Batch_Reader(test_data, test_encoded)
- 现在,让我们创建一个 CNTK 神经网络模型。我们首先定义一些常量:
dimensions = 784classes = 10hidden_layers = 3hidden_layers_neurons = 400
我们将输入数据的维度定义为784
。回想一下我们在第三章《创建你的第一个深度学习 Web 应用》中使用的 MNIST 数据集。MNIST 数据集中的图像以单维数组格式存储,包含 28 x 28 个值,范围从0
到255
。这些图像属于 10 个不同的类别,对应阿拉伯数字系统中的每个数字。我们保留了 3 个隐藏层,每个隐藏层有 400 个神经元。
- 然后我们创建两个 CNTK 的
input
变量,用于在创建模型时使用。这是 CNTK 中最重要的概念之一。
input = C.input_variable(dimensions)label = C.input_variable(classes)
在 CNTK 中,input
变量本质上是一个占位符,我们在模型训练、评估或测试时用来填充样本。从数据集中获取的输入形状必须与此步骤中声明的input
变量的维度完全匹配。这里需要特别提到的是,很多人将输入的维度与数据集的特征数混淆。一个具有N个特征和M个样本的数据集,其形状为(M, N),因此该数据集的维度仅为2
:
def create_model(features): with C.layers.default_options(init = C.layers.glorot_uniform(), activation = C.ops.relu): hidden_out = features for _ in range(hidden_layers): hidden_out = C.layers.Dense(hidden_layers_neurons)(hidden_out) network_output = C.layers.Dense(classes, activation = None)(hidden_out) return network_output
- 我们创建了
create_model()
方法,它以特征作为输入参数。
首先,为模型设置默认值,使用均匀分布来初始化权重和其他值。默认的激活函数设置为ReLU
。
第一层包含特征本身,最终层包含一个维度等于类别数的向量。中间的所有层包含一个完全连接的网络,拥有 3 个隐藏层,每个隐藏层有 400 个神经元,并使用 ReLU 激活:
model = create_model(input/255.0)
最后,我们使用前面的函数创建模型。通过255
进行除法运算,实现数据集的归一化,将图像数组中的值限制在0
和1
之间。
训练 CNTK 模型
模型创建完成后,我们现在可以进行模型训练并让其学习预测。为此,我们需要使用 CNTK 模型对象,并将数据集中的样本拟合到它。与此同时,我们还需要记录 loss
和其他评估指标。我们需要执行以下步骤来训练模型:
- 创建
loss
和分类误差的占位符:
loss = C.cross_entropy_with_softmax(model, label)label_error = C.classification_error(model, label)
- 现在,我们可以为 CNTK 框架设置一个
trainer
对象,用于执行实际的训练:
lrs = C.learning_rate_schedule(learning_rate, C.UnitType.minibatch)learner = C.sgd(model.parameters, lrs)trainer = C.Trainer(model, (loss, label_error), [learner])
- 现在,让我们进行训练:
epochs = 10num_iters = (num_samples * epochs) / batch_sizefor i in range(int(num_iters)): batch_data, batch_label = train_reader.next_batch(batch_size=batch_size) arguments = {input: batch_data, label: batch_label} trainer.train_minibatch(arguments=arguments) if i % 1000 == 0: training_loss = False evalaluation_error = False training_loss = trainer.previous_minibatch_loss_average evalaluation_error = trainer.previous_minibatch_evaluation_average print(\"{0}: , Loss: {1:.3f}, Error: {2:.2f}%\".format(i, training_loss, evalaluation_error * 100))
我们将训练的 epoch 数设置为 10
,以便进行快速训练和评估。你可以将其设置为更高的值以提高训练的准确性;然而,这可能在某些情况下导致没有更好的训练效果或过拟合。在每次达到 1,000 次迭代时,我们都会显示到目前为止的损失和评估误差。这些值的整体趋势应该是下降的。
测试并保存 CNTK 模型
在继续使用 Django 框架将此项目转换为 Web 应用程序之前,让我们快速测试一下模型在此训练中的准确性。我们将执行以下操作,从模型中进行预测:
predicted_label_probs = model.eval({input: test_data})
这将为数据集中的每个标签创建一个 NumPy 概率数组。必须将其转换为索引并与测试数据的标签进行比较。我们按如下方式进行操作:
predictions = np.argmax(predicted_label_probs, axis=1)actual = np.argmax(test_encoded, axis=1)correct = np.sum(predictions == actual)print(correct / len(actual))
我们发现预测准确率约为 98%。这是一个非常好的值,我们将继续保存模型并通过 Django 使用它。保存 CNTK 模型的方法如下:
model.save(\"cntk.model\")
成功保存模型后,如果你使用了 Colaboratory 来构建模型,你需要将 model
文件下载到本地系统。接下来,我们可以继续将模型部署到基于 Django 的服务器上。
Django Web 开发简介
Django 是使用 Python 进行 Web 开发的最流行框架之一。该框架轻量、健壮,并且得到社区的积极维护,社区会迅速修补安全漏洞并添加新特性。本书中我们介绍了 Flask 框架,它本质上是一个用于 Python Web 开发的简单框架。然而,Django 提供了许多内建功能,实施了最先进的方法和实践。
Django 项目的初始结构如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/220c2b95-9ed4-4521-9ee1-9937f6e28fec.png
这些文件是在使用 django-admin
工具创建新 Django 项目时自动生成的。顶级目录 mysite
表示 Django 项目的名称。每个 Django 项目包含多个应用程序。应用程序类似于软件开发中的模块概念。它们通常是完整项目中的独立部分,并通过项目目录中的 mysite
主应用程序组合在一起。每个项目内部可以有多个应用程序。
让我们学习如何开始使用 Django 并创建一个新项目!
入门 Django
使用 Django 之前的首要步骤是安装它。幸运的是,这个框架可以轻松地作为一个模块从 Python PIP 仓库安装。它也可以在 Conda 仓库中找到。要安装 Django,打开一个新的终端窗口并使用以下命令:
conda install django
或者,如果你更喜欢使用 PIP,可以使用以下命令:
pip install django
这将把 Django 模块安装到你的 Python 环境中。
要检查是否已成功安装,请在终端中使用以下命令:
python -m django --version
这应该会输出一个版本号,例如- 2.0.8
。如果没有,请检查你的 Django 安装。
创建一个新的 Django 项目
Django 提供了一个名为django-admin
的便捷工具,可以用来生成 Django 项目所需的模板代码。要创建一个名为cntkdemo
的新项目,请使用以下代码:
django-admin startproject cntkdemo
这将创建所有的模板文件和文件夹。但是,我们必须在项目中创建至少一个应用。通过终端将当前工作目录更改为cntkdemo
文件夹。使用以下命令在此项目中创建一个应用:
python manage.py startapp api
因此,我们创建了一个名为api
的文件夹,其中包含以下文件夹;所有文件都带有自动生成的占位符代码和文档:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/3d297b46-da99-422e-aab5-4dfb5cbc90e6.png
现在我们可以继续进行初步 UI 的编码了。
设置首页模板
现在,让我们创建一个当访问/
路由时加载的网页。还记得我们在项目中创建的api
应用吗?为了简化起见,我们将把首页作为这个应用的一部分。虽然可以在mysite
应用的urls.py
文件中创建这个路由,但我们会为api
应用提供一个独立的路由处理文件。
让我们从设置首页模板的步骤开始:
- 在
api
文件夹中创建一个文件urls.py
。这个文件相对于项目目录的完整路径是mysite/api/urls.py
。在这个文件中,让我们使用以下代码添加/
路由:
from django.urls import pathfrom . import viewsurlpatterns = [ path(\'\', views.indexView), # This line handles the \'/\' route.]
-
保存此文件。前面的代码本质上为
api
应用添加了一个新路径/
(注意,这不是项目的路径!)。它导入了api
应用中的所有视图(views.py
文件)。请注意,indexView
仍然不存在。我们将在下一步后创建这个视图。 -
api
应用没有链接到主项目应用。我们需要在mysite/mysite/urls.py
文件中添加以下几行,以便启用api
应用的路由处理:
from django.contrib import adminfrom django.urls import pathfrom django.urls import include # -- Add this line!urlpatterns = [ path(\'\', include(\'api.urls\')), # -- Add this line! path(\'admin/\', admin.site.urls),]
第一行导入了一个工具,用于将特定于应用的路由设置包含到项目应用中。我们通过使用api.urls
字符串,将urls.py
文件包含到api
应用中。这会自动将字符串转换为代码行,试图找到并包含正确的文件。
- 在
api
应用目录中的views.py
文件中,添加以下几行代码:
from django.http import HttpResponsefrom django.template import loader
HttpResponse
方法允许view
方法返回一个 HTML 响应。loader
类提供了从磁盘加载 HTML 模板的方法。
- 现在,我们创建
indexView
方法:
def indexView(request): template = loader.get_template(\'api/index.html\') context = {} return HttpResponse(template.render(context, request))
indexView
方法加载api/index.html
模板文件,并使用context
字典中提供的变量以及可用于模板的request
参数进行渲染。目前,我们传递一个空的上下文,因为我们没有任何值要发送到模板。但如前所述,之前定义的api/index.html
文件并不存在。
- 让我们创建一个用于存放模板的文件夹,并将其链接到项目设置中。为此,进入项目的根目录并创建一个名为
templates
的文件夹。我们需要让项目能够识别该文件夹作为模板的目录。为此,我们需要修改mysite/mysite/settings.py
文件中的TEMPLATES
设置:
TEMPLATES = [ { \'BACKEND\': \'django.template.backends.django.DjangoTemplates\', \'DIRS\': [os.path.join(BASE_DIR, \'templates\')], # -- Add this line! \'APP_DIRS\': True, \'OPTIONS\': { \'context_processors\': [
添加前述行后,项目将会在mysite/templates/
文件夹中查找模板。
-
创建
index.html
模板文件。请注意,我们在第 4 步中提到的模板文件路径存在于
api
目录中。在templates
目录下创建一个名为api
的文件夹。在这个文件夹中,创建index.html
文件,并添加以下代码:
{% load static %}... <div class=\"jumbotron\"> <h3 class=\"jumbotronHeading\">Draw here!</h3> ... </div> <div class=\"jumbotron\"> <h3>Prediction Results</h3> <p id=\"result\"></p> </div> <div id=\"csrf\">{% csrf_token %}</div> </div> <script src=\'https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js\'></script> <script src=\"img/{% static \"/index.js\" %}\"></script>...
我们在前面的代码块的末尾包含了一些必需的脚本,其中包括从后端获取 CSRF token 的脚本。
- 现在,让我们在前面的代码块中,向具有
jumbotron
类的div
元素中添加一个canvas
元素,我们将在该元素上绘制数字。我们还将添加一个滑动条,用于选择绘图笔的宽度,如下所示:
<div class=\"jumbotron\"> <h3 class=\"jumbotronHeading\">Draw here!</h3> <div class=\"slidecontainer\"> <input type=\"range\" min=\"10\" max=\"50\" value=\"15\" id=\"myRange\"> <p>Value: <span id=\"sliderValue\"></span></p> </div> <div class=\"canvasDiv\"> <canvas id=\"canvas\" width=\"350\" height=\"350\"></canvas> <p style=\"text-align:center;\"> <button class=\"btn btn-success\" id=\"predict-btn\" role=\"button\">Predict</button> <button class=\"btn btn-primary\" id=\"clearButton\" role=\"button\">Clear</button> </p> </div> </div>
template
文件还包含了两个静态文件——style.css
和 script.js
。我们将在接下来的部分中创建这些文件。目前我们还没有创建用于将数据发送到服务器并呈现收到的响应的脚本。
- 现在,我们将开始添加与后端 API 通信所需的 JavaScript 代码。首先,我们创建一个方法来检查是否需要 CSRF token 来与后端通信。这只是一个工具函数,与调用后端 API 无关,因为有时后端 API 会被设计为接受没有 CSRF token 的请求。我们创建这个函数,如下所示:
<script type=\"text/javascript\"> function csrfSafeMethod(method) { return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); }
- 然后,我们为
Predict
按钮创建一个click
处理程序。这个处理程序函数首先设置所需的正确头信息以便与后端 API 通信,然后将画布上的绘图转换为数据 URL 字符串:
$(\"#predict-btn\").click(function() { var csrftoken = $(\'input[name=csrfmiddlewaretoken]\').val(); $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader(\"X-CSRFToken\", csrftoken); } } }); $(\'#predict-btn\').prop(\'disabled\', true); var canvasObj = document.getElementById(\"canvas\"); var img = canvasObj.toDataURL(); // MORE CODE TO BE ADDED BELOW THIS LINE // MORE CODE TO BE ADDED ABOVE THIS LINE }); </script>
- 最后,我们将代码添加到
Predict
按钮的click
处理函数中,以便通过 Ajax 调用后端,将画布中的数据发送出去,如下所示:
$(\"#predict-btn\").click(function() {... // MORE CODE TO BE ADDED BELOW THIS LINE $.ajax({ type: \"POST\", url: \"/predict\", data: img, success: function(data) { console.log(data); var tb = \"Item Confidence \"; var res = JSON.parse(data); console.log(res); $(\'#result\').empty.append(res.data); $(\'#predict-btn\').prop(\'disabled\', false); } }); // MORE CODE TO BE ADDED ABOVE THIS LINE...}); </script>
- 在我们创建静态文件之前,我们需要为它们创建一个文件夹并将其链接到项目中。这与我们创建
templates
文件夹的方式类似。首先,在项目目录中创建一个名为static
的文件夹,路径为mysite/static/
。然后,修改mysite/mysite/settings.py
文件中的STATIC
配置,如下所示:
STATIC_URL = \'/static/\'STATICFILES_DIRS = [ os.path.join(BASE_DIR, \"static\"), # -- Add this line!]
现在,我们可以像在index.html
文件中一样,使用模板文件顶部的{% load static %}
指令将静态文件加载到项目模板中。
- 创建
style.css
和script.js
文件—由于这些文件与本书的上下文没有直接关系,你可以直接从tiny.cc/cntk-demo
下载它们。
请注意,如果没有script.js
文件,项目将无法运行。
我们已经为在index.html
模板文件中绘制的图像预测创建了设置。然而,/predict
路由尚未创建。接下来的部分我们将看到如何在 Django 中加载并使用 CNTK 模型。
使用 Django 项目中的 CNTK 进行预测
在这一部分中,我们将首先设置所需的路由、视图和 CNTK 模型的导入,以便与 Django 一起使用。然后,我们将从保存的文件中加载 CNTK 模型,并使用它进行预测。
设置预测路由和视图
回想一下我们如何在api
应用中创建/
路由及其对应的视图:
- 首先,将以下行添加到
mysite/api/urls.py
中:
urlpatterns = [ path(\'\', views.indexView), path(\'predict\', views.predictView), # -- Add this line!]
这创建了/predict
路由。然而,视图predictView
尚未创建。
- 将以下行添加到
api
应用的views.py
文件中:
from django.http import JsonResponsedef predictView(request): # We will add more code below this line # We will add more code above this line return JsonResponse({\"data\": -1})
请注意前面代码行中的占位符。我们将在接下来的步骤中在这里添加更多内容。
导入必要的模块
现在,让我们加载所有必要的模块,以便按照以下步骤使用 CNTK 模型进行预测:
- 将以下导入语句添加到
api
应用的views.py
文件中:
import osfrom django.conf import settings
- 我们需要前面的导入语句来从磁盘加载模型:
import cntk as Cfrom cntk.ops.functions import load_model
前面的代码行将 CNTK 模块导入 Django 项目。load_model
方法将帮助我们加载保存的 CNTK 模型文件。
以下模块用于处理进行预测时使用的图像:
from PIL import Imageimport numpy as np
以下模块提供了处理 Base64 编码字符串的实用功能,这是index.html
页面在请求中发送画布数据的格式:
import reimport base64import random import string
其他库将在它们在接下来的部分中使用时进行解释。
使用 CNTK 模型进行加载和预测
现在,我们将通过以下步骤进一步编辑predictView
视图:
- 首先,使用以下代码将 Base64 编码的图像字符串数据读取到变量中:
def predictView(request): # We will add more code below this line post_data = request.POST.items() pd = [p for p in post_data] imgData = pd[1][0].replace(\" \", \"+\") imgData += \"=\" * ((4 - len(imgData) % 4) % 4)
Base64 解码后的字符串没有适当的填充,并且包含需要转换为+
的空格。前面代码块中的最后两行对字符串进行了相同的操作。
- 接下来,我们将把这个 Base64 编码的字符串转换为 PNG 图像,并使用以下代码保存到磁盘:
filename = \'\'.join([random.choice(string.ascii_letters + string.digits) for n in range(32)])convertImage(imgData, filename)
第一行创建了一个 32 字符长的随机字符串作为文件名。下一行调用了convertImage
方法,将base64
字符串存储为提供的文件名。
- 然而,
convertImage
方法尚未定义。在predictView
方法外部,按如下方式添加该函数的定义:
def convertImage(imgData, filename): imgstr = re.search(r\'base64,(.*)\', str(imgData)).group(1) img = base64.b64decode(imgstr) with open(filename+\'.png\', \'wb\') as output: output.write(img)
该方法会从字符串中去除多余的元数据,然后解码该字符串并将其保存为 PNG 文件。
- 让我们回到
predictView
方法。我们将首先加载保存的 image
文件:
image = Image.open(filename+\'.png\').convert(\'1\')
我们还将把图像转换为仅黑白通道。这将图像中的通道数从 3 降至 1。
- 回想一下,MNIST 数据集中的所有图像的尺寸都是 28 x 28。我们必须将当前图像调整为相同的尺寸。我们通过以下代码来实现:
image.thumbnail((28,28), Image.ANTIALIAS)
- 现在,我们使用以下代码将图像转换为 NumPy 数组:
image_np = np.array(image.getdata()).astype(int)image_np_expanded = np.expand_dims(image_np, axis = 0)
np.expanded_dims
是 NumPy 中的一个简单工具,用于为数组添加额外的维度,以便与大多数机器学习库兼容。
-
加载 CNTK 模型。首先,在项目的根目录创建一个名为 data
的文件夹,并将保存的 model
文件复制到 mysite/data/cntk.model
中。
我们现在在 predictView
方法中加载 CNTK 模型,如下所示:
model = load_model(os.path.join(settings.BASE_DIR, \"data/cntk.model\"))
- 最后,我们可以预测图像的标签,如下所示:
predicted_label_probs = model.eval({model.arguments[0]: image_np_expanded})data = np.argmax(predicted_label_probs, axis=1)
eval
方法的第一个参数期望传入图像的 NumPy 数组,并返回每个输出类别的概率列表。np.argmax
方法用于找到具有最高概率的类别的索引。
- 要返回输出,请修改
predictView
方法中的 return
部分,如下所示:
# We will add more code above this line return JsonResponse({\"data\": str(data[0])})
图像的预测标签作为包含在 data
变量中的数字发送,响应的 JSON 数据会在页面上显示。
测试网页应用程序
最后,我们可以测试我们开发的 CNTK + Django 应用程序。为此,打开终端并将其切换到项目的根目录。
使用以下命令启动 Django 服务器:
python manage.py runserver
如果端口空闲,服务器会在 localhost:8000
启动。打开网页浏览器,点击提供的画布上绘制数字并点击预测按钮。你可以在页面底部看到模型的预测结果,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-py-dl-web/img/b717132a-d629-41e8-b622-7424137ccf76.png
请注意,模型在前面的屏幕截图中返回了正确的输出,即 2。因此,我们得出结论,CNTK 模型通过 Django 部署已完成。
总结
在这一章,我们介绍了 Microsoft AI 和 Azure 云服务在网站上执行深度学习的相关功能。我们看到了如何使用面部 API 来预测图像中人物的性别和年龄,以及如何使用文本分析 API 来预测给定文本的语言、关键短语或任何句子的情感。最后,我们使用 CNTK 在 MNIST 数据集上创建了一个深度学习模型。我们展示了如何保存模型,并通过基于 Django 的 Web 应用程序将其作为 API 部署。通过 Django 部署保存的模型可以轻松适配其他深度学习框架,如 TensorFlow 或 PyTorch。
在下一章,我们将讨论一个通用框架,用于使用 Python 构建生产级深度学习应用程序。