【NLP入门】一文搞懂 Word2Vec 词向量化技术(★小白必会版★)

【NLP入门】一文搞懂 Word2Vec 词向量化技术(★小白必会版★)


🌟 嗨,我是 青松 !很高兴认识你 😄

🌈 自小刺头深草里,而今渐觉出蓬蒿。



为更好地展示关键内容,本文将以QA形式探讨了以下问题:

  • 词向量化概述
    • 什么是词向量化技术?
    • 怎么理解单词的分布式假设?
    • 单词含义的表示方法有哪些?
  • 词向量化方法
    • 基于计数的表示方法
      • 如何基于计数的方法表示文本?
      • 基于计数的表示方法存在哪些问题?
    • 基于推理的表示方法
      • 如何基于推理的方法表示文本?
      • word2vec的两种模型分别是什么?
      • word2vec的两种优化方法是什么?
      • word2vec的词向量存在哪些问题?

💯 什么是词向量化技术?

自然语言处理的目标就是让计算机理解人说的话,进而完成对我们有帮助的事情。我们的语言是由文字构成的,而语言的含义是由单词构成的。因此,为了让计算机理解自然语言,让它理解单词含义可以说是最重要的事情了。

在自然语言处理任务中,词向量化(Word Embedding)是表示自然语言里单词的一种方法,即把每个词都表示为一个N维空间内的点,即一个高维空间内的向量。通过这种方法,实现把自然语言计算转换为向量计算。

图1 所示的词向量计算任务中,先把每个词(如queen,king等)转换成一个高维空间的向量,这些向量在一定意义上可以代表这个词的语义信息。再通过计算这些向量之间的距离,就可以计算出词语之间的关联关系,从而达到让计算机像计算数值一样去计算自然语言的目的。

image.png

图1:词向量计算示意图

因此,大部分词向量模型都需要回答两个问题:

  1. 如何把词转换为向量?
    自然语言单词是离散信号,比如“香蕉”,“橘子”,“水果”在我们看来就是3个离散的词。
    如何把每个离散的单词转换为一个向量?

  2. 如何让向量具有语义信息?
    比如,我们知道在很多情况下,“香蕉”和“橘子”更加相似,而“香蕉”和“句子”就没有那么相似,同时“香蕉”和“食物”、“水果”的相似程度可能介于“橘子”和“句子”之间。
    那么,我们该如何让词向量具备这样的语义信息?

如何把词转换为向量?

自然语言单词是离散信号,比如“我”、“ 爱”、“人工智能”。如何把每个离散的单词转换为一个向量?通常情况下,我们可以维护一个如 图2 所示的查询表。表中每一行都存储了一个特定词语的向量值,每一列的第一个元素都代表着这个词本身,以便于我们进行词和向量的映射(如“我”对应的向量值为 [0.3,0.5,0.7,0.9,-0.2,0.03] )。给定任何一个或者一组单词,我们都可以通过查询这个excel,实现把单词转换为向量的目的,这个查询和替换过程称之为Embedding Lookup。


图2:词向量查询表

上述过程也可以使用一个字典数据结构实现。事实上如果不考虑计算效率,使用字典实现上述功能是个不错的选择。然而在进行神经网络计算的过程中,需要大量的算力,常常要借助特定硬件(如GPU)满足训练速度的需求。GPU上所支持的计算都是以张量(Tensor)为单位展开的,因此在实际场景中,我们需要把Embedding Lookup的过程转换为张量计算,如 图3 所示。


图3:张量计算示意图

如何让向量具有语义信息?

得到每个单词的向量表示后,我们需要思考下一个问题:比如在多数情况下,“香蕉”和“橘子”更加相似,而“香蕉”和“句子”就没有那么相似;同时,“香蕉”和“食物”、“水果”的相似程度可能介于“橘子”和“句子”之间。那么如何让存储的词向量具备这样的语义信息呢?

我们先学习自然语言处理领域的一个小技巧。在自然语言处理研究中,科研人员通常有一个共识:使用一个单词的上下文来了解这个单词的语义,比如:

“苹果手机质量不错,就是价格有点贵。”
“这个苹果很好吃,非常脆。”
“菠萝质量也还行,但是不如苹果支持的APP多。”

在上面的句子中,我们通过上下文可以推断出第一个“苹果”指的是苹果手机,第二个“苹果”指的是水果苹果,而第三个“菠萝”指的应该也是一个手机。事实上,在自然语言处理领域,使用上下文描述一个词语或者元素的语义是一个常见且有效的做法,可以让这些词向量具备表示语义信息的能力。

💯 怎么理解单词的分布式假设?

“某个单词的含义由它周围的单词形成”,称为分布式假设(distributional hypothesis)。

分布式假设所表达的理念非常简单。单词本身没有含义,单词含义由它所在的上下文(语境)形成。的确,含义相同的单词经常出现在相同的语境中。

💯 单词含义的表示方法有哪些?

常见的基于上下文的单词嵌入表示方法,有以下两类:

  • 基于计数的方法
  • 基于推理的方法

💯 如何基于计数的方法表示文本?

基于分布式假设使用向量表示单词,最直截了当的实现方法是对周围单词的数量进行计数。具体来说,在关注某个单词的情况下,对它的周围出现了多少次什么单词进行计数,然后再汇总,汇总后所得的矩阵称之为共现矩阵。我们将这种做法称为“基于计数的表示方法”。

窗口大小

上下文是指某个居中单词的周围词汇。这里,我们将上下文的大小(即周围的单词有多少个)称为窗口大小(window size)。窗口大小为1,上下文包含左右各1个单词;窗口大小为2,上下文包含左右各2个单词。

Pasted image 20231023222244
窗口大小为2的上下文例子。在关注goodbye时,将其左右各2个单词用作上下文

共现矩阵

窗口大小为1,句子’You say goodbye and I say hello.’ 的共现矩阵统计过程如下:

统计单词you的下文共现的单词的频数:

Pasted image 20231023223010
单词you的上下文

Pasted image 20231023223117
单词you的上下文中包含的单词的频数,这也意味着可以用向量[0, 1, 0, 0, 0, 0, 0]表示单词you

**统计单词say的下文共现的单词的频数:

Pasted image 20231023223307
单词say的上下文中包含的单词的频数,单词say可以表示为向量[1, 0, 1, 0, 1, 1, 0]

对所有的单词进行上述操作,将会得到如下的共现矩阵:

Pasted image 20231023223521

💯 基于计数的表示方法存在哪些问题?

  1. 存在维度爆炸问题,会造成极高的算力成本。在现实世界中,语料库处理的单词数量非常大。比如,据说英文的词汇量超过100万个。如果词汇量超过100万个,那么使用基于计数的方法就需要生成一个100万×100万的庞大矩阵。
  2. 无法增量学习。基于计数的方法通过对整个语料库的统计数据进行一次学习来获得单词的分布式表示,考虑需要向词汇表添加新词并更新单词的分布式表示的场景。此时,基于计数的方法需要从头开始计算。
  3. 基于计数的方法主要是编码单词的相似性,不能理解更复杂的单词之间的模式。

💯 如何基于推理的方法表示文本?

基于推理的方法的主要操作是“推理”。如下图所示,当给出周围的单词(上下文)时,预测“?”处会出现什么单词,这就是推理。 基于推理的方法使用了推理机制。当然,这里的推理机制用的是神经网络。

Pasted image 20231106104416
基于两边的单词(上下文),预测“?”处出现什么单词

基于推理的方法引入了某种模型。这个模型接收上下文信息作为输入,并输出(可能出现的)各个单 词的出现概率。在这样的框架中,使用语料库来学习模型,使之能做出正确的预测。作为模型学习的副产品,我们得到了单词的分布式表示。这就是基于推理的方法的全貌。

Pasted image 20231106104804

基于推理的方法和基于计数的方法一样,也基于分布式假设。分布式假设假设“单词含义由其周围的单词构成”。

💯 word2vec的两种模型分别是什么?

Word2vec 可以根据给定的语料库,通过优化后的训练模型快速有效地将一个词语表达成向量形式,为自然语言处理领域的应用研究提供了新的工具。Google 公司在 2013年开放了 Word2vec这一款用于训练词向量的软件工具。

Word2vec 有两个模型:CBOW 模型和 skip-gram 的模型。

  • CBOW 模型从上下文的多个单词预测中间的单词(目标词)
  • skip-gram 模型则从中间的单词(目标词)预测周围的多个单词(上下文)

CBOW模型和skip-gram模型要处理的问题,如图所示:

Pasted image 20231106151007

CBOW模型

CBOW 模型是根据上下文预测目标词的神经网络(“目标词”是指中间的单词,它周围的单词是“上下文”)。通过训练这个 CBOW 模型,使其能尽可能地进行正确的预测,我们可以获得单词的分布式表示。

Pasted image 20231106162332
word2vec的CBOW模型:从上下文的单词预测目标词

CBOW模型的网络结构如下:
Pasted image 20231106154758

CBOW 模型的输入是上下文。这个上下文用 [‘you’, ‘goodbye’] 这样的单词列表表示,输入经过中间层后到达输出层。从输入层到中间层的变换由相同的全连接层(权重为W_in)完成, 从中间层到输出层神经元的变换由另一个全连接层(权重为W_out)完成。

  1. 这里我们对上下文仅考虑两个单词,所以输入层有两个。 如果对上下文考虑 N 个单词,则输入层会有 N 个。
  2. 中间层的神经元是各个输 入层经全连接层变换后得到的值的“平均”。
  3. 输出层的神经元是各个单词的得分,它的值越大,说明对应单词的出现概率就越高。得分是指在被解释为概率之前的值, 对这些得分应用 Softmax 函数,就可以得到概率。

Pasted image 20231106162719

以上下文是 you 和 goodbye,正确解标签(神经网络应该预测出的单词)是 say为例。使用CBOW模型的计算流程如下(节点值的大小用灰度表示) :

Pasted image 20231106160949

如果网络具有“良好的权重”, 那么在表示概率的神经元中,对应正确解的神经元的得分应该更高。CBOW 模型的学习就是调整权重,以使预测准确。如果模型能很好的完成预测推理任务,则权重 W_in(确切地说是 W_in 和 W_out 两者)学习到了蕴含单词出现模式的有效向量。

Pasted image 20231106161523
输入侧和输出侧的权重都可以被视为单词的分布式表示

输入侧和输出侧权重作为单词的分布式表示有三种选择:

  • A. 只使用输入侧的权重
  • B. 只使用输出侧的权重
  • C. 同时使用两个权重

CBOW模型只是学习语料库中单词的出现模式。如果语料库不一样,学习到的单词的分布式表示也不一样。

skip-gram模型

skip-gram 是反转了 CBOW 模型处理的上下文和目标词的模型。skip-gram 模型则从中间的单词(目标词)预测周围的多个单词 (上下文)。

Pasted image 20231106165042

skip-gram 模型的网络结构如图所示:
Pasted image 20231106164758

skip-gram 模型的输入层只有一个,输出层的数量则与上下文的单词个数相等。因此,首先要分别求出各个输出层的损失,然后将它们加起来作为最后的损失。

💯 哪个模型的单词分布式表示更好?

答案应该是 skip-gram 模型。skip-gram 模型根据一个单词预测其周围的单词,这是一个非常难的问题。相较于 CBOW 模型,skip-gram 模型要解决的是更难的问题。经过这个更难的问题的锻炼,skip-gram 模型能提供更好的单词的分布式表示。

💯 Word2vec训练中存在什么问题?

Word2vec 模型中最大的问题是,随着语料库中处理的词汇量的增加,计算量也随之增加。

假设词汇量有 100 万个,CBOW 模型的中间层神经元有 100 个,此时 word2vec 进行的处理如图所示:

Pasted image 20231107074719
假设词汇量为100万个时的CBOW模型

输入层和输出层存在 100 万个神经元,在以下两个地方的计算会出现瓶颈:

  • 输入层的 one-hot 表示和权重矩阵 W_in 的乘积
  • 中间层和权重矩阵 W_out 的乘积以及 Softmax 层的计算

第 1 个问题与输入层的 one-hot 表示有关。在词汇量有 100 万个的情况下,仅 one-hot 表示本身就需要占用 100 万个元素的内存大小。此外,还需要计算 one-hot 表示和权重矩阵 Win 的乘积,这也要花费大量的计算资源。关于这个问题,通过引入新的 Embedding 层来解决。

第 2 个问题是中间层之后的计算。首先,中间层和权重矩阵 Wout 的乘积需要大量的计算。其次,随着词汇量的增加,Softmax 层的计算量也会增加。关于这些问题,通过引入 Negative Sampling(负采样) 这一新的损失函数来解决。

💯 Word2vec是如何进行优化的?

用 Embedding 层优化输入到中间层的计算

我们来考虑词汇量是 100 万个的情况。假设中间层的神经元个数是 100,则使用one-hot表示的上下文和 W_in 权重的乘积过程如下:

Pasted image 20231107080202

one-hot表示的上下文和 W_in 的权重的乘积,做的无非是将矩阵的某个特定的行取出来。我们可以创建一个从权重参数中抽取“单词 ID 对应行(向量)”的层来替代矩阵计算,可称之为 Embedding 层。这样一来,既能减少内存使用量,又能避免不必要的计算。
**

在Embedding层的反向传播中,如果句子中有相同的词,其梯度需要进行“加法”来合并。

Pasted image 20231107081040

用负采样优化中间层到输出层的计算

以词汇量为 100 万个、中间层的神经元个数为 100 个的 wod2vec(CBOW 模型)为例,word2vec 进行的处理如图所示:

Pasted image 20231107110811
词汇量为100万个时的word2vec:上下文是you和goodbye,目标词是say

词汇量是 100 万个的情况下,模型输出时需要预测所有词(100万个)的概率。此时,在以下两个地方需要很多计算时间:

  • 中间层的神经元和权重矩阵( W o u t W_{out} Wout)的乘积
  • Softmax 层的计算

我们将采用名为负采样(negative sampling) 的方法作为解决方案,使用 Negative Sampling 替代 Softmax,无论词汇量有多大,都可以使计算量保持较低或恒定。

💯 Word2vec的词向量存在哪些问题?

Word2vec是一种常用的词向量生成方法,它通过训练语料库学习单词的上下文关系,从而生成词向量。但是,Word2vec模型训练的词向是静态的,即在给定的语料上库训练完成后,通过查表(Lookup Table)的方式获取词向量,所以Word2vec也存在一些如下问题:

  1. 无法处理多义词:Word2vec无法处理一词多义的情况,每个单词的向量只与其一个固定的含义相关联。
  2. 无法处理新词:如果语料库中没有出现过的单词,Word2vec无法为其生成有效的词向量。
  3. 语料库强相关:Word2vec的训练需要大量的语料库,而且语料库的质量和分布也会影响生成的词向量的质量,实际推理任务中的词汇分布和语料库可能存在偏差。
  4. 存在词汇鸿沟:Word2vec生成的词向量无法动态捕捉推理任务中词汇的上下文。
  5. 丢失位置信息:Word2vec中的上下文是指目标词周围的单词并未考虑词汇的位置顺序。CBOW 是 Continuous Bag-Of-Words 的简称。Bag-Of-Words 是“一袋子单词”的意思,这意味着袋子中单词的顺序被忽视了。
### BERT实现词向量化与文本向量化的方法 #### 方法概述 BERT(Bidirectional Encoder Representations from Transformers)是一种强大的预训练语言模型,能够生成高质量的词向量和文本向量。通过微调或直接使用其隐藏层输出,可以有效捕捉语义信息并用于各种自然语言处理任务。 #### 词向量化过程 在BERT中,每个输入token会被映射为其对应的嵌入表示。具体来说,BERT会将输入序列转换为一系列固定维度的向量[^1]。这些向量可以通过以下方式获得: - **Token Embeddings**: 输入中的每一个单词都会被转化为一个固定的embedding。 - **Positional Encodings**: 添加位置编码以保留顺序信息。 - **Segment Embeddings**: 如果存在多个句子,则标记它们属于哪个部分。 最终得到的是每一层Transformer后的隐状态矩阵 \( H \in R^{T \times D} \),其中\( T \) 是tokens数量,而\( D \) 则是hidden size大小。通常可以选择最后一层作为词语级别的特征表示[^2]。 ```python from transformers import BertTokenizer, BertModel import torch tokenizer = BertTokenizer.from_pretrained('bert-base-chinese') model = BertModel.from_pretrained('bert-base-chinese') text = "我喜欢学习人工智能" encoded_input = tokenizer(text, return_tensors='pt', padding=True, truncation=True) with torch.no_grad(): output = model(**encoded_input) word_embeddings = output.last_hidden_state # 获取最后一个隐藏层的状态 print(word_embeddings.shape) # 输出形状应类似于(batch_size, sequence_length, hidden_dim) ``` 上述代码展示了如何加载预训练好的`bert-base-chinese`模型,并提取给定中文字符串各token的最后一层隐藏态作为词向量。 #### 文本向量化过程 对于整个文档或者较长片段而言,可以直接取特殊分类符 `[CLS]` 对应的位置处的向量当作整体文本表征;然而这种方法可能不够精确因为仅依赖单个点不足以概括全文含义。另一种更优的方式是对所有token的结果求平均值得到全局描述子: \[ \text{Text Vector} = mean(H_{i}) , i=0,...,N-1\] 这里 N 表示实际有效的 token 数目(不包括填充的部分). 另外还有专门针对句间关系建模优化过的本如Sentence-BERT(SBERT), 它通过对偶样本对比学习调整原始BERT内部机制从而更适合做短文本匹配类工作. ```python sentence_embedding = word_embeddings.mean(dim=1).squeeze() print(sentence_embedding.shape) # 应该返回(hidden_dim,) ``` 以上脚本演示了怎样计算一段话的整体表达形式. ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值