目录

人工智能

目录

参考:




术语表

人工智能相关的一些相关术语:

  • 人工智能(AI, Artificial Intelligence)
  • 弱人工智能(Weak AI)
  • 强/通用人工智能(Strong AI, AGI)
  • 符号人工智能(Symbolic AI)
  • 专家系统(Expert System)
  • 推理引擎(inference engine)
  • 神经网络(Neural Network)
  • 深度学习(Deep Learning)
  • 计算机视觉(Computer Vision)
  • 自然语言处理(NLP, Natural Language Processing)
  • 图灵测试(Turing Test)
  • 人工神经网络(artificial neural network)
  • 机器学习(ML, Machine Learning)
  • 图形处理单元(GPU, Graphics Processing Unit)
  • 过拟合(overfitting)
  • 偏差(Bias):预测值与实际平均值的差值。
  • 方差(Variance):告诉我们数据的分布。
  • 卷积神经网路(CNN, convolutional neural network)
  • 光流(Optical flow)
  • 密集光流(Dense Optical Flow )
  • 稀疏光流(Sparse Optical Flow)
  • 卷积滤波器(convolutional filter)
  • 二维矩阵(2D-matrix)
  • 三位张量(3D-tensor)
  • 卷积核(kernel)
  • 滤波器(filter)
  • 矩阵(matrix)
  • 预训练网络(pre-trained newtorks)
  • 迁移学习(transfer learning)
  • 理想图像(ideal images)
  • 对抗攻击(adversarial attacks)
  • 梯度消失(vanishing gradients),梯度爆炸(exploding gradients)
  • 正态分布(Normal distribution)/ 高斯分布
  • 批量归一化(Batch Normalization)
  • 变异自动编码器(VAE, variational autoencoders)
  • 自监督学习(self-supervised learning)
  • 生成式对抗网络(GAN, generative adversarial network)
  • 生成器(generator)
  • 判别器(discriminator)
  • 风格转换(style transfer)
  • 物体检测(objectdetection)
  • 区域建议网络(Region Proposal Network)
  • 兴趣区域(Region of Interests)
  • 单通道(one-pass)
  • 词块、词元(token)



初学者的人工智能

探索人工智能的世界,包括符号人工智能、神经网络、深度学习、计算机视觉、自然语言处理等多个内容。

你将学习:

  • 关于人工智能的不同方法,包括使用知识表示(Knowledge Representation)的推理(reasoning)的古老符号方法。
  • 神经网络和深度学习是现代 AI 的核心。将使用两个最受欢迎的框架 TensorFlow 和 PyTorch 中的代码来阐述这些重要主题背后的概念。
  • 处理图像和文本的神经架构。
  • 不太流行的 AI 方法,如遗传算法(Genetic Algorithms)和多代理系统(Multi-Agent Systems)。



人工智能简介

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/ai-intro.png



课前测试

AI 是一门科学学科,研究如何使计算机表现出智能行为,例如做那些人类擅长的事情。

最初,查尔斯-巴贝奇发明的计算机安装明确定义的程序——算法,对数字进行运算。现代计算机比 19 世纪的原始模型先进得多,但仍遵循相同的受控计算理念。因此,如果我们知道实现目标所需的确切步骤顺序,就有可能对计算机进行编程。


根据照片确定一个人的年龄是一项无法明确编程的任务,因为我们不知道自己在做这件事时时如何在脑海中得出一个数字的。

有些任务我们并不明确知道如何解决。例如,从一个人的照片判断年龄。因为我们见过很多不同年龄的人的例子,所以我们学会了这样做。但我们无法解释如何做到这一点,也无法编写程序让计算机做到这一点。这正是 AI 感兴趣的任务。



弱AI和强AI

弱人工智能,强/通用人工智能。

Weak AI Strong AI(AGI)
针对特定任务或范围较小的任务,而设计和训练的人工智能系统。 指具有人类水平的管理和理解能力的人工智能系统。
一般没有智能,它们擅长执行预定任务,但缺乏真正的理解或意识。 有能力完成人类能够完成的任何智力任务,适应不同领域,并拥有某种形式的意识或自我意识。
例子包括 Siri 等虚拟助手、流媒体服务使用的推荐算法,以及为特定客户服务设计的聊天机器人。 实现它是一个长期目标,需要开发能够在各种任务和环境中进行推理、学习、理解和适应的系统。
弱 AI 高度专业化,不具备类似人类的认知能力,也不具备超出其狭窄领域的一般解决问题的能力。 目前,强 AI 还只是一个理论概念,还没有任何 AI 系统能达到这种通用智能水平。


智能的定义和图灵测试

智能一词没有明确的定义。人们可以说智能与抽象思维或自我意识有关,但我们无法给它下一个恰当的定义。

在谈论通用人工智能时,我们需要有一些方法来判断我们是否创建了一个真正的智能系统。阿兰-图灵提出了一种名为“图灵测试”的方法,它也是智能的一种定义。如果人类无法在基于文本的对话中区分真人和计算机系统,那么该系统就被认为是智能的。

你有没有被聊天机器人骗过,以为自己在和人类说话?它是如何说服你的?



AI的不同方法

如果我们想让计算机的行为像人类一样,我们就需要以某种方式在计算机中模拟人类的思维方式。因此,我们需要努力了解是什么造就了人类的智慧。

解决这个问题有两种可能的方法:

自上而下法(Symbolic Reasoning) 自下而上法(Neural Networks)
自上而下法是模拟人解决问题的推理方式。它包括从人的知识中提取知识,并以计算机可读的形式表示出来。还需要开发一种在计算机内部模拟推理的方法。 自下而上法以人脑结构为模型,由大量称为神经元的简单单元组成。每个神经元就像其输入的加权平均值,我们可以通过提供数据来训练神经元网络,从而解决有用的问题。

还有一些其他可能的智能的方法:

  • 新兴的、协同的或多代理的方法是基于这样一个事实,即复杂的智能行为可以通过大量简单代理的相互作用而获得。根据进化控制论,在元系统过渡过程中,智能可以从更简单的反应中产生。
  • 进化方法或遗传算法是一种基于进化元里的优化过程。


自上而下法

在此方法中,尝试对推理进行建模。由于在推理时可以跟随自己的思维,因此可以将这一过程形式化,并在计算机中进行编程。这就是所谓的符号推理。

人们的头脑中往往会有一些指导决策过程的规则。例如,当医生诊断病人时,他可能会意识到一个病人发烧了,因此体内可能有一些炎症。通过将大量规则应用于特定问题,医生可能会得出最终诊断结果。

这种方法很大程度上依赖于知识表示和推理。从人类专家那里提取知识可能是最困难的部分。因为在很多情况下,医生并不知道自己为什么会得出特定的诊断结果。有时,他只是在脑海中浮现出解决方案,而无需进行明确的思考。



自下而上法

我们可以通过模拟大脑中最简单的元素——神经元。我们可以在计算机中构建一个所谓的人工神经网络(artificial neural network),然后通过示例教它解决问题。这个过程类似于新生儿通过观察了解周围环境的过程。

研究一下婴儿是如何学习的。婴儿大脑的基本元素是什么?

机器学习是什么?人工智能的一部分是通过计算机学习来解决基于某些数据的问题,这称为机器学习(ML, Machine Learning)。请参考机器学习



AI简史

人工智能作为一个领域始于二十世纪中叶。最初,符号推理是一种流行的方法,并取得了一些重要的成功。然而,人们很快就发现,这种方法并不能很好地扩展。从专家那里提取知识,用计算机将其表示出来,并保持知识库的准确性,是一项非常复杂的任务,而且成本太高,在很多情况下并不实用。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/history-of-ai.png


随着时间的推移,计算资源变得越来越偏移,可用的数据也越来越多,因此神经网络方法开始在计算机视觉或语音理解等领域展现出与人类竞争的卓越性能。近十年来,人工智能一词大多被用作神经网络的同义词,因为我们听到的大多数人工智能成功案例都是基于神经网络。

如一个下棋程序:

  • 早期的国际象棋程序是以搜索为基础的,程序明确地产时估计对手在给定的下一步棋数中可能走的步数,并根据几步棋所能达到的最佳位置选择最佳棋步。这导致了所谓的 alpha-beta pruning 搜索算法的发展。
  • 搜索策略在棋局结束时很好,因为此时需要搜索的步数很少。然而,在棋局开始时,搜索空间是巨大的,因此可以通过学习人类棋手之间的现有对局来改进算法。
  • 能够战胜人类棋手的现代程序都是基于神经网络和强化学习,程序完全通过长时间与自己对弈并从自己的错误中学会下棋——这与人类学习下棋的过程非常相似。然而,计算机程序可以用更少的时间下更多的棋,因此学习速度也更快。


最新的AI研究

近期神经网络研究的巨大发展始于 2010 年左右,当时大型公共数据集开始可用。

2012 年,卷积神经网络首次用于图像分类,使分类错误率大幅下降。

从那时起,神经网络在许多任务中表现都非常成功:图像分类、会话语音识别、自动机器翻译和图像字幕等。

在过去几年中,大模型语言取得巨大成功,如 BERT 和 GPT-3。这主要归功于有大量的通用文本数据可供使用,让我们可以训练模型来捕捉文本的结构和含义,在通用文本几何上对它们进行预训练,然后针对更具体的任务对这些模型进行专门化。我们将在后面学习自然语言处理。




知识表示和专家系统

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/ai-symbolic.png

对人工智能的追求基于对知识的探求,即像人类一样理解世界。

符号AI基于两大理念:知识表示和推理。

如今,人工智能通常被认为是机器学习或神经网络的代名词。然而,人类也会进行显式推理,这时神经网络目前无法处理的。在现实世界的项目中,显式推理仍被用于执行需要解释的任务,或以受控方式修改系统行为。


课前练习课后练习



知识表示

符号 AI 的一个重要概念是知识,必须将知识与信息或数据区分开。例如,书籍包含知识,人们可以通过阅读书籍成为专家。然而,书籍包含的内容实际上被称为数据,通过阅读书籍并将这些数据整合到我们的世界模型中,我们就将数据转换为了知识。

知识使包含在我们头脑中的东西,代表着我们对世界的理解。知识是通过积极的学习过程获得的,它将我们接收到的信息碎片整合到我们对世界的积极模型中。


大多数情况下,我们并不严格定义知识。它包含一下概念:

  • 数据(Data):以文字或语言等物理介质表示,独立于人类而存在,可在人与人之间传递。
  • 信息(Information):我们在头脑中解读数据的方式。
  • 知识(Knowledge):融入我们世界模型的信息。
  • 智慧(Wisdom):我们理解世界的另一个层面,它代表着知识,即关于如何以及何时使用知识的一些概念。

因此,知识表示的问题是找到某种有效的方法,以数据的形式在计算机中表示知识,使其能够自动使用。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/knowledge-spectrum.png

在左侧,有几种简单的知识表示法可以被计算机有效利用。最简单的是算法,即用计算机程序来表示知识。然而,这并不是最佳方式,因为它并不灵活。我们头脑中的知识往往是非算法行的。

在右侧,是自然文本等表征。它的功能最强大,但不能用于自动推理。

想一想,你是如何在头脑中呈现知识并将其转化为笔记的?是否有一种特定的格式对你来说非常有效?



计算机知识表示分类

我们可以将不同的计算机知识表示法分为以下几类:

  • 网络表示,基于我们大脑中存在一个由相互关联的概念组成的网络。我们可以尝试在计算机中以图形的形式再现相同的网络,即所谓的语义网络。
  • 对象-属性-值或属性-值。由于图可以在计算机中表示为节点和边的列表,因此我们可以用包含对象、属性和值的三元组列表来表示语义网络。
  • 分层表示,我们经常在头脑中对物体进行层次划分。例如,我们知道金丝雀是一种鸟,所有鸟都有翅膀。
    • 框架表示,将每个对象或对象类表示为一个包含槽的框架。槽包含一些内容。所有框架形成一个层次结构,类似于面向对象编程语言中的对象层次结构。
    • 情景,是一种特殊的框架,代表着可以在时间中展开的复杂情况。
  • 程序化表示,通过一些列动作来表示知识,这些动作在特定条件发生时可以执行。
    • 生产规则是 if-then 语句,可让我们得出结论。
    • 算法可被视为另一种程序表示法,尽管它们几乎从不直接用于基于知识的系统中。
  • 逻辑学,最初由亚里士多德提出,作为表述人类普遍知识的一种方法。
    • 谓词逻辑作为一种数学理论,其内容丰富,无法计算,因此通常使用它的某些子集。
    • 描述逻辑是一系列逻辑系统,用于表示和推理分布式知识表示的对象层次。

例如,我们建立了以下有关编程语言的三元组:

Object Attribute Value
Python is Untyped-Language
Untyped-Language doesn’t have type definitions

Slot Value Default value Interval
Name Python - -
Is-A Untyped-Language - -
Variable Case - CamelCase -
Program Length - - 5-5000 lines


专家系统

符号人工智能的早期成功之一是所谓的专家系统,计算机系统充当某个有限问题领域的专家。它们基于从一个或多个人类专家那里提取知识库,并包含一个推理引擎,在此基础上进行推理。

人类神经系统的简化结构和基于知识的系统架构。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/arch-human.png

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/arch-kbs.png


专家系统旧项人类的推理系统一样,包含长期记忆和短期记忆。同样,在以知识为基础的系统中,我们区分一下几个组成部分:

  • 问题记忆:包含当前正在解决的问题的相关知识。如病人的提问或血压等。这种知识也被称为静态知识,因为它包含了我们当前对问题的了解的快照——即所谓的问题状态。
  • 知识库:代表有关问题领域的长期知识。它是从人类专家那里人工提取的,不会因咨询而改变。由于它允许我们从一个问题状态浏览到另一个问题状态,因此也被称为动态知识。
  • 推理引擎:协调整个问题状态空间的搜索过程,必要时向用户提问。

举个例子,下面这个专家系统,它可以根据动物的身体特征来判断动物。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/AND-OR-Tree.png



前向推理与反向推理

前向推理以工作记忆中有关问题的一些初始化数据为起点,然后执行以下推理循环:

  • 如果目标属性存在于工作记忆中,停止并给出结果。
  • 查找当前条件满足的所有规则,获得冲突规则集。
  • 执行冲突解决,选择一条将在此步骤中执行的规则。可能有不同的冲突解决策略:
    • 选择知识库中第一条适用的规则
    • 选择一个随机规则
    • 选择一个更具体的规则
  • 应用选定的规则,在问题状态中插入新知识。
  • 重复上述步骤

反向推理由目标——我们正在寻找的属性值驱动。



练习-动物推理

参考 Animals.ipynb,了解实施正向和反向推理的专家系统示例。



本体和语义网

20 世纪末,人们提出了使用知识表示法来注释互联网资源的倡议,这样就可以找到与非常具体的查询相对应的资源。这一动议被称为语义网(Semantic Web),它依赖于几个概念:

  • 一种基于描述逻辑学的特殊知识表示法。
  • 分布式知识表示法,即所有概念都由一个全局 URI 标识符表示,从而创建跨越互联网的知识层次结构。
  • 基于 XML 的知识描述语言系列:资源描述框架、RDF 模式、本体网络语言。

语义网的一个核心概念是本提概念。它是指使用某种形式的知识表示法对问题领域进行的明确规范。最简单的本地可能只是问题领域中对象的层次结构,但更复杂的本体将包括可用于推理的规则。



练习-家庭本体论

参考 FamilyOntology.ipynb,有关使用语义网技术推理家庭关系的示例。




神经网络简介-感知器

1957 年,康奈尔航空实验室的弗兰克-罗森布拉特首次尝试实现与现代神经网络类似的功能。这是一种名为 Mark-1 的硬件实现,旨在识别三角形、正方形和圆形等几何图形。

输入图像由 20x20 光电池阵列表示,因此神经网络有 400 个输入和一个二进制输出。一个简单的网络包含一个神经元,也称为阈值逻辑单元(threshold login unit)。神经网络的权重就像电位器,在训练阶段需要手动调整。


课前测试课后测试



感知器模型

感知器是一种二元分类模型,它可以区分输入数据的两个类别。输出结果将通过公式计算得出:$y(x)=f(w^Tx)$



训练感知器

为了训练感知器,我们需要找到一个权重向量 w,它能正确地对大部分数值进行分类,即误差最小。




神经网络简介-多层感知器

最简单的神经网络模型单层感知器,是一种线性两级分类模型。

本节我们将把这一模型扩展到一个更加灵活的框架中,是我们能够:

  • 进行多级分类
  • 解决回归问题
  • 分离不线性可分的类

课前测试课后测试




机器学习的形式化

让我们从机器学习问题的形式化开始。假设我们有一个带有标签 Y 的训练数据集 X,我们需要建立一个能做出最准确预测的模型 f。预测的质量由损失函数(Loss Function)来衡量。经常使用的损失函数如下:

  • 对于会归问题,当我们需要预测一个数字时,可以使用绝对误差(absolute error)或平方误差(squared error)。
  • 对于分类,我们使用 0-1 损失或逻辑损失。


梯度下降优化

有一个著名的函数优化方法叫梯度下降法(gradient descent)。其原理是,我们可以计算损失函数相对于函数的导数(在多维情况下称为梯度),并通过改变参数来减少误差。



多层感知器和反向传播

如上所述,单层网络能够对线性可分离的类别进行分类。为了建立更丰富的模型,我们可以将多层网络结合起来。



神经网络框架

要想高效地训练神经网络,我们需要做两件事:

  • 对张量(tensor)进行运算
  • 计算所有表达式的梯度,以便进行梯度下降优化

深度神经网络训练需要进行大量计算,因此在 GPU 上并行处理这些计算非常重要。


目前最流行的两个神经框架是: TensorFlow 和 PyTorch。两者都提供了低级 API,可在 CPU 和 GPU 上对张量进行操作。

1 2 3
Low-level API TensorFlow Pytorch
High-level API Keras PyTorch Lightning

低级 API,两个框架都允许你构建所谓的计算图。改图定义了如何在给定输入参数的情况下计算输出(通常是损失函数),如果 GPU 可用,还可以推送到 GPU 上进行计算。

高级 API,几乎将神经网络视为一个层序列,使大多数神经网络的构建变得更加容易。训练模型通常需要准备数据,然后调用 fit 函数来完成这项工作。

高级 API 可让你快速构建典型的神经网络,而无需担心大量细节。低级 API 对训练过程的控制能力更强,因此在研究新的神经网络架构时会被大量使用。



过拟合

过拟合使机器学习中一个极其重要的概念,正确理解它非常重要。

在模型的丰富程度(参数数量)和训练样本数量之间取得正确的平衡非常重要。



为什么会发生过拟合

  • 训练数据不足
  • 模型太强大
  • 输入数据噪音太大


如何检测过拟合

过拟合可通过极低的训练误差和较高的验证误差检测出来。



如何阻止过拟合

  • 增加训练数据量
  • 降低模型的复杂度
  • 使用一些正则化技术


偏差-方差权衡

过拟合实际上是统计学中一个更普遍的问题,即偏差-方差权衡(Bias-Variance Tradeoff)。

  • 偏差错误:是由于算法无法正确捕捉训练数据之间的关系造成的。其原因可能是模型不够强大(拟合不足)。
  • 方差错误:是模型逼近输入数据中的噪声而不是有意义的关系(过拟合)造成的。

在训练过程中,偏差误差会减小(模型学会了逼近数据),而方差误差会增大。手动或自动停止训练对于防止过拟合非常重要。




计算机视觉

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/ai-computervision.png


将了解以下内容:

  • 计算机视觉
  • 卷积神经网络
  • 预训练网络和迁移学习
  • 自动编码器
  • 生成式对抗网络
  • 物体检测
  • 分割


计算机视觉入门

计算机视觉是一门学科,其目标是让计算机获得对数字图像的高级理解。这是一个相当宽泛的定义,因为理解可以有很多不同的含义,包括在图片上找到一个物体(物体检测)、理解正在发生的事情(事件检测)、用文字描述图片或重建三维场景。还有一些与人类图像相关的特殊任务:年龄和情感估计、人脸检测和识别以及三维姿态估计等。


计算机视觉最简单的任务之一就是图像分类。

计算机视觉通常被认为是人工智能的一个分支。如今,大多数计算机视觉任务都是通过神经网络来解决的。用于计算机视觉的特殊类型神经网络——卷积神经网络。

不过,在将图像传递给神经网络之前,很多情况下都需要使用一些算法技术来增强图像的效果。

有多个可用的 Python 库用于图像处理:

  • imageio
  • Pillow
  • OpenCV
  • dlib


使用计算机视觉的示例

计算机视觉执行特定任务:

  • 预处理盲文书籍的照片:重点是如何使用阈值处理、特征检测、透视变换和 NumPy 操作来分离单个盲文符号,以便神经网络进一步分类。
  • 利用帧差检测视频中的运动:如果摄像机是固定的,那么拍摄的帧之间应该非常相似。由于帧是以数组的形式表示的,因此只需要减去随后两个帧的数组,就能得到像素差值,静态帧的像素差值应该较低,而一旦图像中出现较大的运动,像素差值就会变高。
  • 使用光流检测运动:通过光流,可以了解视频帧上的单个像素是如何移动的。
    • 密集光流 计算矢量场,显式每个像素的移动位置。
    • 稀疏光流 基于提取图像中的一些显著特征,并建立其从一帧到另一帧的轨迹。



卷积神经网络

我们希望能够识别图片上的物体,而不管图片中的确切位置。计算机视觉不同于一般的分类,因为当我们试图在图片中找到某个物体时,我们是在扫描图片,寻找一些特定的模式以及其组合。

为了提取模式,我们将使用卷积滤波器的概念。图像是由二位矩阵或具有颜色深度的三维张量表示的。应用滤波器意味着,我们需要一个相对较小的过滤器卷积核矩阵,对于原始图像中的每个像素,我们都要计算其与邻近点的加权平均值。我们可以将其视为在整个图像上滑动的一个小窗口,并根据滤波器卷积核矩阵中的权重对所有像素进行平均。



卷积神经网络背后的主要理念

CNN 的工作方式基于以下重要理念:

  • 卷积滤波器可提取模式
  • 我们可以在设计网络时自动训练滤波器
  • 我们可以使用同样的方法来发现高级特征中的模式,而不仅仅是原始图像中的模式。因此,CNN 的特征提取工作是基于特征的层次结构,从低层次的像素组合开始,一直到更高层的图片部分组合。


金字塔架构

大多数用于图像处理的卷积神经网络都采用所谓的金字塔架构。应用于原始图像的第一个卷积层通常具有相对较少的滤波器,这些滤波器对应不同的像素组合(如水平/垂直的笔画线条)。在下一层中,我们会减少网络的空间维度,增加滤波器的数量,从而对应更多可能的简单特征组合。每过一层,随着我们向最终分类器的迈进,图像的空间维度就会降低,滤波器的数量就会增加。




著名的卷积网络神经架构



VGG-16架构

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/vgg-16-arch.jpg



ResNet架构

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/resnet-block.png



Inception架构

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/inception.png



MobileNet




预训练网络和迁移学习

卷积神经网络的训练需要花费大量的时间和数据。然而,大部分时间都花在学习网络可以用来从图像提取模式的最佳底层滤波器上。

一个自然而然的问题出现了——能否使用在一个数据集上训练好的神经网络,在不需要完整的训练过程的情况下,将其用于不同图像的分类?

这种方法被称为迁移学习,因为我们将一些知识从一个神经网络模型迁移到另一个模型。在迁移学习中,我们通常从一个预先训练好的模型开始,该模型已经在一些大型图像数据集上训练过。这些模型已经可以很好地从普通图像中提取不同的特征,在很多情况下,只需在这些提取的特征之上构建分类器就能获得很好的结果。



作为特征提取器的预训练模型

如果我们再足够大的通用和多样化图像数据集上对卷积神经网络进行训练,该网络就能学会提取这些共同特征。

最常用的 CNN 架构在上一节中已经描述。



练习-迁移学习

Transfer Learning - TensorFlow



可视化对抗猫

预训练神经网络的大脑中包含不同的模式,包括理想猫(理想狗等)的概念。以某种方式将这一图像可视化会很有趣。然而,这并不简单,因为模式遍布整个网络权重,而且以层次结构组织。

我们可以采取的一种方法是从随机图像开始,然后尝试使用梯度下降优化技术来调整图像,是网络开始认为这是一只猫。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/ideal-cat-loop.png


但是,如果我们这样做,就会得到与随机噪声非常相似的结果。这是因为有很多方法可以让网络认为输入图像是一只猫,包括一些视觉上毫无意义的方法。虽然这些图像包含了很多猫的典型模式,但没有任何东西能限制它们在视觉上与众不同。

为了改善结果,我们可以在损失函数中加入“变异损失”——这是一个显示图像相邻像素相似程度的指标。将变异损失最小化可以使图像更平滑,并消除噪音,从而显示出更具视觉吸引力的图像。

下面是一个理想图像的例子,这些图像被高概率归类为猫和斑马:

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/ideal-images.png


类似的方法也可用于对神经网络所谓的对抗性攻击。假设我们想愚弄神经网络,让狗看起来像猫。如果我们使用狗的图像,而网络将其识别为狗,那么我们可以使用梯度下降优化法对其稍作调整,知道网络开始将其分类为猫。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/original-adversaria-dog.png




深度学习训练技巧

随着神经网络越来越深入,其训练过程也变得越来越具有挑战性。其中一个主要问题是所谓的 梯度消失梯度爆炸



将数值保持在合理区间

为了使数值计算更加稳定,我们希望确保神经网络中的所有数值都在合理的范围内。这并不是一个非常严格的要求,但浮点运算的性质决定了不同量级的数值无法精确地放在一起处理。

大多数激活函数在 [-1..1] 附近具有非线性,因此将所有输入数据缩放至 [-1..1][0..1] 区间是合理的。



初始权重初始化

在理想情况下,我们希望数值在经过网络层后保持在同一范围内。因此,在初始化权重时,必须保持权重值的分布。

正态分布 N(0,1) 并不是一个好主意,如果我们有 n 个输入,输出的标准偏差就是 n,而且数值和可能跳出 [0..1] 区间。

经常使用的初始化如下:

  • 均匀分布
  • N(0,1/n)
  • N(0,1/√n_in)
  • N(0,√2/(n_in+n_out))


批量归一化

即使进行了适当的权重初始化,权重也可能在训练过程中任意变大或变小,从而使信号超出了适当的范围。可以使用归一化技术使信号恢复正常。

虽然有多种归一化技术(权重归一化、层归一化),但最常用的还是批量归一化。

批量归一化的原理是考虑整个小批量中的所有值,并根据这些值进行归一化(即减去平均值并除以标准偏差)。它是作为一个网络层来实现的,在应用权重之后、激活函数之前进行归一化。因此,可能会有更高的最终准确率和更快的训练速度。



Dropout

Dropout 技术能在训练过程中移除一定比例的随机神经元。

这种效应有几种解释:

  • 它可以被视为模型的随机冲击因子,使优化过程摆脱局部最小值的限制。
  • 这可以看作是隐式模型平均。


防止过度拟合

深度学习的一个非常重要的方面就是能够防止过度拟合。我们始终应该平衡模型参数数量与训练样本数量之间的关系。

有几种方法可以防止过度拟合:

  • 早期停止–持续监控验证集上的误差,并在验证误差开始增加时停止训练。
  • 显式权重衰减/正则化–为权重绝对值较高的损失函数增加额外的惩罚,从而防止模型得到非常不稳定的结果。
  • 模型平均–训练多个模型,然后求平均值。这有助于将方差最小化。
  • Dropout(隐式模型平均)


优化器和训练算法

训练的另一个重要方面是选择好的训练算法。虽然经典的梯度下降是一种合理的选择,但有时会过于缓慢,或导致其他问题。

在深度学习中,我们使用随机梯度下降法,它从训练集中随机选取小批量数据进行梯度下降。

  • 动量随机梯度下降法
  • Adagrad, Adam
  • 梯度剪裁
  • 学习率衰减


不同的网络架构

为你的问题选择正确的、已被证明适用于特定任务的网络架构。




自动编码器

在训练神经网络时,一个问题是我们需要大量标记数据。就图像分类而言,我们需要将图像分成不同的类别,这需要人工操作。

不过,我们可能希望使用原始数据来训练卷积神经网络特征提取器,这就是所谓的自监督学习。我们将使用训练图像作为网络输入输出,而不是标签。自动编码器的主要思想,将有一个编码器网络,将输入图像转换到某个潜在空间,然后是解码器网络,其目标是重建原始图像。

自动编码器是一种人工神经网络,用于学习未标记数据的有效编码。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/autoencoder_schema.jpg



自动编码器的使用场景

虽然重建原始图像本身似乎没什么用,但在一些情况下,自动编码器却特别有用:

  • 降低图像维度,实现可视化或训练图像嵌入。
  • 去噪
  • 超分辨率
  • 生成模型


变异自动编码器

传统的自动编码器以某种方式降低输入数据的维度,找出输入图像的重要特征。然而,潜向量往往没有太大意义。

要训练生成式模型,最好对潜空间有一定的了解。这一想法让我们想到了变异自动编码器,用于预测潜在参数的统计分布,即所谓的潜分布。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/vae.png


变异自动编码器使用由两部分组成的复杂损失函数:

  • 重建损失,是显示重建图像与目标图像接近的损失函数。
  • KL 损失,确保潜变量分布接近正态分布。

VAE 的一种重要优势是,它能让我们相对轻松地生成新图像,因为我们知道从哪个分布中对潜向量进行采样。



自动编码器的特性

  • 数据专用性,它们只适用于经过训练的图像类型。
  • 有损耗,重建后的图像与原始图像不同。
  • 适用于未标记的数据



生成式对抗网络

前面,我们了解了生成式模型——可以生成与训练数据集中相似的图像。VAE 就是生成式模型的一个很好的例子。

但是,如果我们尝试用 VAE 生成真正有意义的东西,比如一幅分辨率合理的画作,就会发现训练收敛效果并不好。针对这种用例,我们应该了解另一种专门针对生成模型的架构,生成式对抗网络。

GAN 的主要理念是让两个神经网络相互训练:

  • 生成器是一个网络,它获取一些随机矢量,然后生成图像。
  • 判别器是一个获取图像的网络,它可以判别图像是真实的(来做训练数据集),还是有生成器生成的。它本质上是一个图像分类器。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/gan_architecture.png



判别器

判别器的结构与普通图像分类网络并无不同。在最简单的情况下,它可以是全连接分类器,但最有可能是卷积网络。

卷积神经网络判别器由以下几层组成:若干的卷积 + 汇集(空间大小依次递减)和一个/多个全连接层,以获得特征向量和最终二元分类器。



生成器

生成器稍微复杂一些。可将其视为反向判别器。从潜向量开始,它有一个全连接层,将其转换为所需的大小/形状,然后进行解旋和升旋。这与自动编码器的解码器部分类似。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/gan_arch_detail.png



训练生成式对抗网络

GAN 之所以被称为对抗型网络,是因为生成器与判别器之间存在着持续的竞争。在这种竞争过程中,生成器和判别器都会不断改进,从而使网络学会生成越来越好的图像。

训练分两个阶段进行:

  • 训练判别器。这项任务很简单:用生成器生成一批图像(标记为 0,代表假图像)。然后从输入数据集中提取一批图像(标记为 1, 代表真图像)。我们会得到一些判别损失,然后进行反推。
  • 训练生成器。这一点有些棘手,因为我们无法直接知道生成器的预期输出。我们使用由生成器和判别器组成的整个 GAN 网络,向其输入一些随机矢量,并预期结果为 1(对应真是图像)。然后,我们冻结判别器的参数(我们不希望在这一步对其进行训练),并执行反向推演。

在这一过程中,生成器和判别器的损耗都不会明显降低。在理想情况下,它们应该会出现振荡,这与两个网络的性能都有所提高是相对应的。



生成式对抗网络训练的问题

GAN 特别难以训练,下面是几个问题:

  • 模式崩溃。指生成器学会生成一个成功的图像来欺骗生成器,而不是生成各种不同的图像。
  • 对超参数的敏感性。GAN 根本不会收敛,然后学习率会突然下降,从而导致收敛。
  • 保持生成器和判别器之间的平衡。在很多情况下,判别器的损失会相对较快地降到零,从而导致生成器无法继续训练。为了解决这个问题,可以尝试为生成器和判别器设置不同的学习率,或在损失已经过低的情况下跳过判别器训练。
  • 高分辨率训练。由于重建卷积网络的层数过多而导致伪影。此问题通常用渐进式增长来解决,即首先在低分辨率图像上训练几层,然后解锁或增加几层。


风格转换

GAN 是生成艺术图像的绝佳方法。另一种有趣的技术是所谓的风格转换。它采用一种内容图像,并应用风格网络中的过滤器,以不同的风格重新绘制。

其工作原理如下:

  • 从随机噪声图像开始
  • 目标是创建这样一种图像,它即接近内容图像,又接近风格图像。这将由两个损失函数决定:
    • 内容损失,根据 CNN 从当前图像和内容图像的某些层提取的特征计算出来的。
    • 风格损失,通过一种巧妙的方法,即使用革兰氏矩阵在当前图像和风格图像之间计算出来的。
  • 为了使图像更平滑并消除噪音,还引入了变异损失,它可以计算相邻像素之间的平均距离。
  • 主要的优化环路使用了梯度下降算法调整当前图像,以尽量减少总损失(所有三项损失的加权和)。



物体检测

迄今为止,我们所处理的图像分类模型都是通过图像得出分类结果。然而,在很多情况下,我们并不希望仅仅知道图片上有物体,还希望能够确定物体的精确位置。这正是物体检测的意义所在。



物体检测的原生方法

假设我们想在一张图片上找到一只猫,那么非常简单的物体检测方法如下:

  • 将图片分解成若干块瓷砖。
  • 对每块瓷砖进行图像分类。
  • 激活度足够高的瓷砖可被视为包含相关物体。

然而,这种方法远非理想,因为它只能让算法非常不精确地确定物体的边界框。要想获得更精确的定位,需要进行某种回归来预测边界框的坐标——为此,需要特定的数据集。



物体检测回归



物体检测数据集



物体检测指标

对于物体检测,我们即需要衡量分类的正确性,也需要衡量推断边界框位置的准确性。对此,使用交并比(IoU, Intersection over Union)来衡量边框的重叠程度。

概念很简单,用两个图形的交集面积除以它们的结合面积。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/iou_equation.png


平均精度(Average Precision)


平均精度均值(mAP, Mean Average Precison)



不同的物体检测方法

物体检测算法有两大类:

  • 区域建议网络(R-CNN, Fast R-CNN, Faster R-CNN)。主要思路是生成兴趣区域,然后着这些区域上运行 CNN,寻找最大激活度。这种方法一个缺点是速度较慢,因为需要对图像进行多次 CNN 分类。
  • 单通道(YOLO, SSD, RetinaNet)方法。着这些架构中,设计的网络可以一次性预测类别和兴趣区域。



分割算法

物体检测,让我们通过预测图像中物体的边界框来定位物体。然而,在某些任务中,不仅需要边界框,还需要更精确的物体定位。这项任务被称为分割(Segmentation)。

分割可以看作是像素分类,而对于图像中的每个像素,都必须预测其类别。主要有两种分割算法:

  • 语义分割(Semantic segmentation)。只能显示像素的类别,并不能区分同一列类别中的不同对象。
  • 实例分割(Instance segmentation)。将类别划分为不同的实例。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/instance_vs_semantic.jpeg


用于分割的神经架构各有不同,但都具有相同的结构。在某种程度上,它类似于自动编码器,但我们的目标不是解构原始图像,而是解析遮罩。因此,分割网络有以下几个部分:

  • 编码器从输入图像中提取特征。
  • 解码器将这些特征转换为掩码图像(mask image),其大小和通道数与类别数相同。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/segm.png



医学影像分割




自然语言处理

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/ai-nlp.png


讨论使用神经网络处理与自然语言处理(NLP, Natural Language Processing)相关的任务。我们希望计算机能够解决许多 NLP 问题:

  • 文本分类(Text Classification)是与文本序列相关的典型分类问题。如将文章分类为体育、经济和政治等类别。
  • 情感分析(Sentiment analysis)是一个典型的回归问题。根据句子含义的正负面程度,赋予一个相应的情感数字。如“在这家餐厅,我喜欢这里的菜肴,但气氛很糟糕”。
  • 命名实体识别(NER, Named Entity Recognition)指从文本中提取特定实体的问题。如“我明天需要飞往巴黎”这句话,明天指日期,巴黎指地点。
  • 关键字提取(Keyword extraction)与 NER 类似,但我们需要自动提取对句子意义重要的词语,而无需针对特定实体进行预训练。
  • 文本聚类(Text clustering),当我们想将类似的句子归类在一起时,文本聚类就会派上用场。
  • 问题解答(QA, Question Answering)指模型回答特定问题的能力。
  • 文本生成(Text Generation)指模型生成新文本的能力。先进的文本生成模型(如 GPT-3),能够使用一种称为提示编程(prompt programming)或提示工程(prompt engineering)的技术解决其他 NLP 任务。
  • 文本摘要(Text summarization)是一种概括长篇文字的技术。
  • 机器翻译(Machine translation)可视为一种语言文本理解和另一种语言文本生成的结合。

最初,大多数 NLP 任务都是使用语法等传统方法解决的。如今,使用神经网络可以更有效地解决许多 NLP 任务。

自然语言处理工具包 的 Python 库中实现了许多经典的 NLP 方法。




用张量表示文本



文本分类

讨论文本分类任务。



表示文本

如果我们想用神经网络解决 NLP 任务,就需要某种方法将文本表示为张量。计算机能将文本字符表示为数字,并通过 ASCII 或 UTF-8 等编码方式来表示。

作为人类,我们了解每个字母代表什么,以及所有字符如何组成一个句子。然而,计算机本身并不具备这种理解能力,神经网络必须在训练过程中学习其含义。

因此,在表示文本时,我们可以使用不同的方法:

  • 字符级表示法,即将每个字符视为一个数字来表示文本。
  • 单词级表示法,创建一个包含文本中所有词(word)的词汇表(vocabulary),然后使用独热编码(one-hot encoding)来表示单词。此方法在某种程度上更好,因为每个字母本身并没有太多意义,因此通过更高层次的语义概念——词,简化了神经网络的任务。不过,由于字典容量较大,我们需要处理高纬稀疏张量。

无论采用哪种表示法,首先需要将文本转换成一串词块(token),一个词元可以是一个字符、一个词,有时甚至是一个词的一部分。然后,将词元转换为一个数字,通常使用词汇表,这个数字可以通过独热编码输入到神经网络。



N元组

在自然语言中,词的确切含义只能根据上下文来确定。例如 neural network 与 fishing network 的含义就完全不同。考虑到这一点的方法之一是在词对(pairs of words)的基础上建立我们的模型,并将词对视为独立的词汇表词元。

“I like to go fishing” 这个句子就可以用下面的词块序列来表示:I like, like to, to go, go fishing。这种方法的问题在于,词典的容量会大幅增加,而像 go fishing 和 go shopping 这样的组合会由不同的词块来表示,尽管使用的是同一个动词,但它们在语义上没有任何相似之处。

在某些情况下,还可以考虑三元组(tri-grams)(三个词的组合)。因此,这种方法通常被称为 N元组(n-grams)。此外,使用字符级表示的 n-gram 也很有意义,在此情况下,n-gram 将大致对应于不同的音节。



词袋

在解决文本分类等内容时,需要用一个固定大小的向量来表示文本,并将其作为最终密集分类器的输入。要做到这一点,最简单的方法之一就是将所有单独的词表示组合起来,例如将它们相加。如果我们将每个词的单词编码相加,最终就会得到一个频率向量,显示每个词在文本中出现的次数,这种文本表示法称为 词袋(BoW, bag of words)。

从本质上将,词袋代表了文本中出现的词及其数量,这的确可以很好地说明文本的内容。例如,关于政治的新闻很可能包含国家、部门和领导人等信息。因此,词频(word frequency)在很多情况下可以很好地说明文本内容。

词袋的问题在于,某些常用词(如 and, is 等)会出现在大多数文本中,而且出现频率最高,从而掩盖了真正重要的词。可以通过考虑词在整个文档集中出现的频率来降低这些词的重要性。这就是 TF/IDF 方法背后的主要思想。

然而,这些方法都不能完全考虑文本的语义。需要更强大的神经网络模型来做到这一点。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/bow.png




语义词嵌入

Semantic word embeddings

在训练基于 BoW 或 TF/IDF 的分类器时,我们使用的是长度为 vocab_size 的高维词袋向量,并且我们明确地将低维位置表示向量转换为稀疏的独热(one-hot)表示。然而,这种独热表示并不节省内存。此外,每个词都是独立处理的,也就是说,独热编码向量并不能表达词之间的任何语义相似性(semantic similarity)。

嵌入(embedding)的概念是用低维密集向量(lower-dimensional dense vectors)来表示词,这种向量以某种方式反映词的语义。可将嵌入视为降低词向量维度的一种方法。

因此,嵌入层会将作为一个词作为输入,并产生一个指定 embeeding_size 的输出向量。从某种意义上说,它与 Linear 层非常相似,但它不接收独热编码向量,而是接收词编号作为输入,这样我们就可以避免创建大量的独热编码向量。

通过将嵌入层作为分类器网络的第一层,我们可以将词袋模型转换为嵌入袋模型,即首先将文本中的每个词转换为相应的嵌入,然后计算所有这些嵌入的聚合函数(如总和、平均值或最大值等)。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/embedding-classifier-example.png



语义嵌入-Word2Vec

Semantic Embeddings

虽然嵌入层学会了将词映射到向量表示中,但这种表示并不一定具有太多的语义。如果能学会一种向量表示法,使相似的词语或同义词对应于在某种向量距离上相互接近的向量,那就更好了。

为此,我们需要以特定的方式在大量文本集合上预先训练我们的嵌入模型。其中一种训练语义嵌入的方法称为 Word2Vec。它基于两种主要架构,用于生成词的分布式表示:

  • 连续词袋(CBoW, Continuous Bag-of-Words),着这种结构中,我们训练模型从周围上下文中预测一个词。
  • 连续跳格(Continuous skip-gram),与 CBoW 相反。该模型使用周围的语境词窗口来预测当前单词。

CBoW 的速度更快,而 skip-gram 的速度较慢,但在表示不常见的词方面做的更好。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/example-algorithms-for-converting-words-to-vectors.png


Word2Vec 预训练嵌入也可以用来代替神经网络中的嵌入层。不过,我们需要处理词汇问题,因为用于预训练 Word2Vec 的词汇很可能与我们文本语料库中的词汇不同。



上下文嵌入

Contextual Embeddings

传统预训练嵌入表示法(如 Word2Vec)的一个主要局限是词义消歧问题(word sense disambiguation)。虽然它可以捕捉到上下文中的部分词义,但一个词的所有可能含义都会被编码到相同的嵌入中。这可能会给下游模型带来问题,因为许多词在不同的语境中会有不同的含义。

为了克服这一局限,我们需要根据语言模型(language model)来构建嵌入,因为语言模型是在大量文本语料库中训练出来的,知道在不同语境中如何将单词组合在一起。




语言模型

Language Modeling. Training your own embeddings.

语义嵌入实际上是语言模型的第一步——创建能以某种方式理解语言性质的模型。

语言模型背后的主要理念是以无监督的方式在未标记的数据集上对其进行训练。这一点很重要,因为我们有大量的未标记文本,而标记文本的数量总是受限于我们在标记上所能花费的精力。大多数情况下,我们可以建立能够预测文本中缺失单词(predict missing words)的语言模型,因为在文本中随机屏蔽一个单词并将其作为训练样本是很容易的。



训练嵌入

Training Embeddings

在前面的示例中,我们使用了预先训练好的语义嵌入,但如何训练这些嵌入也很有意思。有几种可能的思路可以使用:

  • N-Gram 语言模型
  • CBoW
  • Skip-gram



循环神经网络

Recurrent Neural Networks, RNN

在前面的章节中,我们使用了丰富的文本语义表示和嵌入式之上的简单线性分类器。这种架构的作用是捕捉句子中单词的综合含义,但它并不考虑单词的顺序,因为在嵌入式之上进行的聚合操作会从原始文本中删除这一信息,由于这些模型无法对单词顺序进行建模,因此无法解决更复杂或更模糊的任务,如文本生成或问题解答。

要捕捉文本序列的含义,我们需要使用另一种神经网络架构——循环神经网络(RNN)。在 RNN 中,我们每次将句子中的一个符号传递个网络,网络会产生一些状态,然后再将下一个符号传递个网络。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/rnn.png



RNN单元剖析

Anatomy of an RNN Cell

它接受前一个状态 $S_{i-1}$ 和当前符号 $X_i$ 作为输入,并必须产生输出状态 $S_i$。

一个简单的 RNN cell 内部有两个权重矩阵:一个是转换输入符号(称之为 W),另一个是转换输入状态(称之为 H)。在这种情况下,网络输出的计算公式为 $σ(W×X_i+H×S_{i-1}+b)$,其中 σ 是激活函数,b 是附加偏差。

在许多情况下,输入词块在进入 RNN 之前会经过嵌入层,以降低维度。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/rnn-anatomy.png



长短期记忆

Long Short Term Memory (LSTM)

经典 RNN 的主要问题之一是所谓的梯度消失问题(vanishing gradients)。由于 RNN 是通过一次反向传播进行端到端训练的,因此很难将误差传播到网络的第一层,网络也就无法学习远处词块之间的关系。避免此问题的方法之一是通过使用所谓的门(gates)来引入显式状态管理(explicit state management)。有两种著名的此类结构:长短期记忆(LSTM)和门控中继单元(GRU, Gated Relay Unit)。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/long-short-term-memory-cell.svg


LSTM 网络的组织方式与 RNN 类似,但在层与层之间传递的是两种状态:实际状态 C 和隐藏向量 H。在每个单元中,隐藏向量 H 与输入 $X_i$ 相连,它们通过门控制状态 C 的变化。每个门都是一个具有sigmoid 激活功能(输出范围为 [0, 1])的神经网络,当它与状态向量相乘时,可以将其视为一个比特掩码。

有以下几个门(上图中从左到右依次为):

  • forget gate,获取一个隐藏向量,并确定我们需要遗忘向量 C 中的哪些分量,以及哪些需要传递。
  • input gate,从输入矢量和隐藏矢量中获取一些信息,并将其插入状态。
  • output gate

状态 C 的组成部分可以看作是一些可以打开或关闭的标志。



双向和多层RNN




生成式循环网络

Generative Recurrent Networks

循环神经网络(RNN)及其门控单元变体(如 LSTM 和 GRU)为语言建模提供了一种机制,即它们可以学习单词排序,并为序列中下一个单词提供预测。这使得我们可以将 RNN 用于生成任务(generative task),如普通文本生成、机器翻译,甚至图像字幕。

每个 RNN 单元都会产生下一个隐藏状态作为输出。不过,我们也可以为每个递归单元添加另一个输出,这样就能输出一个序列(与原始序列等长)。此外,我们还可以使用每一步都不接受输入的 RNN 单元,只接受某个初始状态向量,然后产生一串输出。

如下图所示,不同的神经架构都可以实现:

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/unreasonable-effectiveness-of-rnn.jpg


  • one-to-one,有一个输入和输出的传统神经网络。
  • one-to-many,是一种生成式架构,它接受一个输入值,并生成一系列输出值。例如,如果我们想训练一个能生成图片文字说明的图片字幕(image caption ing)网络,可以将一张图片作为输入,通过 CNN 获取其隐藏状态,然后让递归链(recurrent chain)逐字生成字幕。
  • many-to-one,对应于上一单元中描述的 RNN 架构,例如文本分类。
  • many-to-many(sequence-to-sequence),对应的任务如机器翻译,我们让第一个 RNN 将输入序列中的所有信息收集到隐藏状态中,然后由另一个 RNN 链将该状态展开到输出序列中。

在本单元中,我们将学习帮助我们生成文本的简单生成式模型。为简单起见,我们将使用字符级词块化(character-level tokenization)。

我们将逐步训练 RNN 生成文本。在每一步中,我们将获取长度为 nchars (n 个字符)的字符序列,并要求网络为每个输入字符生成下一个输出字符:


https://raw.githubusercontent.com/zhang21/images/master/cs/ai/rnn-generate.png


在生成文本时(推理过程中),我们从某个提示(prompt)开始,通过 RNN 单元生成中间状态,然后从这个状态开始生成。每次生成一个字符,然后将状态和生成的字符传递给另一个 RNN 单元,生成下一个字符,直到生成足够多的字符为止。


https://raw.githubusercontent.com/zhang21/images/master/cs/ai/rnn-generate-inf.png



软文本生成和温度

Soft text generation and temperature

每个 RNN 单元的输出式字符的概率分布(probability distribution)。如果我们总是将概率醉倒的字符作为生成文本的下一个字符,那么文本往往会在相同的字符序列之间反复循环(cycled),就像下例一样:


1
today of the second the company and a second the company ...

但是,如果我们看一下下一个字符的概率分布,可能几个最高概率之间的差别并不大,比如一个字符的概率是 0.2,另一个是 0.19,等等。例如,在查找 play 的下一个字符时,既可以时空格,也可以是 e(player)。

由此我们可以得出结论:选择概率较高的字符并不总是公平的,因为选择第二高的字符仍有可能得到有意义的文本。

更明智的做法是从网络输出给出的概率分布中抽取字符。我们还可以使用一个参数——温度,它可以使概率分布更平缓,以防我们想增加随机性,或使概率分布更陡峭,以防我们想更多地选择概率最高的字符。




注意力机制和变换器模型

Attention Mechanisms and Transformers

机器翻译(machine translation)是 NLP 领域最重要的问题之一,也是谷歌翻译等工具的基本任务。本节将重点讨论机器翻译,或者更广义地说,任何序列到序列的任务(sequence-to-sequence),也称为句子转换。

在 RNN 中,序列到序列由两个递归网络实现,其中一个网络(编码器)将输入序列折叠为隐藏状态,而另一个网络(解码器),则将此隐藏状态展开为翻译结果。这种方法存在一些问题:

  • 编码器网络的最终状态很难记住句子的开头,因此导致长句子的模型质量较差。
  • 序列中的所有单词对结果的影像相同。但实际上,输入序列中的特定词语对序列输出的影响往往大于其他词语。

注意力机制(Attention Mechanisms),提供了一种对每个输入向量对每个 RNN 输出预测的上下文影响加权的方法。此机制可以增强神经网络输入数据中某些部分的权重,同时减弱其他部分的权重。其实现方式是在输入 RNN 和输出 RNN 的中间状态之间创建捷径。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/encoder-decoder-attention.png

下面是一个矩阵示例:

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/bahdanau-fig3.png


注意力机制是当前或接近当前 NLP 技术水平的主要原因。然而,增加注意力会大大增加模型参数的数量,从而导致 RNN 的扩展问题。扩展 RNN 的一个关键限制因素是,模型的递归性质使得批量和并行化训练具有挑战性。在 RNN 中,序列中的每个元素都需要按顺序处理,这意味着它并不容易并行化。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/EncDecAttention.gif


注意力机制的采用与这一限制因素相结合,创造了我们今天所熟知和使用的最先进的变换器(transformer)模型,如 BERT(基于变换器的双向编码器表示技术) 到 GPT3(生成式预训练变换模型)。GPT3 基于谷歌开发的 Transformer 模型。



变换器模型

变换器背后的主要理念之一是避免 RNN 的顺序性,并创建一个在训练过程中可并行的模型。要做到这一点,需要落实两个理念:

  • 位置编码(positional encoding)
  • 使用自我注意力机制(self-attention)来捕捉模式,而不是使用 RNN 或 CNN。


位置编码

位置编码的原理如下:

  • 在使用 RNN 时,词块的相对位置由步数表示,因此无需明确表示。
  • 但是,一旦我们转而使用注意力,就需要知道词块在序列中的相对位置。
  • 为了获得位置编码,我们用序列中的词块位置序列(即0、1…)来增强我们的词块序列。
  • 然后,我们将词块位置与词块嵌入向量混合。要将位置转换为向量,有以下不同的方法:
    • 可训练嵌入,类似于词块嵌入。我们在词块及其位置之上应用嵌入层,产生相同维度的嵌入向量,然后将其相加。
    • 固定位置编码功能。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/pos-embedding.png



多头自我注意力

Multi-Head Self-Attention

接下来,我们需要在序列中捕捉一些模式。为此,变换器使用了自我注意力机制(self-attention),即对输入和输出的相同序列进行注意。应用自我注意可以让我们考虑到句子中的上下文,并了解哪些词语是相互关联。

例如,它能让我们看到哪些词是通过核心关联词(如 it)来指代的,同时还能将上下文考虑在内:

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/CoreferenceResolution.png


在变换器中,我们使用多头注意力(Multi-Head Attention),以便让网络能够捕捉到几种不同类型的依赖关系。例如长期与短期的词语关系,共同参照与其他关系。



编码器-解码器注意力

Encoder-Decoder Attention

在变换器中,有两处使用了注意力:

  • 利用自我注意力捕获输入文本中的模式。
  • 执行序列转换,它是编码器和解码器之间的注意力层。

下图解释了编码器-解码器注意力的作用。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/transformer-animated-explanation.gif

由于每个输入位置都是独立映射到每个输出位置的,因此变换器比 RNN 具有更好的并行性,从而可以建立更大、更有表现力的语言模型。每个注意力头可用于学习单词之间的不同关系,从而改进下游的自然语言处理任务。



BERT

基于变换器的双向编码器表示技术(BERT, Bidirectional Encoder Representations from Transformers),是一个非常大的多层变换器网络,BERT-base 有 12 层,BERT-large 有 24 层。该模型是第一个预训练模型,它在一个大型文本数据语料库(WikiPedia + books)上进行无监督训练(预测句子中的隐藏词)。在预训练过程中,模型吸收了大量的语言理解能力,然后可以通过微调利用其他数据集。这一个过程被称为 迁移学习(transfer learning)。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/jalammarBERT-language-modeling-masked-lm.png




命名实体识别

NER, Named Entity Recognition


到目前为止,我们主要专注于一种 NLP 任务——分类。不过,神经网络也可以完成其它 NLP 任务。其中一项任务是命名实体识别(NER),即识别文本中特定实体,如地名、人名、日期时间间隔和化学式等。



NER使用示例

假设你想开发一个自然语言聊天机器人,智能聊天机器人的工作方式是通过对输入句子进行文本分类来了解用户的需求。这种分类的结果就是所谓的意图,它决定了聊天机器人应该做什么。

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/bot-ner.png


不过,用户可以在短语中提供一些参数。例如,在询问天气时,用户可能会指定一个地点或日期。机器人应该能够理解这些实体,并在执行操作前填写相应的参数。这正是 NER 的作用。



作为词块分类的NER

NER as Token Classification

NER 模型本质上是词块分类模型(token classification),因为对于每个输入词块,都需要判断它是否属于某个实体,如果属于,又属于哪个实体类别。

请看下面论文的题目:

Tricuspid valve regurgitation and lithium carbonate toxicity in a newborn infant.

这里的实体是:

  • Tricuspid valve regurgitation 是一种疾病(DIS)
  • Lithium carbonate 是一种化学物质(CHEM)
  • Toxicity 是一种疾病(DIS)

请注意,一个实体可以跨越多个词块。在本例中,我们需要区分两个连续的实体。因此,通常为每个实体使用两个类——一个类表示实体的第一个词块(通常使用 B- 前缀,表示开始);另一个类表示实体的延续(I-前缀,表示内部词块)。我们还使用 O 作为一个类来表示所有其他词块。这种词块标记被称为 BIO 标记。


标记后,我们的标题看起来像这样:

Token Tag
Tricuspid B-DIS
valve I-DIS
regurgitation I-DIS
and O
lithium B-CHEM
carbonate I-CHEM
toxicity B-DIS
in O
a O
newborn O
infant O
. O

由于我们需要在词块和类别之间建立一一对应的关系,因此我们可以根据这行图片训练一个最右边多对多神经网络模型:

https://raw.githubusercontent.com/zhang21/images/master/cs/ai/unreasonable-effectiveness-of-rnn.jpg



训练NER模型

由于 NER 模型本质上是一个词块分类模型,因此我们可以使用 RNN 来完成这项任务。在这种情况下,每个递归网络块都将返回词块 ID。




大语言模型和提示工程

Large Language Models, Prompt Programming and Few-Shot Tasks

在我们之前的所有任务中,我们都是使用已标记的数据集训练神经网络来执行特定任务。在 BERT 等大型转换器模型中,我们以自我监督的方式使用语言模型来构建语言模型,然后通过进一步的特定领域训练将其专门用于特定的下游任务。不过,事实证明,大型语言模型也可以在没有特定领域训练的情况下解决许多任务。

能够做到这一点的模型系列被称为 GPT(Generative Pre-Trained Transformer,生成式预训练转换器)。



文本生成与困惑度

《Language Models are Unsupervised Multitask Learners》论文中提出,神经网络无需下游训练即可完成一般任务。其主要思想是,许多其他任务都可以通过文本生成来建模,因为理解文本本质上就意味着能够生成文本。由于模型是在包含人类知识的大量文本中训练出来的,因此它会对各种主题有所了解。



GPT是一个大家族

GPT 不是一个单一的模型,而是由 OpenAI 开发和训练的一系列模型的集合。

GPT-2 GPT-3 GPT-4
语言模型参数多达 15 亿 语言模型参数多大 1750 亿 100 兆参数,接受图像和文本输入,并输入文本


提示工程

Prompt Engineering

由于 GPT 经过大量数据的训练,能够理解语言和代码,因此它们会根据输入(提示)提供输出。提示是 GPT 的输入或查询,通过输入或查询,人们可以向模型提供下一步完成任务的指令。要获得理想的结果,你需要最有效的提示,这涉及到正确的单词、格式、短语甚至是符号。这种方法就是提示工程。




其他AI技术

包括:

  • 遗传算法(Genetic Algorithms)
  • 深度强化学习(Deep Reinforcement Learning)
  • 多代理系统(Multi-Agent Systems)