TensorFlow.js:重新训练垃圾评论检测模型以处理极端情况

1. 准备工作

本 Codelab 以本系列上一个 Codelab 的最终结果(使用 TensorFlow.js 检测垃圾评论)为基础。

上一个 Codelab 中,您为一个虚构视频博客创建了一个功能完善的网页。您使用由 TensorFlow.js 提供支持的浏览器端预训练垃圾评论检测模型,能够在评论被发送到服务器进行存储之前,或者被发送到其他已连接的客户端之前,对评论进行过滤。

该 Codelab 的最终结果如下所示:

ee0f13398ea4e91e.gif

这种方法非常有效,但也有它无法检测到的极端情况有待探索。您可以重新训练该模型,以处理它无法处理的情况。

本 Codelab 重点介绍如何使用自然语言处理(一种用计算机理解人类语言的技术),并将向您展示如何修改您创建的现有 Web 应用(强烈建议您按顺序学习这些 Codelab),旨在解决垃圾评论这一非常现实的问题,这也是许多 Web 开发者在开发如今数量不断增长的热门应用时势必会遇到的问题。

在本 Codelab 中,您将重新训练您的机器学习模型,基于当前趋势或热门讨论主题了解随着时间的推移垃圾消息内容可能发生的变化,从而使模型保持时新性,并应对这类变化。

前提条件

  • 已完成本系列第一个 Codelab。
  • 具备 HTML、CSS 和 JavaScript 等网页技术的基础知识。

构建内容

您需要将之前构建的网站重用于带有实时评论板块的虚构视频博客,并进行升级,以使用 TensorFlow.js 加载经过训练的自定义版本垃圾内容检测模型,以便在之前可能无法处理的极端情况下实现更出色的性能。当然,作为 Web 开发者和工程师,您可以更改这种假想的用户体验,以便在您日常工作中处理的任何网站上进行重复利用,并对解决方案进行调整,使之适应任何客户端用例(可能为博客、论坛或某种形式的内容管理系统,比如 Drupal)。

我们开始行动吧...

学习内容

您将学习以下内容:

  • 识别预训练模型无法处理的极端情况
  • 重新训练使用 Model Maker 创建的垃圾内容分类模型。
  • 将这个基于 Python 的模型导出为 TensorFlow.js 格式,以便在浏览器中使用。
  • 使用新训练的模型更新托管模型及其字典,并检查结果

学习本实验的前提是要熟悉 HTML5、CSS 和 JavaScript。此外,您还将通过“Colab”笔记本运行一些 Python 代码,以重新训练使用 Model Maker 创建的模型,不过执行此过程无需熟悉 Python。

2. 设置代码环境

同样,您将使用 Glitch.com 托管和修改 Web 应用。如果您尚未完成前提条件 Codelab,可先在此处克隆最终结果,以此为起点。如果您对代码的工作原理有任何疑问,强烈建议您完成上一个 Codelab,了解如何构建这款即将使用的 Web 应用,然后再继续。

在 Glitch 上,点击 remix this 按钮创建分支,并创建一组可修改的新文件。

3.探索先前解决方案中的极端情况

如果您打开刚刚克隆的已完成网站,并尝试输入一些评论,您会发现它在大部分情况下具有预期效果,可以按照预期屏蔽疑似垃圾内容的评论,并允许发布符合规定的回复。

但是,如果您尝试通过一些巧妙的措辞方法突破该模型的限制,最终可能会在某种情况下取得成功。利用试错法,您可以手动创建如下所示的示例。请尝试将这些内容粘贴到现有 Web 应用中,检查控制台,查看评论为垃圾评论的概率:

发布没有问题的合规评论(真负例)

  1. “Wow, I love that video, amazing work.”垃圾内容概率:47.91854%
  2. “Totally loved these demos! Got any more details?”垃圾内容概率:47.15898%
  3. “What website can I go to learn more?”垃圾内容概率:15.32495%

很好,上述所有示例的垃圾内容概率都相当低,在采取措施之前,成功通过了默认的 75% 最低 SPAM_THRESHOLD 概率阈值(已在上一个 Codelab 的 script.js 代码中定义)。

现在,我们尝试编写一些更极端的评论,即使这些评论不是垃圾内容,也可能会被标记为垃圾内容...

标记为垃圾内容的合规评论(假正例)

  1. “Can someone link the website for the mask he is wearing?”垃圾内容概率:98.46466%
  2. “Can I buy this song on Spotify? Someone please let me know!”垃圾内容概率:94.40953%
  3. “Can someone contact me with details on how to download TensorFlow.js?”垃圾内容概率:83.20084%

糟糕!这些合规评论似乎在应该允许发布的情况下被标记为垃圾评论。该如何解决此问题?

一个简单的选择是将 SPAM_THRESHOLD 的置信度提高到超过 98.5%。这样,系统就会允许发布这些被错误分类的评论。记住这一点,接下来让我们继续了解其他可能的结果...

垃圾评论标记为垃圾内容(真正例)

  1. “This is cool but check out the download links on my website that are better!”垃圾内容概率:99.77873%
  2. “I know some people who can get you some medicines just see my pr0file for details”垃圾内容概率:98.46955%
  3. “See my profile to download even more amazing video that are even better! http://example.com”垃圾内容概率:96.26383%

很好,这与我们预期的 75% 原始阈值效果相同,不过,在上一步,您已将 SPAM_THRESHOLD 更改为高于 98.5% 的置信度,这意味着有两个示例可以达到该阈值,所以,或许这个阈值设置得太高了。或许设置为 96% 会更好?但如果是这样,那么上一部分中的一条评论(假正例)会在合规的情况下被标记为垃圾评论,因为评分为 98.46466%。

在这种情况下,最好捕获所有这些真正的垃圾评论,并直接针对上面的失败尝试重新进行训练。将阈值设置为 96% 后,仍将捕获所有真正例,并且可消除上面的两个假正例。还不错,只需要更改一个数字。

我们继续往下...

获准发布的垃圾评论(假负例)

  1. “See my profile to download even more amazing video that are even better!”垃圾内容概率:7.54926%
  2. “Get a discount on our gym training classes see pr0file!”垃圾内容概率:17.49849%
  3. “omg GOOG stock just shot right up! Get before too late!”垃圾内容概率:20.42894%

对于这些评论,您只需进一步更改 SPAM_THRESHOLD 值,无需执行任何其他操作。将垃圾内容的阈值从 96% 减少至 9% 左右会使真正的评论被标记为垃圾内容 - 其中某条评论的评分只有 58%,虽然它是合规的。处理此类评论的唯一方法是使用训练数据中包含的此类极端情况重新训练模型,让它学习调整对垃圾内容的观点。

虽然目前唯一的解决方案是重新训练模型,但您也已了解到,可以如何优化用于将评论判断为垃圾评论的阈值,进一步改善性能。作为人类,75% 的阈值已经相当充分,但对于此模型,您需要将阈值增加到接近 81.5%,才能在样本输入上获得更好的效果。

没有一个值能够神奇地适用于不同模型,这个阈值需要具体模型具体对待,使用真实的数据进行试验,获得良好的运行结果。

在某些情况下,假正例(或假负例)可能会造成严重的后果(例如在医疗行业),因此您可以将阈值调整为非常高的值,并针对未达到阈值的情况增加更多人工审核流程。作为开发者,您可以这样选择,而且需要进行一些实验。

4.重新训练垃圾评论检测模型

在上一部分中,您确定了模型无法处理的许多极端情况,唯一的方法是重新训练模型以应对这些情况。在生产系统中,经过一段时间后,您可能会发现以下情况:模型允许发布的评论被人工手动标记为垃圾评论,或者管理员对模型标记为垃圾内容的评论进行审核,却发现实际上不是垃圾内容,您可以标记此类评论,将其用于进行重新训练。假设您已经针对这些极端情况收集了大量新数据(为达到最佳效果,应该尽可能使用这些新句子的一些变体),我们将继续向您展示如何重新训练模型,将这些极端情况考虑在内。

预建模型回顾

您使用的预建模型是由第三方通过 Model Maker 创建的,该模型使用“平均字词嵌入”模型来执行操作。

由于该模型是使用 Model Maker 构建的,您需要暂时切换到 Python 来重新训练模型,然后将创建的模型导出为 TensorFlow.js 格式,以便在浏览器中使用。幸好 Model Maker 可简化其模型的使用,所以这一操作应该非常简单。我们将指导您完成这个过程,即便您以前没有用过 Python,也不用担心!

Colab

在本 Codelab 中,您无需担心如何设置 Linux 服务器来安装各种 Python 实用程序,只需使用“Colab 笔记本”在网络浏览器中运行代码即可。这些笔记本可以连接到“后端”- 后端只是一个预安装了部分内容的服务器,通过该服务器,您可以在网络浏览器中执行任意代码并查看结果。这对于快速原型设计或在类似这样的教程中使用非常有用。

只需转到 colab.research.google.com,系统会显示欢迎屏幕,如下所示:

b2df89c1f7b38cc9.png

现在,点击弹出式窗口右下角的 New Notebook 按钮,您应该会看到如下所示的空白 Colab:

94a875f67d6e34f6.png

太好了!下一步是将前端 Colab 连接到某个后端服务器,以便执行您要编写的 Python 代码。为此,请点击右上角的 Connect,然后选择 Connect to managed runtime

f4fcd56ae53527bd.png

连接后,您应该会看到 RAM 和磁盘图标出现在对应位置,如下所示:

d979e93ba595d1de.png

做得不错!现在,您可以开始用 Python 进行编码,重新训练 Model Maker 模型。只需执行以下几个步骤即可。

第 1 步

在目前为空的第一个单元格中,复制以下代码。它会使用名为“pip”的 Python 软件包管理器为您安装 TensorFlow Lite Model Maker(与本 Codelab 的大多数读者可能更为熟悉的 JS 生态系统中的 npm 类似):

!pip install -q tflite-model-maker

不过,将代码粘贴到单元格并不会执行代码。接下来,将鼠标悬停在粘贴了上述代码的灰色单元格上,单元格左侧会显示一个小的“播放”图标,如下所示:

be966130d68b5aac.png 点击“播放”按钮可执行刚刚在单元格内输入的代码。

现在,您会看到系统正在安装 Model Maker:

376bc0fbde89a60d.png

按如下所示执行该单元格后,请继续执行下一步。

第 2 步

接下来,添加一个新的代码单元格(如下所示),以便在第一个单元格后粘贴一些代码并单独执行:

7ec405d0d82b2143.png

下一个单元格将执行多次导入操作,笔记本其余部分中的代码将会用到这些导入项。将以下内容复制并粘贴到创建的新单元格中:

import numpy as np
import os

from tflite_model_maker import configs
from tflite_model_maker import ExportFormat
from tflite_model_maker import model_spec
from tflite_model_maker import text_classifier
from tflite_model_maker.text_classifier import DataLoader

import tensorflow as tf
assert tf.__version__.startswith('2')
tf.get_logger().setLevel('ERROR')

这是一些相当标准的代码步骤,即使您不熟悉 Python。您需要导入垃圾内容分类器所需的一些实用程序和 Model Maker 函数。系统还会检查您是否正在运行 TensorFlow 2.x,这是使用 Model Maker 的必要条件。

最后,和之前一样,将鼠标悬停在单元格上方时按“播放”图标以执行单元格然后添加新的代码单元格以执行下一步

第 3 步

接下来,您要从远程服务器将数据下载到您的设备,并将 training_data 变量设置为所下载的本地文件的路径:

data_file = tf.keras.utils.get_file(fname='comment-spam-extras.csv', origin='https://storage.googleapis.com/laurencemoroney-blog.appspot.com/jm_blog_comments_extras.csv', extract=False)

Model Maker 可以从简单的 CSV 文件(如下载的模型)中训练模型。您只需指定哪些列用于存放文本,哪些列用于存放标签即可。您可以在第 5 步中了解详细操作。如果您愿意,也可以自行直接下载 CSV 文件,查看其中所包含的内容。

您可能注意到,该文件的名称为 jm_blog_comments_extras.csv - 此文件只是用于生成第一个评论垃圾模型的原始训练数据,并与您发现的新极端情况数据合并,因此这些数据全部放在一个文件中。除了要学习的新句子之外,您还需要用于训练模型的原始训练数据。

可选:如果您下载此 CSV 文件并查看最后几行,则会看到之前无法正常预测的极端情况示例。这些极端情况刚刚添加到现有训练数据的末尾,预建模型使用这些数据来自我训练。

执行此单元格,在执行完毕后添加新单元格,然后转到第 4 步。

第 4 步

使用 Model Maker 时,您无需从头开始构建模型。通常使用现有模型,并根据需要进行自定义。

Model Maker 提供了几种预学习的模型嵌入供您使用,但最简单也最快速的起步方式是 average_word_vec,您在上一个 Codelab 中使用它来构建了网站。代码如下:

spec = model_spec.get('average_word_vec')
spec.num_words = 2000
spec.seq_len = 20
spec.wordvec_dim = 7

然后将它粘贴到新单元格并运行以下命令。

了解

num_words

参数

这是您希望模型使用的字词数量。您可能会认为越多越好,但根据每个字词的使用频率,通常都有一个最有效点。如果您使用整个语料库中的每个字词,那么模型最终可能会尝试学习并平衡仅使用一次的字词的权重 - 这没什么用。您会发现,在所有文本语料库中,许多字词只使用了一到两次,通常不值得用在您的模型中,因为它们对整体情绪的影响微乎其微。因此,您可以使用 num_words 参数,根据所需的字词数微调模型。此处的数字越小,模型尺寸就越小,处理速度就越快,但由于识别的字词较少,准确率会较低。此处的数字越大,模型就越大,处理速度可能就越慢。找到最有效点是关键所在,作为机器学习工程师,您需要确定什么最适合您的用例。

了解

wordvec_dim

参数

wordvec_dim 参数是要为每个字词矢量使用的维度数量。这些维度本质上是不同的特征(由机器学习算法在训练时创建),任何给定的字词都可以通过这些特征进行衡量,程序也将使用这些特征尝试以某种有意义的方式关联相似的字词。

例如,如果您有一个关于字词与“医学”之间关系的维度,那么像“药片”这样的词在这个维度上得分可能会很高,并且与其他得分较高的词(如“x 射线”)相关联,但是“猫”在这个维度上的得分会很低。当将“医学维度”与其他可能决定使用的重要维度结合在一起时,结果可能会证明该纬度对于确定垃圾内容非常有用。

对于在"医学维度"上得分很高的字词,可能会发现将字词与人体联系起来的第二个维度可能很有用。在这种情况下,“腿”、“手”和“颈”等字词的得分可能会比较高,并且在医学维度上得分也比较高。

模型可以根据这些维度检测更可能与垃圾内容相关的字词。或许垃圾邮件更有可能包含同时具有医学和人体部位含义的字词。

根据研究得出的经验法则是,字词数量的四次方根适用于此参数。所以,如果我使用 2000 个字词,从 7 个维度着手是很好的起点。如果您更改了所用的字词数量,也可以相应地更改此数字。

了解

seq_len

参数

当涉及到输入值时,模型通常非常严格。对于语言模型而言,这意味着语言模型可以对特定静态长度的句子进行分类。这由 seq_len 参数确定,该参数代表“序列长度”。将字词转换为数字(或词元)时,句子就会变为这些词元的序列。因此,您的模型将得到训练(在本示例中),以分类和识别包含 20 个词元的句子。如果句子的长度超过此数字,则会被截断。如果比这个数字短,则会加以填充 - 就像本系列第一个 Codelab 中所叙述的一样。

第 5 步 - 加载训练数据

您之前下载了 CSV 文件。现在,可以使用数据加载程序将其转换为模型可以识别的训练数据了。

data = DataLoader.from_csv(
      filename=data_file,
      text_column='commenttext',
      label_column='spam',
      model_spec=spec,
      delimiter=',',
      shuffle=True,
      is_training=True)

train_data, test_data = data.split(0.9)

如果您在编辑器中打开 CSV 文件,会看到每行只有两个值,而且这些值在文件的第一行中使用文本进行了描述。通常,每个条目都被视为一个“列”。您会看到,第一列的描述符为 commenttext,而且每行的第一个条目都是评论的文本。

同样,第二列的描述符为 spam,而且您会看到每一行的第二个条目为 TRUEFALSE,表示该文本是否被视为垃圾评论。其他属性用于设置您在第 4 步中创建的模型规范以及分隔符。在本例中,此分隔符为英文逗号,因为文件是以英文逗号分隔的。此外,您还可以设置 Shuffle 参数以随机重新排列训练数据,以便将可能相似或共同收集的内容随机分布到整个数据集中。

然后,您将使用 data.split() 将数据拆分为训练和测试数据。0.9 表示数据集中有 90% 的数据将用于训练,其余数据将用于测试。

第 6 步 - 构建模型

添加另一个单元格,我们将在其中添加用于构建模型的代码:

model = text_classifier.create(train_data, model_spec=spec, epochs=50)

该单元格会使用 Model Maker 创建一个文本分类器模型,您需要指定要使用的训练数据(在第 4 步中定义)、模型规范(也在第 4 步中设置)以及周期数(在本例中为 50)。

机器学习的基本原则是模式匹配形式。首先,它会加载预训练的字词权重,并尝试将它们组合在一起,同时预测哪些字词组合在一起表示垃圾内容,哪些不是。第一次的权重可能接近 50:50,因为模型刚开始使用,如下所示:

d6c8116f8e7e781b.png

接下来,它会衡量此次结果,更改模型的权重以调整其预测,然后将再次尝试。这就是一个周期。因此,指定 Epoch=50 后,它将经历 50 次“循环”,如下所示:

fc7bf6a948b7aa26.png

在进入第 50 个周期时,模型报告的准确率会大幅度提高。在本例中显示的准确率高达 99.1%!

第 7 步 - 导出模型

训练完成后,您可以导出模型。TensorFlow 以自己的格式训练模型,需要将之转换为 TensorFlow.js 格式,才能在网页上使用。只需将以下内容粘贴到新单元格中并运行即可:

model.export(export_dir="/js_export/", export_format=[ExportFormat.TFJS, ExportFormat.LABEL, ExportFormat.VOCAB])
!zip -r /js_export/ModelFiles.zip /js_export/

运行此代码后,如果您点击 Colab 左侧的小文件夹图标,则可以导航到上面的导出目标文件夹中(在根目录中 - 可能需要浏览到上一级文件夹),并找到 ModelFiles.zip 中包含的已导出文件压缩包。

请将此 ZIP 文件下载到计算机,因为您将在第一个 Codelab 中使用这些文件:

a9d8595a3e2564dc.png

太好了!Python 部分到此结束,您现在可以返回到您熟悉且喜爱的 JavaScript 部分了。哇噻!

5. 应用新的机器学习模型

现在,您差不多可以加载模型了。在此之前,您必须上传之前在本 Codelab 中下载的新模型文件,以便对它进行托管并在代码中使用。

首先,如果您还没有解压缩的话,请解压缩刚刚从 Model Maker Colab 笔记本下载的模型对应的文件。您应该会看到,各个文件夹中包含如下所示的文件:

5634d536ef8be9ca.png

目前您构建了哪些内容?

  • model.json - 这是构成经过训练的 TensorFlow.js 模型的文件之一。您将在 JS 代码中引用此特定文件。
  • group1-shard1of1.bin - 这是一个二进制文件,包含已导出的 TensorFlow.js 模型的大部分已保存数据,该文件需要托管在服务器上的某个位置以便下载,与上面的 model.json 位于同一目录。
  • vocab - 这个奇怪的文件没有扩展名,由 Model Maker 提供,它向我们展示了如何编码句子中的字词,从而让模型了解如何使用这些字词。下一部分将对此进行详细介绍。
  • labels.txt - 它只包含模型将预测的类别名称结果。在此模型中,如果您在文本编辑器中打开这个文件,那么其中只会列出“false”和“true”,分别表示“不是垃圾内容”或“垃圾内容”,作为预测输出。

托管 TensorFlow.js 模型文件

首先,将生成的 model.json*.bin 文件放在 Web 服务器上,以便您可以通过您的网页访问它们。

删除现有模型文件

在基于本系列第一个 Codelab 的最终结果构建模型时,必须先删除上传的现有模型文件。如果您使用的是 Glitch.com,只需查看左侧文件面板的 model.jsongroup1-shard1of1.bin,然后点击每个文件的三点状菜单下拉菜单并选择 delete,如下所示:

7412b0b795d3b84f.png

将新文件上传到 Glitch

太好了!立即上传新视频:

  1. 打开 Glitch 项目的左侧面板中的 assets 文件夹,然后删除上传的所有同名旧资源。
  2. 点击 upload an asset,然后选择 group1-shard1of1.bin,即可上传到此文件夹。上传后,该界面现在应如下所示:

25a2251c7f165184.png

  1. 太好了!现在,对 model.json 文件执行相同的操作,然后这两个文件应该位于 assets 文件夹中,如下所示:

51a6dbd5d3097ffc.png

  1. 如果您点击刚刚上传的 group1-shard1of1.bin 文件,便可以将该网址复制到对应位置。立即复制此路径,如下所示:

92ded8d46442c404.png

  1. 现在,依次点击屏幕左下角的 Tools > Terminal。等待终端窗口进行加载。
  2. 加载完成后,输入以下内容,然后按 Enter 键将目录更改为 www 文件夹:

终端

cd www
  1. 接下来,使用 wget 下载刚刚上传的两个文件,方法是将下面的网址替换为您为 Glitch 上的 assets 文件夹中的文件生成的网址(请在 assets 文件夹中查看每个文件的自定义网址)。

请注意,两个网址之间有空格,并且您需要使用的网址与所示网址不同,但它们看起来类似:

终端

wget https://cdn.glitch.com/1cb82939-a5dd-42a2-9db9-0c42cab7e407%2Fmodel.json?v=1616111344958 https://cdn.glitch.com/1cb82939-a5dd-42a2-9db9-0c42cab7e407%2Fgroup1-shard1of1.bin?v=1616017964562

太棒了!现在,您已复制上传到 www 文件夹的文件。

但是,现在下载它们时,文件名称会非常奇怪。如果您在终端中输入 ls 并按 Enter 键,会看到如下内容:

9cc90f1d053f517f.png

  1. 请使用 mv 命令重命名这些文件。在控制台中输入以下内容,然后在输入每行后按 Enter 键:

终端

mv *group1-shard1of1.bin* group1-shard1of1.bin
mv *model.json* model.json
  1. 最后,在终端中输入 refresh 并按 Enter 键来刷新 Glitch 项目:

终端

refresh

刷新后,界面的 www 文件夹中现在应该会显示 model.jsongroup1-shard1of1.bin

50dd98c0a8f3e629.png

太好了!最后一步是更新 dictionary.js 文件。

  1. 使用文本编辑器或使用此工具手动将新下载的词汇表文件转换为正确的 JS 格式,然后将生成的输出内容以 dictionary.js 格式保存在 www 文件夹中。如果您已有 dictionary.js 文件,只需将其复制粘贴到该文件并保存文件即可。

棒极了!您已成功更新所有已更改的文件,如果您现在尝试使用网站,会注意到重新训练的模型如何应对所发现和学习的极端情况,如下所示:

3ece5dbd0a673987.gif

如您所见,前 6 个被正确分类为非垃圾内容,而第 2 批的 6 个全部被识别为垃圾内容。太棒了!

我们再尝试做出一些更改,看看它的泛化效果是否良好。最初有一个失败的句子,比如:

“omg GOOG stock just shot right up!Get before too late!”

现在,这句话被正确分类为垃圾内容,但如果您将这句话更改为下面这样,会怎么样呢:

So XYZ stock just increased in value!Buy some right before it's too late!"

此时,您预测的垃圾内容概率为 98%,即使您对股票代号和措辞进行了细微更改,依然如此。

当然,如果您确实想尝试突破这种新模型的限制,那么一定能够做到,只需收集更多训练数据,从而尽可能为很可能在网上遇到的常见情况捕获更多唯一变体。在未来的 Codelab 中,我们将向您展示如何使用标记的实时数据持续改进该模型。

6.恭喜!

恭喜!您已成功地重新训练一个现有的机器学习模型并进行更新,使其适应您发现的极端情况,并通过 TensorFlow.js 将这些更改部署到浏览器,以用于实际应用。

回顾

在本 Codelab 中,您学习了以下内容:

  1. 发现了使用预建垃圾评论模型时无法处理的极端情况
  2. 重新训练了 Model Maker 模型,并将您发现的极端情况考虑在内
  3. 将经过训练的新模型导出为 TensorFlow.js 格式
  4. 更新了您的 Web 应用,以使用新文件

接下来做什么?

所以,这次更新非常有效,但和所有 Web 应用一样,随时间推移会发生很多变化。如果应用可以持续改进,性能会更加出色,而不必每次都手动完成。您能不能想到,当有 100 条新评论被标记为错误分类后,如何自动执行这些步骤来重新训练模型?试着采用常规的网络工程思维,您也许会想出如何创建流水线来自动执行此操作。如果做不到这一点,也不用担心,您可以学习本系列的下一个 Codelab,了解如何操作。

与我们分享您的成果

您也可以轻松将今天的成果扩展到其他创意用例中,建议您跳出思维定式,做到持续改进。

请记得使用 #MadeWithTFJS# 标签在社交媒体上标记我们,这样就有机会在 TensorFlow 博客甚至未来的活动中展示您的项目。我们很期待看到您的成果。

更多可深入学习的 TensorFlow.js Codelab

参考网站