_ 作者选择了 代码 2040作为 写给捐款计划的一部分,以接收捐款。
介绍
随着机器学习领域(ML)的增长,使用这种技术的环境列表也随之增加. 其中一种环境是网页浏览器,近年来,针对基于网络的机器学习模型的数据相关框架激增. 这些框架的一个例子是TensorFlow.js,TensorFlow的JavaScript对应库,用于培训,执行和在浏览器中部署机器学习模型. 为了让拥有有限或没有ML经验的开发者能够访问TensorFlow.js,库中出现了几个经过预先训练的模型,这些模型在盒外工作.
训练有素的机器学习模式是随时可以使用的机器学习, TensorFlow.js包括14个适合各种用途的病例. 例如,有一个图像分类模型用于识别常见物体,还有一个身体分化模型用于识别身体部分. 这些模式的主要方便在于,随着名称的出现,你不必训练它们. 相反,你装入你的应用程序。 这些模型不仅便于使用,而且具有预先训练的性质,而且精准而快,有时由算法作者培训,为网页浏览器优化.
在本教程中,您将创建一个 Web 应用程序,使用 TensorFlow.js 服务一个 问题和答案 (QnA) 预先训练的模型,您将部署的模型是 Bidirectional Encoder Representations from Transformers (BERT) 模型,它使用一个通道和一个问题作为输入,并试图从通道中回答问题。
您将部署应用程序在DigitalOcean的应用平台中,这是一个可管理的解决方案,用于在GitHub等来源的几个点击之内构建,部署和扩展应用程序.您将创建的应用程序由一个静态页面组成,其中有两个输入字段,一个用于通道和一个用于问题。
前提条件
要完成本教程,您将需要:
- [数字海洋] (https://cloud.digitalocean.com/)账户。
- 联合国 在 GitHub 上的一个账户,您可以通过访问 [ 创建您的账户** 页] (https://github.com/join) 来创建该账户。
- 配置并安装在您的本地机器上。 见[如何为开放源码作出贡献:从Git开始(https://andsky.com/tech/tutorials/how-to-contribute-to-open-source-getting-started-with-git),以及[如何使用Git:一个参考指 (https://www.digitalocean.com/community/cheatsheets/how-to-use-git-a-reference-guide)中的参考指针.
- 联合国 您还需要对 HTML 、 CSS 和 JavaScript 的基本知识, 您可以在我们 [ How To Build a website With HTML series] (https://www.digitalocean.com/community/tutorial_series/how-to-build-a-website-with-html), [ How To Build a website With CSS series] (https://www.digitalocean.com/community/tutorial_series/how-to-build-a-website-with-css) 和 [How To Code in JavaScript (https://www.digitalocean.com/community/tutorial_series/how-to-code-in-javascript) 中找到这些知识。 .
步骤 1 — 创建应用的界面并导入所需的库
在此步骤中,您会写入应用的HTML代码,该代码将定义其界面并导入应用程序的库. 其中第一个库是 TensorFlow.js , 而不是在本地安装软件包, 您将从 content 递送网络 或 CDN 中加载它 。 CDN是一个服务器网络, 覆盖多个地点, 此内容包括JavaScript文件, 如 TensorFlow.js 库, 从一个 CDN 中加载它可以保存您在应用程序中的包装 。 同样,您将导入包含问答模式的库。 下一步,您会写出该应用的JavaScript,它使用模型来回答一个特定的问题.
在本教程中,您将构建一个看起来像这样的应用程序:
应用程序有五个主要元素:
- 可用于测试应用程序的预定义通道的按钮。 * 一个输入文本字段(如果您选择写或复制自己的通道)。 * 一个输入文本字段为该问题。 * 一个触发回答问题的预测按钮。 * 一个显示模型输出的区域在 ** 回答! 按钮下面(目前是空白空间)。
在此目录中,使用您所选择的文本编辑器,创建一个名为index.html的新HTML文件,并粘贴到以下代码:
1[label index.html]
2<!DOCTYPE html>
3<html lang="en-US">
4
5<head>
6 <meta charset="utf-8" />
7 <!-- Load TensorFlow.js -->
8 <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
9 <!-- Load the QnA model -->
10 <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/qna"></script>
11 <link href="./style.css" rel="stylesheet">
12</head>
13
14<body>
15 <div class="main-centered-container">
16 <h1>TensorFlow.js Pre-trained "QnA" BERT model</h1>
17 <h3 class="header-border">Introduction</h3>
18 <p>This application hosts TensorFlow.js' pre-trained Question and Answer model, and it attempts to answer the question
19 using a given passage. To use it, write a passage (any!) in the input area below and a question. Then, click the
20 "answer!" button to answer the question using the given passage as a reference. You could also click the test
21 button to load a pre-defined input text.</p>
22
23 <h4>Try the test passage!</h4>
24 <div id='test-buttons'></div>
25
26 <div>
27 <h4>Enter the model's input passage here</h4>
28 <textarea id='input-text' rows="20" cols="100" placeholder="Write the input text..."></textarea>
29 </div>
30
31 <div>
32 <h4>Enter the question to ask</h4>
33 <textarea id='question' rows="5" cols="100" placeholder="Write the input text..."></textarea>
34 </div>
35 <h4>Click to answer the question</h4>
36 <div id="answer-button"></div>
37 <h4>The model's answers</h4>
38 <div id='answer'></div>
39
40 <script src="./index.js"></script>
41
42 </div>
43</body>
44
45</html>
以下是如何破坏HTML:
- 联合国 最初的"
<"有"
<"的标记. 用于定义元数据、样式和加载脚本的标签。 它的第一个元素是"<"( meta>
),在这里您将把页面的'charset'编码为'utf-8'. 之后,有两个"QQscriptQ"标记,用于从一个CDN上同时装入TensorFlow.js和"问答"模型. - 联合国 跟着这两本小说 标记,有一个 QQlinkQQ 标记可以装入 CSS 文件( 您将创建它) 。
- 接下来是HTML的
正文'文件的内容。 其内部有"以主为中心-容器"类的"
<"( div>)标记,包含该页的元素. 第一个是带有应用程序标题的QQh1>
头和一个较小的QQh3>`头,然后是简短的介绍,解释它是如何工作的. - 联合国 在引言下,有一个
<h4>
头和一个<div>
在其中,您将附加按钮,以样本文本填充段落输入文本字段. - 联合国 然后,还有应用程序的输入字段:一个是给通过(你想让模型读什么),一个是给问题(你想让模型回答什么). 如果要调整大小,请改变
rows'和
cols'属性。 - 联合国 在文本字段后,有一个有 id
按钮
的 QQdiv 。 在其中,您以后会附加一个按钮,在单击时,该按钮将读取文本字段的文本,并将其作为模型的输入。 - 最后,有一个`回答 ' 。 用于显示模型的输出以及包含您将在下一节所写的 JavaScript 代码的 QQscript 标记 。 .
接下来,您将添加 CSS 到项目中. 在您添加了 index.html 文件的相同目录中,创建一个名为 style.css 的新文件,并添加以下代码:
1[label style.css]
2body {
3 margin: 50px 0;
4 padding: 0;
5 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial;
6}
7
8button {
9 margin: 10px 10px;
10 font-size: 100%;
11}
12
13p {
14 line-height: 1.8;
15}
16
17.main-centered-container {
18 padding: 60px;
19 display: flex;
20 flex-direction: column;
21 margin: 0 auto;
22 max-width: 960px;
23}
24
25.header-border {
26 border: solid #d0d0d0;
27 border-width: 0 0 1px;
28 padding: 0 0 5px;
29}
CSS 将风格添加到三个 HTML 元素中:体、按钮和段落(‘
’)。 对于体
,它会添加一个边缘、插头,并改变默认字体。 对于按钮
,它会添加边缘并增加字体大小。 对于p
段落,它会修改线高
属性。 CSS 有一个类主中心容器
,以中心化内容,另一个类标题边界
,为元素添加一个坚实的线。
在此步骤中,您写了应用程序的 HTML 文件。您导入了 TensorFlow.js 库和 QnA 模型,并定义了您以后将使用的元素,以添加您想要回答的段落和问题。
步骤2 – 使用预训练模型预测
在本节中,您将实施Web应用程序的JavaScript代码,该代码读取应用程序的输入字段,做一个预测,并在HTML中写出预测的答案。您将在一个函数中执行,当您点击答案
按钮时启动。一旦点击,它将引用两个输入字段以获取其值,将其用作模型输入,并在<div>
中写出您在步骤1中定义的ID输出
,然后,您将本地运行应用程序来测试它,然后将其添加到GitHub。
在项目的目录 tfjs-qna-do/
中,创建一个名为 `index.js 的新文件,并声明以下变量:
1[label index.js]
2let model;
3
4// The text field containing the input text
5let inputText;
6
7// The text field containing the question
8let questionText;
9
10// The div where we will write the model's answer
11let answersOutput;
其中第一个变量,即模型
,是您将存储QnA模型的地方;inputText
和questionText
是输入和问题文本字段的参考;answersOutput
是输出<div>
的参考。
除了这些变量之外,您还需要一个常数来存储您将使用的样本文本来测试应用程序. 我们将使用 DigitalOcean上的维基百科文章作为样本通道. 基于这个通道,您可以向模型提出像DigitalOcean总部在哪里?
这样的问题,希望它会输出纽约
。
将此块复制到您的 index.js 文件中:
1[label index.js]
2// Sample passage from Wikipedia.
3const doText = `DigitalOcean, Inc. is an American cloud infrastructure provider[2] headquartered in New York City with data centers worldwide.[3]
4DigitalOcean provides developers cloud services that help to deploy and scale applications that run simultaneously on multiple computers.
5DigitalOcean also runs Hacktoberfest which is a month-long celebration (October 1-31) of open source software run in partnership with GitHub and Twilio.
6`;
现在,您将定义应用程序的功能,从createButton()
开始,该功能会创建一个按钮并将其附加到HTML元素中:
1[label index.js]
2function createButton(innerText, id, listener, selector, disabled = false) {
3 const btn = document.createElement('BUTTON');
4 btn.innerText = innerText;
5 btn.id = id;
6 btn.disabled = disabled;
7
8 btn.addEventListener('click', listener);
9 document.querySelector(selector).appendChild(btn);
10}
「createButton()」是创建应用程序的两个按钮的函数,因为所有按钮都起到相似的作用,因此该函数可以避免重复代码。
innerText
:按钮的文本. *id
:按钮的 id. *listener
:当用户点击按钮时执行的回调函数. *selector
:您将附加按钮的div>
元素. *disabled
:为禁用或启用按钮的布尔值. 此参数的默认值是false
。
createButton()
始于创建一个按钮的实例,并将其分配给变量 btn
. 然后,它会设置按钮的 innerText
、 id
和 disabled
属性。 按钮使用一个点击事件倾听器,每次你点击它时执行调用函数。 函数的最后一行将按钮附加到指定在 selector
参数中的 `div> 元素。
接下来,您将创建一个名为)`两次,以创建应用程序的按钮。
1[label index.js]
2function setupButtons() {
3 // Button to predict
4 createButton('Answer!', 'answer-btn',
5 () => {
6 model.findAnswers(questionText.value, inputText.value).then((answers) => {
7 // Write the answers to the output div as an unordered list.
8 // It uses map create a new list of the answers while adding the list tags.
9 // Then, we use join to concatenate the answers as an array with a line break
10 // between answers.
11 const answersList = answers.map((answer) => `<li>${answer.text} (confidence: ${answer.score})</li>`)
12 .join('<br>');
13
14 answersOutput.innerHTML = `<ul>${answersList}</ul>`;
15 }).catch((e) => console.log(e));
16 }, '#answer-button', true);
17}
函数创建的第一个按钮是触发预测的按钮. 它的前两个参数). 第四个参数selector'是您想要添加按钮的"div"的代号(QQ-answer-button"),而第五个参数
disabled'被设定为` true',它禁用按钮(以避免在应用程序加载模型之前预测).
收听器的回调是一个功能,一旦点击了Answer! 按钮就执行. 点击后,回调函数首先将预训模型的函数称为"findAnswers ()". (关于findAnswers ()'函数的更详细情况,见[产品文件](https://www.npmjs.com/package/@tensorflow-models/qna#find-the-answers))。
findAnswers () ' 将输入段落(从问题文本 ' 读取)和问题(从
输入文本 ' 读取)作为论据。) 它在一个外观如下的阵列中返回模型的输出 :
1[secondary_label Model's output]
2[
3 {
4 "text": "New York City",
5 "score": 19.08431625366211,
6 "startIndex": 84,
7 "endIndex": 97
8 },
9 {
10 "text": "in New York City",
11 "score": 8.737937569618225,
12 "startIndex": 81,
13 "endIndex": 97
14 },
15 {
16 "text": "New York",
17 "score": 7.998648166656494,
18 "startIndex": 84,
19 "endIndex": 92
20 },
21 {
22 "text": "York City",
23 "score": 7.5290607213974,
24 "startIndex": 88,
25 "endIndex": 97
26 },
27 {
28 "text": "headquartered in New York City",
29 "score": 6.888534069061279,
30 "startIndex": 67,
31 "endIndex": 97
32 }
33]
数组的每个元素都是四个属性的对象:
text
:答案. *score
:模型信任级别. *startIndex
:回答问题的段落的第一个字符的索引. *endIndex
:答案的最后字符的索引。
代替在模型返回时显示输出时,调用函数使用map()
函数,创建一个包含模型的答案和分数的新数组,同时添加列表<li>
的HTML标签。
接下来,添加第二个调用到createButton()
。
1[label index.js]
2function setupButtons() {
3 // Button to predict
4 createButton('Answer!', 'answer-btn',
5 () => {
6 model.findAnswers(questionText.value, inputText.value).then((answers) => {
7 // Write the answers to the output div as an unordered list.
8 // It uses map create a new list of the answers while adding the list tags.
9 // Then, we use join to concatenate the answers as an array with a line break
10 // between answers.
11 const answersList = answers.map((answer) => `<li>${answer.text} (confidence: ${answer.score})</li>`)
12 .join('<br>');
13
14 answersOutput.innerHTML = `<ul>${answersList}</ul>`;
15 }).catch((e) => console.log(e));
16 }, '#answer-button', true);
17
18 createButton('DigitalOcean', 'test-case-do-btn',
19 () => {
20 document.getElementById('input-text').value = doText;
21 }, '#test-buttons', false);
22}
这个新调用附加到),第二个参数是)。
接下来,您将创建一个名为init() 的函数,该函数呼叫其他函数:
1[label index.js]
2async function init() {
3 setupButtons();
4 answersOutput = document.getElementById('answer');
5 inputText = document.getElementById('input-text');
6 questionText = document.getElementById('question');
7
8 model = await qna.load();
9 document.getElementById('answer-btn').disabled = false;
10}
然后,它将应用程序的某些HTML元素分配给你在脚本顶部定义的变量。接下来,它会加载QnA模型,并更改答案的禁用属性(‘answer-btn’)按钮为‘false’。
最后,请拨打init()
:
1[label index.js]
2init();
要测试它,请打开您的网页浏览器,并在地址栏中添加到该项目的目录绝对路径 /index.html. 你也可以打开您的文件管理程序(如 Mac 上的 Finder)并点击
index.html来打开 Web 应用程序. 在这种情况下,地址将看起来像
your_filepath/tfjs-qna-do/index.html`。
要找到绝对路径,请前往终端,并从项目目录中执行以下命令:
1pwd
它的产量将是这样的:
1[secondary_label Output]
2/Users/your_filepath/tfjs-qna-do
在启动应用程序后,您需要等待几秒钟,而该应用程序下载和加载模型。当应用程序启用 回答! 按钮时,您将知道该应用程序已经准备好了。
要测试应用程序,点击DigitalOcean
按钮。在通道输入区域,你会看到关于DigitalOcean的样本文本。在问题输入区域,写DigitalOcean总部在哪里?
从通道中,我们可以看到答案是纽约
。但是模型会说同样的话吗?点击 回答! 来找出。
结果应该是这样的:
虽然有轻微的差异,但五个答案中有四个表示DigitalOcean总部位于纽约市。
在此步骤中,您完成并测试了 Web 应用程序. 您写的 JavaScript 代码读取了输入通道和问题,并将其用作 QnA 模型的输入来回答问题。
步骤 3 – 将应用推到 GitHub
在本节中,您将 Web 应用程序添加到 GitHub 存储库中,随后将该存储库连接到 DigitalOcean 应用平台并部署该应用程序。
从其主页开始,点击你的名字下面的绿色按钮或屏幕右上角的加标记来创建一个新的存储库。
任何一个选择都会带你到),命名存储库 tfjs-qna-do 。
打开终端,进入项目的目录 tfjs-qna-do/
. 在那里,执行以下命令来创建一个新的本地Git存储库:
1git init
接下来,您要使用 Git 跟踪的文件,在这种情况下,是目录中的所有内容:
1git add .
并使他们:
1git commit -m "initial version of the app"
重命名存储库的主要分支机构为main
:
1git branch -M main
然后将您的本地存储库链接到GitHub上的远程存储库:
1git remote add origin [email protected]:your-github-username/tfjs-qna-do.git
最后,将本地代码库推到远程存储库:
1git push -u origin main
它会要求你输入你的GitHub凭证,如果这是你第一次将代码推到它。
一旦你推了代码,回到GitHub存储库并更新页面,你应该看到你的代码。
在此步骤中,您将您的 Web 应用程序的代码推到远程 GitHub 存储库,然后将该存储库链接到您的 DigitalOcean 帐户并部署该应用程序。
步骤4:在DigitalOcean应用平台部署Web应用程序
在这最后一节中,您将部署))从在步骤 3 中创建的GitHub存储库中。
一旦登录,点击右上角的 创建 绿色按钮,然后点击** 应用程序** ;这将带您到** 创建新应用程序** 屏幕:
在这里,选择 GitHub 作为项目所在的源。
如果您没有将您的 DigitalOcean 帐户链接到 GitHub,它将要求您授权 DigitalOcean 访问您的 GitHub。
在 App Platform 窗口中,选择应用程序的存储库(tfjs-qna-do ),它将部署应用程序的分支机构(** main** ),并检查** Autodeploy 代码更改** 框;此选项确保应用程序每次将代码推到** main** 分支机构时重新部署。
在下一个屏幕中, 配置您的应用程序 ,使用默认配置值。作为一个额外的步骤,如果您希望更改 Web 应用程序的 HTTP 请求路线,例如,从默认 https://example.ondigitalocean.app/tfjs-qna-do,到 https://example.ondigitalocean.app/my-custom-route,点击** Edit** 在** HTTP 路线** 下,并在** ROUTES** 输入中输入 my-custom-route。
再一次,你可以留下默认的 tfjs-qna-do 名称或用另一个名称取代它。
点击 Next 将带您到最后一个屏幕,** 完成和启动** ,在那里您将选择应用程序的定价层。由于应用程序是一个静态的网页,App Platform将自动选择免费的启动计划。
当应用程序部署时,您将看到一个类似于此的屏幕:
一旦部署,你会看到:
要访问应用程序,请单击应用程序的 URL 来访问您的应用程序,该应用程序现在在云中部署。
结论
随着机器学习领域的扩张,它与它所接触的环境和平台(包括Web浏览器)一起使用的案例也是如此。
在本教程中,您已经构建并部署了一种使用 TensorFlow.js 预先训练的模型的 Web 应用程序. 您的 问题和答案 Web 应用程序作为输入带有问题的一段,并使用预先训练的 BERT 模型来根据段回答问题。
随着未来工作,您可以通过添加更改并将其推到GitHub来触发应用程序的自动部署,您还可以添加新的测试通道,并将答案的输出格式化为表,以提高其可读性。
有关 TensorFlow.js 的更多信息,请参阅其 官方文件。