「PyTorch自然语言处理系列」1. 基础知识介绍(上)

来源 |  Natural Language Processing with PyTorch

作者 | Rao,McMahan

译者 | Liangchu

校对 | gongyouliu

编辑 | auroral-L

全文共5208字,预计阅读时间35分钟。

第一章  基础知识简介(上)

 

1.  监督学习范式

2.  观测和目标编码

    2.1  独热表示

    2.2  TF 表示

    2.3  TF-IDF 表示

    2.4  目标编码

3.  计算图

像 Echo (Alexa)、Siri 和Google Translate这样著名的产品至少有一个共同点——它们都是自然语言处理(natural language processing,NLP)应用的产物,而NLP也是本书两大主题之一。NLP 是一套运用统计方法的技术,它可能利用也可能不用语言学的洞见,为了解决现实世界的任务而理解文本。所谓文本的“理解”主要就是把文本转换为可用的计算表示(representation),它们是离散的或者连续的组合结构,比如向量(vector)、张量(tensor)、图形(graph)和树(tree)。

从数据(本例中为文本)中学习适合于任务的表示是机器学习(machine learning)的主题。机器学习被应用于文本数据已有超过三十年的历史,但最近十年有一种叫深度学习(deep learning)的机器学习技术正在不断发展,并被证实了在NLP、语音技术和计算机视觉的人工智能(artificial intelligence,AI)任务中的有效性。深度学习就是本书的另一大主题。因此,本书是关于NLP和深度学习的研究。

简而言之,深度学习允许人们使用一种称为计算图(computational graph)和数值优化(numerical optimization)技术的抽象概念有效地从数据中学习表示。这就是深度学习和计算图的成功之处,像Google、Facebook 和 Amazon 这样的主流科技公司已经发布了基于它们的计算图框架和库的实现,以启发研究人员和工程师的思维。在本书中,我们考虑使用PyTorch来实现深度学习算法,PyTorch是一个越来越流行的基于 Python 的计算图框架库。在本章中,我们将解释什么是计算图,以及选择使用 PyTorch 作为框架的原因。

机器学习和深度学习的研究领域很广泛。在本章中以及本书的大部分时间里,我们主要考虑所谓的监督学习(supervised learning),也即使用带标签的训练示例进行学习。我们会解释监督学习范式,这也是本书的基础。如果到目前为止你还不熟悉多数术语,那你就选对了书。在这一章以及未来的章节中,我不仅会解释这些术语,而且会对其进行深入研究。倘若你已熟悉其中部分术语和概念,我仍然建议你按顺序读下去,原因有二:为本书其余部分建立一个共享的词汇表;补充理解未来章节所需的知识。

本章的目标是:

• 对监督学习范式有一个清晰理解、理解术语并建立一个概念框架来处理未来章节的学习任务;

• 学习如何编码学习任务的输入;

• 理解什么是计算图;

• 掌握 PyTorch 的基本知识。

让我们开始吧!

1. 监督学习范式

机器学习中的监督——也即监督学习,是指将目标(target,被预测的内容)的真实情况用于观测(observation,也即输入)的情况。例如,在文档分类中,目标是一个分类标签,观测是一个文档。又比如,在机器翻译中,观测是一种语言表述的句子,目标是另一种语言表述的句子。通过对输入数据的理解,下图(1-1)是监督学习范式的演示:

 

 

我们可以将监督学习范式分解,如上图(1-1)所示,可以分解为六个主要概念:

• 观测(observation)

 观测与我们想要预测的东西相关,我们用x表示观测值。我们有时把观测值称为输入(input)。

• 目标(target)

 目标是与观测相对应的标签,它通常是被预测的东西。按照机器学习/深度学习中的标准符号,我们用y表示它。有时,目标被称为真实情况(ground truth)。

• 模型(model)

 模型是一个数学表达式或函数,它接受一个观测值x,并预测其目标标签的值。

• 参数(parameter)

 有时也称为权重(weight),用于参数化模型。标准使用w或ŵ表示参数。

• 预测(prediction)

 预测,也称为估计(estimate),是模型在给定观测值的情况下所预测目标的值。我们使用hat符号表示它,因此,目标y的预测被表示为ŷ。

• 损失函数(loss function)

 损失函数是比较预测与训练数据中观测目标之间的距离的函数。给定一个目标及其预测,损失函数将分配一个称为损失(loss)的标量实数。损失值越低,模型对目标的预测效果越好。我们用L表示损失函数。

尽管在NLP/深度学习建模或编写本书时,严格来讲并不需要数学上的形式化,但我们将正式重述监督学习范式,为该领域的新读者们提供标准术语,以便熟悉arXiv研究论文中的符号和写作风格。

考虑一个数据集有n个例子:

 

给定该数据集,我们想学习一个由权值w参数化的函数(模型)f,也就是说,我们假设f的结构,给定这个结构,权值w的学习值将充分表征模型。对于给定输入X,模型预测ŷ为目标:

 

在监督学习中,对于训练示例,我们知道一个观察的真正目标是y,所以该示例的损失将为L(y, ŷ)。因此监督学习就变成了一个寻找最优参数/权值w从而使得所有n个例子的累积损失最小化的过程。


使用(随机)梯度下降法进行训练 

监督学习的目标是为给定的数据集找到参数值,从而使损失函数最小。换句话说,这与解方程求根一个意思。我们知道梯度下降(gradient descent)是一种常见的用于求方程根的方法。回想一下,在传统的梯度下降法中,我们给根(参数)赋一个猜测的值作为初值并迭代更新这些参数,直到计算得到目标函数(损失函数)的值小于某个可接受的阈值(也即收敛准则)。对于大型数据集来说,由于内存受限,几乎不可能在整个数据集上实现传统的梯度下降法,再者由于计算开销,迭代的速度也非常慢。作为传统梯度下降法的替代,我们通常使用一种称为随机梯度下降(stochastic gradient descent,SGD)的方法作为梯度下降的近似。在随机情况下,某个数据点或数据点的子集是随机选择的,并计算该子集的梯度。当使用单个数据点时,该方法称为纯 SGD(pure SGD),当使用一个或多个数据点的子集时,我们将之称为小型批量 SGD(minibatch SGD)。通常pure和minibatch这两个词在上下文清晰的情况下会舍去不写。在实际应用中,我们很少使用纯 SGD,因为它会由于有噪声的更新而导致收敛非常慢。一般的SGD 算法有各种不同的变体,都是为了更快的收敛。在后面的章节中,我们将探讨某些变体,以及梯度在参数更新过程中的作用。这种迭代更新参数的过程称为反向传播(backpropagation)。反向传播的每个步骤(又名周期(epoch))由前向传递(forward pass)和反向传递(backward pass)组成。前向传递用参数的当前值计算输入并计算损失函数,反向传递使用损失梯度来更新参数。


注意到目前为止,这里讨论的东西并不是针对于深度学习或神经网络的。上图(1-1)中箭头的方向指示系统的训练过程中的数据“流”。我们还会探讨更多关于训练和“计算图”一节中“流”的概念,但首先我们得先看看如何使用数字表示NLP问题中输入的目标,以便训练模型和预测结果。

2. 观测和目标编码

我们将要用数字表示观测值(文本),以便与机器学习算法结合使用。下图(1-2)给出了一个可视化的描述:

 

 

表示文本的一种简单方法是使用数值向量(numerical vector)。有无数种方法可以执行这种映射/表示。事实上,本书的大部分内容都致力于从数据中学习此类任务表示,我们将从基于启发式的一些简单的基于计数的表示开始,这种表示虽然简单,但是它们非常强大,可以作为更丰富的表示学习的起点。所有这些基于计数的表示都是从一个固定维度的向量开始的。

2.1 独热表示

顾名思义,独热表示(one-hot)从一个零向量开始,如果单词出现在句子或文档中,则将向量中的相应条目设为 1。考虑下面两句话:

Time flies like an arrow.

Fruit flies like a banana.

对该句子进行分词,忽略标点符号,全部以小写形式表示,这样就能得到得到一个大小为 8 的字典:{time, fruit, flies, like, a, an, arrow, banana}。因此我们可以用一个八维独热向量来表示每个单词。在本书中,我们使用表示单词w的独热表示。

对于短语、句子或文档,折叠的独热表示仅仅是其组成词的逻辑“或(OR)”的独热表示。使用下图(1-3)所示的编码,短语like a banana的独热表示是一个3×8的矩阵,其中列是 8 维独热向量。通常我们还会看到“折叠(collapsed)”或二进制编码,其中文本/短语由长度为字典长度的向量表示,使用 0 和 1 分别表示单词的缺失或存在。like a banana的二进制编码是:[0,0,0,1,1,0,0,1]。

 

注意

在这一点上,如果你觉得我们把flies的两种不同的意思搞混了,那么恭喜!你真是个聪明的读者!语言充满了歧义,但是我们仍然可以通过极其简化的假设来构建有用的解决方案。学习特定意义的表示也不是不可能,但是对现在的我们来说有些超前了。

尽管在本书中,我们很少使用除了独热表示之外的其他表示用于表示输入,但由于表示在NLP中的受欢迎程度、历史原因以及完成目的,我们现在还将介绍词频(Term-Frequency ,TF)和词频逆向文档频率(Term-Frequency-Inverse-Document-Frequency,TF-IDF)表示。这些表示在信息检索(information retrieval,IR)中历史悠久,甚至在今天的NLP 生产系统中也有广泛的应用。

2.2 TF表示

短语、句子或文档的TF表示仅是构成词的独热表示总和。为了继续我们简单的示例,使用前面提到的独热编码,Fruit flies like time flies a fruit具有以下 TF 表示:[1,2,2,1,1,1,0,0]。注意,每个条目是句子(语料库)中出现相应单词的次数的总计。我们用TF(w)表示一个单词的词频TF。

示例1-1:使用scikit-learn生成“折叠”独热或二进制表示

from sklearn.feature_extraction.text import CountVectorizer
import seaborn as sns


corpus = ['Time flies flies like an arrow.',
          'Fruit flies like a banana.']
one_hot_vectorizer = CountVectorizer(binary=True)
one_hot = one_hot_vectorizer.fit_transform(corpus).toarray()
sns.heatmap(one_hot, annot=True,
            cbar=False, xticklabels=vocab,
            yticklabels=['Sentence 1', 'Sentence 2'])


2.3 TF-IDF表示

考虑一组专利文件,你可能希望它们中的大多数都包含比如claim、system、method、procedure等单词,并且经常出现。TF表示使得单词的权重与其频率成比例。然而,像claim这样的常用词并不能使我们更理解具体某篇专利。相反,像tetrafluoroethylene这样罕见的词出现的频率更低,但却很可能表明专利文件的性质,所以我们希望在表示中赋予其更大的权重。逆向文档频率(Inverse-Document-Frequency,IDF)是一种启发式方法,可以精确达到该目的。

IDF 表示惩罚常见的单词,并奖励向量表示中的罕见单词。单词w的IDF(w)对语料库的定义为:

 

其中是包含单词w的文档数量,N是文档总数。TF-IDF值就是TF(w) * IDF(w)的乘积。首先,注意到在所有文档(例如,)中出现了非常常见的单词, IDF(w)为 0,TF-IDF值为 0,因此能完全惩罚这一项。其次,如果一个术语很少出现,甚至可能只在一个文档中出现,那么 IDF 就是可能的最大值log N。下例(1-2)展示如何使用scikit-learn生成一列英文句子的TF-IDF表示:

示例 1-2:使用 scikit-learn生成TF-IDF 表示

from sklearn.feature_extraction.text import TfidfVectorizer
import seaborn as sns


tfidf_vectorizer = TfidfVectorizer()
tfidf = tfidf_vectorizer.fit_transform(corpus).toarray()
sns.heatmap(tfidf, annot=True, cbar=False, xticklabels=vocab,
            yticklabels= ['Sentence 1', 'Sentence 2'])

 

在深度学习中,因为目标是学习一种表示,所以很少看到使用像 TF-IDF 这样的启发式表示对输入进行编码。通常,我们从一个使用整数索引的独热编码和一个特殊的“嵌入查找”(embedding lookup)层开始构建神经网络的输入。我们会在后面的章节中给出几个像这样做的例子。

2.4 目标编码

正如“监督学习范式”一节所指出的,目标变量的确切性取决于所要解决的 NLP 任务。例如,在机器翻译(machine translation)、文本摘要(summarization)和问答(question answering)任务中,目标也是文本,并使用前面描述的独热编码方法进行编码。

许多 NLP 任务实际上使用分类标签,这种任务的模型必须预测一组固定标签中的一个。对此进行编码的一种常用方法是对每个标签使用唯一索引,然而当输出标签的数量太大时,这种简单的表示就很有问题了。其中一个例子是语言建模(language modeling)问题,在这个问题中,任务是根据过往给出单词来预测下一个单词,标签空间是某语言的全部词汇,因而很容易增长到好几十万,包括特殊字符和名字等等。我们将在后面的章节中重新思考这个问题,看看如何解决它。

一些 NLP 问题涉及从某给定文本中预测一个数值。例如,给定一篇英语短文,我们可能需要给其分配一个数字分数或可读的评分。给定一个餐馆评论片段,我们可能需要预测直到小数点后一位的星级。给定某用户的推文,我们可能需要预测用户的年龄群。有几种方法可用于对数字目标进行编码,但它们只是将目标简单地放在了到分类“容器”中(例如,“0-18”、“19-25”、“25-30”等等),而且将其视为有序分类问题是一种合理的方法。这种绑定可以是均匀的,也可以是非均匀和数据驱动的。虽然这一点的详细内容并不在本书的讨论范围之内,但是我们还是得提醒你注意这些问题,因为在这种情况下,目标编码会显著影响性能,我们建议你参阅 Dougherty 等人(1995)及其引用。

3. 计算图

图1-1将监督学习(训练)范式概括为一个数据流架构,模型(一个数学表达式)将输入转换以获得预测,损失函数(另一个表达式)提供反馈信号来调整模型的参数。可以使用计算图(computational graph)数据结构来方便地实现该数据流。从技术上来说,计算图是对数学表达式建模的抽象。在深度学习的上下文中,计算图的实现(如 Theano、TensorFlow 和 PyTorch)进行了额外的簿记(bookkeeping),以实现在监督学习范式中训练期间获取参数梯度所需的自动微分。我们会在“PyTorch基础”一节中进一步探讨这一点。推理(或预测)简单来说就是表达式求值(计算图上的前向流)。让我们看看计算图如何进行表达式建模。考虑表达式:

 

该表达式可以写成两个子表达式z = wx和y = z + b,接着我们可以用一个有向无环图(directed acyclic graph,DAG)表示原表达式,其中节点是乘法和加法等数学运算。操作的输入是节点的传入边,操作的输出是传出边。因此,对于表达式y = wx + b,计算图如下图(1-6)所示:

 

 

在下一节中,我们将看到 PyTorch 如何让我们以一种直观的方式创建计算图,以及它如何在无需考虑任何bookkeeping的情况下允许我们计算梯度。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据与智能

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值