JavaScript 深度学习(五)(1)

简介: JavaScript 深度学习(五)

第十四章:总结、结论和展望

本章包括

  • 回顾人工智能和深度学习的高层次概念和想法
  • 我们在本书中访问的不同类型的深度学习算法的快速概述,它们何时有用,以及如何在 TensorFlow.js 中实现它们
  • 来自 TensorFlow.js 生态系统的预训练模型
  • 深度学习当前存在的局限性;以及我们将在未来几年看到的深度学习趋势的教育预测
  • 如何进一步提升你的深度学习知识并跟上这个快速发展的领域的指导

这是本书的最后一章。之前的章节是对当前深度学习领域的总体概况,通过 TensorFlow.js 和你自己的努力实现。通过这段旅程,你可能已经学到了很多新的概念和技能。现在是时候再次退后一步,重新审视全局,并对你学到的一些最重要的概念进行复习。这最后一章将总结和审查核心概念,同时将你的视野扩展到迄今为止学到的相对基本的概念之外。我们希望确保你意识到这一点,并且准备好自己继续旅程的下一步。

我们将从鸟瞰视角开始,总结你应该从这本书中学到的东西。这应该让你记起你学到的一些概念。接下来,我们将概述深度学习的一些关键局限性。要正确使用工具,你不仅应该知道它 做什么,还应该知道它 不能 做什么。本章以资源列表和进一步了解深度学习和 JavaScript 生态系统中人工智能知识和技能的策略结束,并保持与新发展的步伐同步。

13.1. 复习重点概念

这一部分简要总结了这本书的关键要点。我们将从人工智能领域的整体格局开始,以为什么将深度学习和 JavaScript 结合起来会带来独特而令人兴奋的机遇而结束。

13.1.1. 人工智能的各种方法

首先,深度学习与人工智能甚至与机器学习并不是同义词。 人工智能 是一个历史悠久的广泛领域。它通常可以定义为“所有试图自动化认知过程”的尝试——换句话说,思维的自动化。这可以从非常基本的任务,如 Excel 电子表格,到非常高级的努力,如一个可以行走和说话的类人机器人。

机器学习 是人工智能的许多子领域之一。它旨在通过暴露给训练数据自动开发程序(称为 模型)。这个将数据转化为程序(模型)的过程被称为 学习。尽管机器学习已经存在了很长一段时间(至少有几十年了),但它直到 1990 年代才开始在实际应用中蓬勃发展。

深度学习 是机器学习的众多形式之一。在深度学习中,模型由许多步骤的表示转换组成,依次应用(因此有形容词“深度”)。这些操作被结构化为称为 的模块。深度学习模型通常是许多层的堆栈或更一般地说是许多层的图。这些层由 权重 参数化,数字值有助于将层的输入转换为其输出,并在训练过程中更新。模型在训练过程中学到的“知识”体现在其权重中。训练过程主要是为这些权重找到一个良好的值。

尽管深度学习只是机器学习的众多方法之一,但与其他方法相比,它已被证明是一个突破性的成功。让我们快速回顾一下深度学习成功背后的原因。

13.1.2. 使深度学习在机器学习子领域中脱颖而出的原因

仅仅在几年的时间里,深度学习在多个历史上被认为对计算机极其困难的任务上取得了巨大突破,特别是在机器感知领域——即从图像、音频、视频和类似感知数据中提取有用信息的能力,具有足够高的准确性。如果有足够的训练数据(特别是标记的训练数据),现在可以从感知数据中提取几乎任何人类可以提取的东西,有时甚至准确度超过人类。因此,有时说深度学习在很大程度上“解决了感知”问题,尽管这只适用于对感知的一个相当狭义的定义(参见 第 13.2.5 节 以了解深度学习的局限性)。

由于其空前的技术成功,深度学习独自引发了第三次,迄今为止最大的 AI 夏季,也被称为 深度学习革命,这是人工智能领域的一个充满兴趣、投资和炒作的时期。这一时期是否会在不久的将来结束,以及之后会发生什么,是人们猜测和讨论的话题。但有一点是确定的:与以往的 AI 夏季形成鲜明对比,深度学习为许多技术公司提供了巨大价值,实现了人类级别的图像分类、目标检测、语音识别、智能助手、自然语言处理、机器翻译、推荐系统、自动驾驶汽车等。炒作可能会减退(理所当然),但深度学习的持续技术影响和经济价值将会保持。从这个意义上说,深度学习可能类似于互联网:可能在几年内被过度炒作,导致不合理的期望和过度投资,但从长远来看,它将成为一个影响技术许多领域并改变我们生活的重大革命。

我们对深度学习特别乐观,因为即使在未来十年内我们在其中不再取得进一步的学术进展,将现有的深度学习技术应用于每一个适用的实际问题仍将改变许多行业的游戏规则(在线广告、金融、工业自动化和残疾人辅助技术,只是列举了一部分)。深度学习无疑是一场革命,目前的进展速度之快令人难以置信,这要归功于资源和人员的指数级投资。从我们的角度来看,未来看起来很光明,尽管短期内的预期可能有些过于乐观;充分发挥深度学习的潜力将需要超过十年的时间。

13.1.3. 怎样从高层次上思考深度学习

深度学习最令人惊讶的一个方面是它的简单性,考虑到它的工作效果以及之前的更复杂的机器学习技术的效果并不如人意。十年前,没有人预料到我们能够仅通过使用梯度下降训练的参数模型在机器感知问题上取得如此惊人的结果。现在事实证明,你只需要足够大的通过梯度下降训练的参数模型以及足够多的带标签示例。正如理查德·费曼曾经关于他对宇宙的理解所说:“这并不复杂,只是有很多。”^([1])

¹

理查德·费曼,采访,“另一种视角下的世界”,约克郡电视台,1972 年。

在深度学习中,一切都被表示为一系列数字——换句话说,是一个向量。一个向量可以被看作是几何空间中的一个。模型输入(表格数据、图像、文本等)首先被向量化,或者转换为输入向量空间中的一组点。同样地,目标(标签)也被向量化,并转换为其相应的目标向量空间中的一组点。然后,深度神经网络中的每一层对通过它的数据执行一个简单的几何变换。在一起,神经网络中的层链形成了一个由一系列简单的几何变换组成的复杂几何变换。这个复杂的变换试图将输入向量空间中的点映射到目标向量空间中的点。这个变换由层的权重参数化,这些权重根据当前变换的好坏进行迭代更新。这个几何变换的一个关键特征是它是可微的:这就是梯度下降变得可能的原因。

13.1.4. 深度学习的关键技术

正在进行的深度学习革命并非一夜之间开始。相反,和其他任何革命一样,它是一系列因素的积累——一开始缓慢,然后一旦到达关键点就突然加速。就深度学习而言,我们可以指出以下关键因素:

  • 渐进式的算法创新,首先涉及两个十年,然后随着深度学习在 2012 年之后投入更多研究力量而加速发展。

²

起始于 Rumelhart、Hinton 和 Williams 的反向传播算法,LeCun 和 Bengio 的卷积层,以及 Graves 和 Schmidthuber 的循环网络。

³

例如,改进的权重初始化方法,新的激活函数,dropout,批量归一化,残差连接。

  • 大量的标记数据可用,覆盖许多数据模式,包括知觉(图像、音频和视频)、数字和文本,这使大型模型可以在足够数量的数据上进行训练。这是消费互联网兴起的副产品,由流行的移动设备推动,以及存储介质中的摩尔定律。
  • 快速、高度并行化的计算硬件以低成本提供,尤其是 NVIDIA 生产的 GPU——首先是为并行计算重新用途的游戏 GPU,然后是从头设计用于深度学习的芯片。
  • 复杂的开源软件堆栈使许多人类开发者和学习者可以使用这种计算能力,同时隐藏了庞大的复杂性:CUDA 语言、WebGL 着色器语言以及框架,如 TensorFlow.js、TensorFlow 和 Keras,其执行自动差分并提供易于使用的高级搭建块,如层、损失函数和优化器。深度学习正在从专家领域(研究人员、AI 研究生和具有学术背景的工程师)转变为每位程序员的工具。TensorFlow.js 在这方面是一个典范性的框架。它将两个丰富活跃的生态系统结合在一起:JavaScript 跨平台生态系统和快速发展的深度学习生态系统。

深度学习革命的广泛和深远影响之一是它与其他不同于它的技术栈(如 C++ 和 Python 生态系统和数字计算领域)的融合。它与 JavaScript 生态系统的跨界融合是其中的一个典型例子。在接下来的部分,我们将回顾为什么将深度学习引入 JavaScript 世界将开启令人兴奋的新机遇和可能性的关键原因。

13.1.5 用 JavaScript 实现深度学习的应用与机遇

训练深度学习模型的主要目的是使其可供用户使用。对于许多类型的输入模态,例如来自网络摄像头的图像、来自麦克风的声音以及用户输入的文本和手势输入,数据是由客户端生成并直接可用的。JavaScript 或许是最成熟和普及的客户端编程语言和生态系统。用 JavaScript 编写的相同代码可以部署为网页和 UI,在各种设备和平台上运行。Web 浏览器的 WebGL API 允许在各种 GPU 上进行跨平台并行计算,TensorFlow.js 利用了这一点。这些因素使 JavaScript 成为部署深度学习模型的一种吸引人的选择。TensorFlow.js 提供了一个转换工具,允许您将使用流行的 Python 框架(如 TensorFlow 和 Keras)训练的模型转换为适合 Web 的格式,并将其部署到网页上进行推理和迁移学习。

除了部署的便利性之外,使用 JavaScript 提供服务和微调深度学习模型还有许多其他优势:

  • 与服务器端推理相比,客户端推理放弃了双向数据传输的延迟,有利于可用性,并带来更流畅的用户体验。
  • 通过使用设备 GPU 加速在边缘执行计算,客户端深度学习消除了管理服务器端 GPU 资源的需要,显着降低了技术堆栈的复杂性和维护成本。
  • 通过保持数据和推理结果在客户端,用户的数据隐私得到了保护。这对于医疗保健和时尚等领域至关重要。
  • 浏览器和其他基于 JavaScript 的 UI 环境的视觉和交互性为神经网络的可视化、辅助理解和教学提供了独特的机会。
  • TensorFlow.js 不仅支持推理,还支持训练。这为客户端迁移学习和微调打开了大门,从而实现了机器学习模型的更好个性化。
  • 在 Web 浏览器中,JavaScript 提供了一个独立于平台的 API,用于访问设备传感器,如网络摄像头和麦克风,这加速了使用这些传感器输入的跨平台应用程序的开发。

除了其客户端的卓越性能,JavaScript 还将其能力扩展到服务器端。特别是,Node.js 是 JavaScript 中高度流行的用于服务器端应用的框架。使用 Node.js 版本的 TensorFlow.js(tfjs-node),您可以在网页浏览器之外的环境中训练和提供深度学习模型,因此不受资源限制。这利用了 Node.js 的庞大生态系统,并简化了社区成员的技术堆栈。所有这些都可以通过使用与您为客户端编写的基本相同的 TensorFlow.js 代码来实现,这使您更接近“一次编写,到处运行”的愿景,正如本书中的几个示例所示。

13.2. TensorFlow.js 中深度学习工作流程和算法的快速概述

通过历史概述,让我们现在来看看 TensorFlow.js 的技术方面。在本节中,我们将回顾当你面对一个机器学习问题时应该遵循的一般工作流程,并强调一些最重要的考虑因素和常见陷阱。然后,我们将过一下我们在书中涵盖的各种神经网络构建块(层)。此外,我们将调查 TensorFlow.js 生态系统中的预训练模型,这些模型可以加速您的开发周期。为了结束本节,我们将介绍您可以通过使用这些构建块解决的一系列机器学习问题,激励您想象使用 TensorFlow.js 编写的深度神经网络如何帮助您解决自己的机器学习问题。

13.2.1. 监督深度学习的通用工作流程

深度学习是一个强大的工具。但或许有些令人惊讶的是,机器学习工作流程中最困难和耗时的部分通常是设计和训练这些模型之前的一切(以及对于部署到生产环境的模型来说,还有之后的一切)。这些困难的步骤包括充分了解问题域,以便能够确定需要什么样的数据,以及可以以合理的准确性和泛化能力进行什么样的预测,机器学习模型如何适用于解决实际问题的整体解决方案中,以及如何度量模型在完成其工作时成功的程度。尽管这些是任何成功应用机器学习的先决条件,但它们不是像 TensorFlow.js 这样的软件库可以自动化的内容。作为提醒,以下是典型监督学习工作流程的快速摘要:

  1. 确定机器学习是否是正确的方法。首先,考虑一下机器学习是否是解决您的问题的正确方法,只有在答案是肯定的情况下才继续以下步骤。在某些情况下,非机器学习方法同样有效,甚至可能更好,成本更低。
  2. 定义机器学习问题。确定可用的数据类型以及您试图使用数据预测的内容。
  3. 检查您的数据是否足够。确定您已经拥有的数据量是否足以进行模型训练。您可能需要收集更多数据或雇用人员手动标记一个未标记的数据集。
  4. 确定一种可靠地衡量训练模型成功的方法。对于简单任务,这可能只是预测准确率,但在许多情况下,它将需要更复杂、特定于领域的度量标准。
  5. 准备评估过程。设计用于评估模型的验证过程。特别是,您应该将数据分成三个同质但不重叠的集合:一个训练集、一个验证集和一个测试集。验证集和测试集的标签不应泄漏到训练数据中。例如,对于时间预测,验证和测试数据应来自训练数据之后的时间间隔。您的数据预处理代码应该经过测试,以防止错误(第 12.1 节)。
  6. 将数据向量化。将您的数据转换为张量,或者n维数组——TensorFlow.js 和 TensorFlow 等框架中机器学习模型的通用语言。通常需要对张量化的数据进行预处理,以使其更适合您的模型(例如,通过归一化)。
  7. 超越常识基线。开发一个能够超越非机器学习基线的模型(例如,在回归问题中预测人口平均值或在时间序列预测问题中预测最后一个数据点),从而证明机器学习确实可以为您的解决方案增加价值。这并不总是可能的(见步骤 1)。
  8. 开发具有足够容量的模型。通过调整超参数和添加正则化逐渐完善模型架构。仅基于验证集的预测准确率进行更改,而不是基于训练集或测试集。请记住,您应该使您的模型过度拟合问题(在训练集上达到比验证集更好的预测准确率),从而确定一个比您需要的容量更大的模型容量。只有在那之后,您才应该开始使用正则化和其他方法来减少过拟合。
  9. 调整超参数。在调整超参数时要注意验证集的过拟合。因为超参数是基于验证集上的性能确定的,所以它们的值会过度专门化于验证集,因此可能不会很好地推广到其他数据。测试集的目的是在调整超参数后获得模型准确性的无偏估计。因此,在调整超参数时不应使用测试集。
  10. 验证和评估训练好的模型。正如我们在第 12.1 节中讨论的,用最新的评估数据集测试您的模型,并决定预测精度是否达到为实际用户服务的预定标准。此外,对模型在不同数据切片(子集)上的质量进行更深入的分析,旨在检测任何不公平行为(例如在不同数据切片上的精度差异)或不希望的偏差。^([4]) 只有当模型通过这些评估标准时,才进行最终步骤。

机器学习中的公平性是一个新兴的研究领域;更多讨论请参见以下链接mng.bz/eD4Q

  1. 优化和部署模型。对模型进行优化,以缩小其尺寸并提高其推理速度。然后将模型部署到服务环境中,如网页、移动应用程序或 HTTP 服务端点(第 12.3 节)。

这个教程是关于监督学习的,它在许多实际问题中都会遇到。本书涵盖的其他类型的机器学习工作流包括(监督)迁移学习、RL(强化学习)和生成式深度学习。监督迁移学习(第五章)与非迁移监督学习的工作流相同,唯一的区别是模型设计和训练步骤是基于预训练模型构建的,并且可能需要比从头开始训练模型更少的训练数据。生成式深度学习的目标与监督学习有所不同——即尽可能创建看起来像真实的假例。实际上,有一些技术将生成模型的训练转化为监督学习,就像我们在第九章中看到的 VAE 和 GAN 示例一样。另一方面,RL 包含一个根本不同的问题形式化,并因此具有截然不同的工作流程——其中主要参与者是环境、代理、行动、奖励结构以及用于解决问题的算法或模型类型。第十一章提供了 RL 中基本概念和算法的快速概述。

13.2.2. 回顾 TensorFlow.js 中的模型和层类型:快速参考

本书涵盖的所有众多神经网络可以分为三类系列:密集连接网络(也称为 MLPs 或多层感知器)、卷积网络和循环网络。这三种基本系列的网络是每个深度学习实践者都应该熟悉的。每种类型的网络适用于特定类型的输入:网络架构(MLP、卷积或循环)对输入数据的结构进行假设—通过反向传播和超参数调整来搜索好模型的假设空间。给定问题是否适用于给定架构完全取决于数据中的结构与网络架构的假设匹配得有多好。

这些不同类型的网络可以像积木一样轻松地组合成更复杂和多模态的网络。从某种意义上说,深度学习层是可微分信息处理的积木。我们快速概述输入数据的模态与适当网络架构之间的映射:

  • 向量数据(没有时间序列或串行顺序)—MLPs(密集 layers
  • 图像数据(黑白、灰度或彩色)—2D 卷积网络
  • 音频数据作为频谱图—2D 卷积网络或 RNNs
  • 文本数据—1D 卷积网络或 RNNs
  • 时间序列数据—1D 卷积网络或 RNNs
  • 体积数据(例如 3D 医学图像)—3D 卷积网络
  • 视频数据(图像序列)—要么是 3D 卷积网络(如果你需要捕捉运动效果),要么是一个逐帧 2D 卷积网络用于特征提取,随后是一个 RNN 或 1D 卷积网络来处理生成的特征序列的组合

现在让我们深入了解每个主要架构系列,它们擅长的任务以及如何通过 TensorFlow.js 使用它们。

密集连接网络和多层感知器

密集连接网络多层感知机这两个术语在很大程度上可以互换使用,但要注意密集连接网络可以只包含一个层,而多层感知机必须至少包含一个隐藏层和一个输出层。为了简洁起见,我们将使用MLP这个术语来指代主要由密集层构建的所有模型。此类网络专门用于无序向量数据(例如,在钓鱼网站检测问题和房价预测问题中的数值特征)。每个密集层试图对输入特征的所有可能的对和该层的输出激活之间的关系进行建模。这通过密集层的核与输入向量之间的矩阵乘法(然后加上偏差向量和激活函数)来实现。每个输出激活受到每个输入特征的影响是这些层和建立在它们上面的网络被称为密集连接(或被一些作者称为完全连接)的原因。这与其他类型的架构(卷积网络和循环神经网络)形成对比,在这些架构中,一个输出元素仅依赖于输入数据中的一部分元素。

MLP 最常用于分类数据(例如,输入特征是属性列表,比如在钓鱼网站检测问题中)。它们也经常被用作大多数分类和回归神经网络的最终输出阶段,这些网络可以包含卷积或循环层作为特征提取器,将特征输入馈送到这样的 MLP 中。例如,我们在第四章和第五章中介绍的二维卷积网络都以一个或两个密集层结尾,我们在第九章中介绍的循环网络也是如此。

让我们简要回顾一下在监督学习中如何选择 MLP 的输出层激活函数以适应不同类型的任务。要进行二元分类,你的 MLP 的最后一个密集层应该正好有一个单元,并使用 sigmoid 激活函数。在训练这样一个二元分类器 MLP 时,应该使用binaryCrossentropy作为损失函数。你的训练数据中的例子应该有二元标签(0 或 1 的标签)。具体来说,TensorFlow.js 的代码如下:

import * as tf from '@tensorflow/tfjs';
const model = tf.sequential();
model.add(tf.layers.dense({units: 32, activation: 'relu', inputShape:
     [numInputFeatures]}));
model.add(tf.layers.dense({units: 32, activation: 'relu'}));
model.add(tf.layers.dense({units: 1: activation: 'sigmoid'}));
model.compile({loss: 'binaryCrossentropy', optimizer: 'adam'});

要进行单标签多类别分类(其中每个例子在多个候选类别中只有一个类别),请在你的层堆叠的末尾加上一个包含 softmax 激活函数的密集层,单位数量等于类别的数量。如果你的目标是独热编码,请使用categoricalCrossentropy作为损失函数;如果它们是整数索引,请使用sparseCategoricalCrossentropy。例如:

const model = tf.sequential();
model.add(tf.layers.dense({units: 32, activation: 'relu', inputShape:
     [numInputFeatures]});
model.add(tf.layers.dense({units: 32, activation: 'relu'});
model.add(tf.layers.dense({units: numClasses: activation: 'softmax'});
model.compile({loss: 'categoricalCrossentropy', optimizer: 'adam'});

为了执行多标签多类别分类(每个示例可能具有多个正确类别),将你的层堆栈结束为一个包含 sigmoid 激活和单位数量等于所有候选类别数量的密集层。使用binaryCrossentropy作为损失函数。你的目标应该是 k-hot 编码:

const model = tf.sequential();
model.add(tf.layers.dense({units: 32, activation: 'relu', inputShape:
     [numInputFeatures]}));
model.add(tf.layers.dense({units: 32, activation: 'relu'}));
model.add(tf.layers.dense({units: numClasses: activation: 'sigmoid'}));
model.compile({loss: 'binaryCrossentropy', optimizer: 'adam'});

为了对连续值向量执行回归,将你的层堆栈结束为一个具有单位数量等于你尝试预测的值数量(通常只有一个数字,比如房价或温度值)的密集层,并使用默认的线性激活函数。多个损失函数可用于回归。最常用的是meanSquaredErrormeanAbsoluteError

const model = tf.sequential();
model.add(tf.layers.dense({units: 32, activation: 'relu', inputShape:
     [numInputFeatures]}));
model.add(tf.layers.dense({units: 32, activation: 'relu'}));
model.add(tf.layers.dense({units: numClasses}));
model.compile({loss: 'meanSquaredError', optimizer: 'adam'});
卷积网络

卷积层通过将相同的几何变换应用于输入张量中的不同空间位置(补丁)来查看局部空间模式。这导致了是平移不变的表示,使卷积层高度数据有效和模块化。这个想法适用于任何维度的空间:1D(序列),2D(图像或类似于非图像数量的表示,如声音频谱图),3D(体积)等等。你可以使用tf.layers.conv1d层来处理序列,使用 conv2d 层来处理图像,使用 conv3d 层来处理体积。

卷积网络由一系列卷积和池化层组成。池化层允许你对数据进行空间降采样,这对于保持特征图的合理大小是必需的,因为特征数量增加,同时也允许后续层“看到”卷积网络输入图像的更大空间范围。卷积网络通常以展平层或全局池化层结束,将空间特征图转换为向量,然后可以通过一系列密集层(MLP)处理以实现分类或回归输出。

很可能常规卷积很快就会被一个等价但更快更高效的替代品所取代(或完全取代):深度可分离卷积(tf.layers.separableConv2d层)。当你从头开始构建一个网络时,强烈推荐使用深度可分离卷积。可分离卷积层可以用作tf.layers .conv2d的即插即用替代品,结果是一个更小更快的网络,在其任务上表现同样好或更好。以下是一个典型的图像分类网络(单标签多类别分类,在本例中)。其拓扑结构包含重复的卷积-池化层组的模式:

const model = tf.sequential();
model.add(tf.layers.separableConv2d({
    filters: 32, kernelSize: 3, activation: 'relu',
    inputShape: [height, width, channels]}));
model.add(tf.layers.separableConv2d({
         filters: 64, kernelSize: 3, activation: 'relu'}));
model.add(tf.layers.maxPooling2d({poolSize: 2}));
model.add(tf.layers.separableConv2d({
         filters: 64, kernelSize: 3, activation: 'relu'}));
model.add(tf.layers.separableConv2d({
         filters: 128, kernelSize: 3, activation: 'relu'}));
model.add(tf.layers.maxPooling2d({poolSize: 2}));
model.add(tf.layers.separableConv2d({
    filters: 64, kernelSize: 3, activation: 'relu'}));
model.add(tf.layers.separableConv2d({
    filters: 128, kernelSize: 3, activation: 'relu'}));
model.add(tf.layers.globalAveragePooling2d());
model.add(tf.layers.dense({units: 32, activation: 'relu'}));
model.add(tf.layers.dense({units: numClasses, activation: 'softmax'}));
model.compile({loss: 'categoricalCrossentropy', optimizer: 'adam'});
循环网络

RNN 通过一次处理一个时间戳的输入序列并始终保持状态来工作。状态通常是一个向量或一组向量(几何空间中的一个点)。在不是时间上不变的序列(例如,时间序列数据,其中最近的过去比遥远的过去更重要)的情况下,应优先使用 RNN,而不是 1D 卷积网络。

TensorFlow.js 提供了三种 RNN 层类型:simpleRNN、GRU 和 LSTM。对于大多数实际目的,您应该使用 GRU 或 LSTM。LSTM 是这两者中更强大的,但也更消耗计算资源。您可以将 GRU 视为 LSTM 的简化和更便宜的替代品。

为了将多个 RNN 层堆叠在一起,除了最后一层之外的每一层都需要配置为返回其输出的完整序列(每个输入时间步对应一个输出时间步)。如果不需要堆叠 RNN 层,通常 RNN 层只需返回最后一个输出,其中包含有关整个序列的信息。

以下是使用单个 RNN 层与密集层一起执行向量序列的二进制分类的示例:

const model = tf.sequential();
model.add(tf.layers.lstm({
  units: 32,
  inputShape: [numTimesteps, numFeatures]
}));
model.add(tf.layers.dense({units: 1, activation: 'sigmoid'}));
model.compile({loss: 'binaryCrossentropy', optimizer: 'rmsprop'});

接下来是一个带有 RNN 层堆叠的模型,用于向量序列的单标签多类别分类:

const model = tf.sequential();
model.add(tf.layers.lstm({
  units: 32,
  returnSequences: true,
  inputShape: [numTimesteps, numFeatures]
}));
model.add(tf.layers.lstm({units: 32, returnSequences: true}));
model.add(tf.layers.lstm({units: 32}));
model.add(tf.layers.dense({units: numClasses, activation: 'softmax'}));
model.compile({loss: 'categoricalCrossentropy', optimizer: 'rmsprop'});
用于减轻过拟合和提高收敛性的层和正则化器

除了上述主要的基本层类型之外,还有一些其他类型的层适用于广泛的模型和问题类型,并协助训练过程。没有这些层,许多机器学习任务的最新准确性不会像今天这样高。例如,dropout 和 batchNormalization 层经常插入到 MLP、卷积网络和 RNN 中,以帮助模型在训练过程中更快地收敛并减少过拟合。以下示例显示了包含 dropout 层的回归 MLP:

const model = tf.sequential();
model.add(tf.layers.dense({
  units: 32,
  activation: 'relu',
  inputShape: [numFeatures]
}));
model.add(tf.layers.dropout({rate: 0.25}));
model.add(tf.layers.dense({units: 64, activation: 'relu'}));
model.add(tf.layers.dropout({rate: 0.25}));
model.add(tf.layers.dense({units: 64, activation: 'relu'}));
model.add(tf.layers.dropout({rate: 0.25}));
model.add(tf.layers.dense({
  units: numClasses,
  activation: 'categoricalCrossentropy'
}));
model.compile({loss: 'categoricalCrossentropy', optimizer: 'rmsprop'});
13.2.3. 从 TensorFlow.js 使用预训练模型

当您要解决的机器学习问题特定于您的应用程序或数据集时,从头开始构建和训练模型是正确的方法,而 TensorFlow.js 使您能够做到这一点。然而,在某些情况下,您面临的问题是通用的,存在预训练模型,这些模型要么完全符合您的要求,要么只需进行轻微调整即可满足您的需求。来自 TensorFlow.js 和第三方开发人员的预训练模型集合。这些模型提供了干净且易于使用的 API。它们还作为 npm 包打包得很好,您可以方便地依赖它们在您的 JavaScript 应用程序(包括 Web 应用程序和 Node.js 项目)中。

在适当的使用案例中使用这些预训练模型可以大大加快您的开发速度。由于不可能列出所有基于 TensorFlow.js 的预训练模型,因此我们只会调查我们所知道的最流行的那些。以@tensorflow-models/为前缀的软件包是由 TensorFlow.js 团队维护的第一方软件包,而其余的是第三方开发者的工作。

@tensorflow-models/mobilenet 是一个轻量级图像分类模型。它能够根据输入图像输出 1,000 个 ImageNet 类别的概率分数。它适用于在网页中为图像标记、从网络摄像头输入流中检测特定内容,以及涉及图像输入的迁移学习任务。虽然@tensorflow-models/mobilenet 关注通用的图像类别,但也有第三方软件包用于更具特定领域的图像分类。例如,nsfwjs 将图像分类为包含色情和其他不当内容与安全内容,这对家长监控、安全浏览等应用非常有用。

如我们在第五章中讨论的那样,目标检测与图像分类不同之处在于,它不仅输出图像中包含的物体,还输出它们在图像坐标系中的位置。@tensorflow-models/coco-ssd 是一个能够检测 90 种对象的目标检测模型。对于每个输入图像,它都能够检测出可能有重叠边界框的多个目标对象(图 13.1,A 面)。

图 13.1。几个使用 TensorFlow.js 构建的预训练 npm 软件包模型的屏幕截图。A 面:@tensorflow-models/coco-ssd 是一个多目标对象检测器。B 面:face-api.js 用于实时人脸和面部特征点检测(通过 Vincent Mühler 的许可从github.com/justadudewhohacks/face-api.js复制)。C 面:handtrack.js 实时跟踪一个或两只手的位置(通过 Victor Dibia 的许可从github.com/victordibia/handtrack.js/复制)。D 面:@tensorflow-models/posenet 使用实时图像输入检测人体的骨骼关键点。E 面:@tensorflow-models/toxicity 检测并标记任何英文文本输入中的七种不当内容。


对于网络应用程序,特定类型的对象特别受到关注,因为它们有可能实现新颖有趣的计算机人类交互。这些包括人脸、手和整个身体。针对每一种类型,都有基于 TensorFlow.js 的专门的第三方模型。对于人脸,face-api.js 和 handsfree 都支持实时人脸跟踪和检测面部特征点(如眼睛或嘴巴;图 13.1,面板 B)。对于手部,handtrack.js 可以实时跟踪一个或两只手的位置(图 13.1,面板 C)。对于整个身体,@tensorflow-models/posenet 实现了高精度、实时的骨架关键点检测(如肩膀、肘部、臀部和膝盖;图 13.1,面板 D)。

对于音频输入模态,@tensorflow-models/speech-commands 提供了一个预训练模型,可以实时检测浏览器的 WebAudio API 中的 18 个英文单词。虽然这不像大词汇连续语音识别那样强大,但它仍然可以在浏览器中实现一系列基于语音的用户交互。

对于文本输入,也有预训练模型可用。例如,来自@tensorflow-models/toxicity 的模型确定给定的英文输入文本在多个维度上的毒性程度(例如,威胁、侮辱或淫秽),这对于辅助内容审核很有用(图 13.1,面板 E)。毒性模型是建立在一个更通用的自然语言处理模型@tensorflow-models/universal-sentence-encoder 之上的,该模型将任何给定的英文句子映射到一个向量,然后可以用于广泛的自然语言处理任务,如意图分类、主题分类、情感分析和问题回答。

需要强调的是,提到的一些模型不仅支持简单的推理,还可以为迁移学习或下游机器学习提供基础,使您能够将这些预训练模型的强大功能应用于您的领域特定数据,而无需进行冗长的模型构建或训练过程。这在一定程度上是由于层和模型的乐高式可组合性。例如,通用句子编码器的输出主要用于下游模型。语音命令模型内置支持您收集新单词类别的语音样本,并基于样本训练一个新的分类器,这对于需要自定义词汇或用户特定语音适应的语音命令应用非常有用。此外,来自 PoseNet 和 face-api.js 等模型的有关头部、手部或身体姿势的时时位置的输出可以输入到一个下游模型中,该模型检测特定的手势或动作序列,这对于许多应用程序非常有用,如辅助使用案例的替代通信。

除了之前提到的面向输入模态的模型之外,还有基于 TensorFlow.js 的第三方预训练模型,面向艺术创造性。例如,ml5.js 包括一个用于图像之间的快速风格转移的模型,以及一个可以自动绘制素描的模型。@magenta/music 提供了一个可以将钢琴音乐转录成谱曲的模型(“音频转谱”),以及一个“旋律的语言模型”,可以根据几个种子音符“写”出旋律,还有其他有趣的预训练模型。

预训练模型的收集庞大且不断增长。JavaScript 社区和深度学习社区都拥有开放的文化和分享精神。随着你在深度学习的旅程中不断前行,你可能会遇到一些有趣且对其他开发者有用的新想法,此时,我们鼓励你将这些模型以我们提到的预训练模型的形式训练、打包并上传到 npm,然后与用户互动并对你的包进行迭代改进。那时,你将真正成为 JavaScript 深度学习社区的一员贡献者。

JavaScript 深度学习(五)(2)https://developer.aliyun.com/article/1516991

相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
相关文章
|
23天前
|
机器学习/深度学习 JavaScript 前端开发
JavaScript 深度学习(五)(5)
JavaScript 深度学习(五)
8 0
|
23天前
|
机器学习/深度学习 JavaScript 前端开发
JavaScript 深度学习(五)(4)
JavaScript 深度学习(五)
24 0
|
23天前
|
存储 机器学习/深度学习 JavaScript
JavaScript 深度学习(五)(3)
JavaScript 深度学习(五)
22 0
|
23天前
|
机器学习/深度学习 并行计算 JavaScript
JavaScript 深度学习(五)(2)
JavaScript 深度学习(五)
29 0
|
23天前
|
机器学习/深度学习 前端开发 JavaScript
JavaScript 深度学习(四)(5)
JavaScript 深度学习(四)
12 1
|
23天前
|
机器学习/深度学习 存储 算法
JavaScript 深度学习(四)(4)
JavaScript 深度学习(四)
22 1
|
23天前
|
机器学习/深度学习 算法 JavaScript
JavaScript 深度学习(四)(3)
JavaScript 深度学习(四)
26 1
|
23天前
|
机器学习/深度学习 编解码 JavaScript
JavaScript 深度学习(四)(2)
JavaScript 深度学习(四)
22 1
|
23天前
|
机器学习/深度学习 自然语言处理 JavaScript
JavaScript 深度学习(四)(1)
JavaScript 深度学习(四)
12 2
|
3天前
|
机器学习/深度学习 数据采集 算法
未来研究将深入探索深度学习的应用及数据质量与安全问题
【6月更文挑战第13天】本文探讨了使用Python和机器学习预测股票价格的方法,包括数据收集与预处理(填充缺失值、处理异常值、标准化)、特征选择(技术指标、基本面指标、市场情绪)、模型选择与训练(线性回归、SVM、神经网络等)、模型评估与调优。尽管股票价格受多重因素影响,通过不断优化,可构建预测模型。未来研究将深入探索深度学习的应用及数据质量与安全问题。
18 5