自然语言处理中的词嵌入模型:Skip-gram、CBOW与GloVe
立即解锁
发布时间: 2025-09-03 01:50:08 阅读量: 4 订阅数: 11 AIGC 

# 自然语言处理中的词嵌入模型:Skip - gram、CBOW与GloVe
## 1. Skip - gram模型训练与原理
### 1.1 训练思路
要训练Skip - gram模型并学习所需的词嵌入,关键是将其转化为一个分类任务,即模型预测目标词上下文中出现的词。这里的“上下文”指以目标词(如“dog”)为中心的固定大小窗口(例如左右各5个词)。当窗口大小为2时,示例如下:
```plaintext
I heard a dog barking in the distance.
```
其中“dog”是目标词,“heard”“a”“barking”“in”是上下文词。这实际上是一个“伪任务”,我们并非关注模型的预测结果本身,而是训练模型过程中产生的副产品——词嵌入。这种训练标签从给定数据集中自动创建的机器学习设置,也被称为自监督学习,近期流行的词嵌入和语言建模技术都采用了自监督学习。
### 1.2 神经网络分类任务的实现
要让神经网络解决分类任务,需要完成以下两件事:
- 修改网络,使其产生概率分布。可以使用softmax函数来实现这一点。softmax函数将一个包含K个浮点数的向量转换为概率分布,它先将这些数字“压缩”到0.0 - 1.0的范围内,然后进行归一化处理,使它们的总和等于1。如果对概率概念不熟悉,可以将其替换为置信度。概率分布是网络对各个预测(这里是上下文词)所赋予的一组置信度值。softmax函数在处理过程中会保留输入浮点数的相对顺序,因此输入的较大数字在输出分布中仍具有较大的概率值。概念图如下:
```mermaid
graph LR
A[Scores: A, B, C, D, ...] --> B[Softmax]
B --> C[Probability distribution: A, B, C, D, ...]
```
- 使用交叉熵作为损失函数。交叉熵是用于衡量两个概率分布之间距离的损失函数。如果两个分布完全匹配,它返回零;如果两个分布有差异,则返回更高的值。对于分类任务,我们使用交叉熵来比较以下两个分布:
- 神经网络产生的预测概率分布(softmax的输出)。
- 目标概率分布,其中正确类别的概率为1.0,其他所有类别的概率为0.0。
随着Skip - gram模型的预测结果越来越接近实际的上下文词,词嵌入也同时被学习到。
## 2. 在AllenNLP中实现Skip - gram模型
### 2.1 数据集读取
可以使用AllenNLP将Skip - gram模型转化为可运行的代码。首先需要实现一个数据集读取器,它可以读取纯文本语料库,并将其转换为Skip - gram模型可以处理的实例集。可以克隆代码仓库并导入读取器:
```python
from examples.embeddings.word2vec import SkipGramReader
reader = SkipGramReader()
text8 = reader.read('https:/./realworldnlpbook.s3.amazonaws.com/data/text8/text8')
```
### 2.2 导入必要模块和定义常量
```python
from collections import Counter
import torch
import torch.optim as optim
from allennlp.data.data_loaders import SimpleDataLoader
from allennlp.data.vocabulary import Vocabulary
from allennlp.models import Model
from allennlp.modules.token_embedders import Embedding
from allennlp.training.trainer import GradientDescentTrainer
from torch.nn import CosineSimilarity
from torch.nn import functional
EMBEDDING_DIM = 256
BATCH_SIZE = 256
```
这里使用text8数据集,它是维基百科的一个摘录,常用于训练简单的词嵌入和语言模型。可以遍历数据集中的实例,`token_in`是模型的输入令牌,`token_out`是输出(上下文词):
```python
for inst in text8:
print(inst)
```
### 2.3 构建词汇表和数据加载器
```python
vocab = Vocabulary.from_instances(
text8, min_count={'token_in': 5, 'token_out': 5})
data_loader = SimpleDataLoader(text8, batch_size=BATCH_SIZE)
data_loader.index_with(vocab)
```
### 2.4 定义嵌入对象
```python
embedding_in = Embedding(num_embeddings=vocab.get_vocab_size('token_in'),
embedding_dim=EMBEDDING_DIM)
```
`EMBEDDING_DIM`是每个词向量的长度,典型的NLP应用使用几百维的词向量(这里是256维),但该值很大程度上取决于任务和数据集。通常建议随着训练数据的增加,使用更长的词向量。
### 2.5 实现Skip - gram模型
```python
class SkipGramModel(Model):
def __init__(self, vocab, embedding_in):
super().__init__(vocab)
self.embedding_in = embedding_in
self.linear = torch.nn.Linear(
in_features=EMBEDDING_DIM,
out_features=vocab.get_vocab_size('token_out'),
bias=False)
def forward(self, token_in, token_out):
embedded_in = self.embedding_in(token_in)
logits = self.linear(embedded_in)
loss = functional.cross_entropy(logits, token_out)
return {'loss': loss}
```
### 2.6 训练模型
```python
reader = SkipGramReader()
text8 = reader.read(' https:/./realworldnlpbook.s3.amazonaws.com/data/text8/text8')
vocab = Vocabulary.from_instances(
text8, min_count={
```
0
0
复制全文
相关推荐









