word2vec和词嵌入-《动手学深度学习pytorch》

1基础

背景:

1. 统计语言模型 2. N-gram模型  

3. 从one-hot vector到dense vector:稠密向量各维度值是实数,不限于0和1,可以表示连续空间,可以通过计算距离度量词与词之间的相似度

4. 分布表示与cooccurence矩阵

示一个词的意义,上下文环境相似的两个词有着相近的语义,词对描述词之间的关系(cooccurence矩阵进行SVD降维表示。

5. NNLM

鉴于N-gram等模型的不足,统计语言模型的框架NNLM(Neural Network Language Model)。它是一个词嵌入+前馈神经网络,通过前n-1个词来预测第n个词的概率。

(参考https://www.jianshu.com/p/22d35745cfd7
 

one-hot 词向量无法准确表达不同词之间的相似度,如我们常常使用的余弦相似度。因此提出Word2Vec 词嵌入工具,它将每个词表示成一个定长的向量,并通过在语料库上的预训练使得这些向量能较好地表达不同词之间的相似和类比关系,
 

PTB (Penn Tree Bank) 是一个常用的小型语料库,它采样自《华尔街日报》的文章,包括训练集、验证集和测试集。我们将在PTB训练集上训练词嵌入模型。

### 建立词语索引
counter = collections.Counter([tk for st in raw_dataset for tk in st]) # tk是token的缩写 raw_dataset是数据
counter = dict(filter(lambda x: x[1] >= 5, counter.items())) # 只保留在数据集中至少出现5次的词

idx_to_token = [tk for tk, _ in counter.items()]
token_to_idx = {tk: idx for idx, tk in enumerate(idx_to_token)}
dataset = [[token_to_idx[tk] for tk in st if tk in token_to_idx]
           for st in raw_dataset] # raw_dataset中的单词在这一步被转换为对应的idx
num_tokens = sum([len(st) for st in dataset])
'# tokens: %d' % num_tokens

二次采样

数据集中每个被索引词 wi 将有一定概率被丢弃, f(wi)是数据集中词 wi的个数与总词数之比,越高频的词被丢弃的概率p越大

def discard(idx):
    #return: True/False 表示是否丢弃该单词
    return random.uniform(0, 1) < 1 - math.sqrt( 1e-4 / counter[idx_to_token[idx]] * num_tokens)

subsampled_dataset = [[tk for tk in st if not discard(tk)] for st in dataset]

提取中心词和背景词

def get_centers_and_contexts(dataset, max_window_size):
    centers, contexts = [], []
    for st in dataset:
        if len(st) < 2:  # 每个句子至少要有2个词才可能组成一对“中心词-背景词”
            continue
        centers += st
        for center_i in range(len(st)):
            window_size = random.randint(1, max_window_size) # 随机选取背景词窗大小
            indices = list(range(max(0, center_i - window_size),
                                 min(len(st), center_i + 1 + window_size)))
            indices.remove(center_i)  # 将中心词排除在背景词之外
            contexts.append([st[idx] for idx in indices])
    return centers, contexts

 2两种模型

word2vec采用一个简单的浅层神经网络来进行训练得到词向量(word embedding),这个向量是低维的、稠密的。

Skip-Gram模型:给定输入词来预测上下文
CBOW模型:给定上下文来预测输入词

Skip-gram模型:

本质是计算输入word的input vector与目标word的output vector之间的余弦相似度,并进行softmax归一化。我们要学习的模型参数正是这两类词向量.

CBOW模型:

忽略上下文环境的序列信息:接将中间层的embedding layer与输出层的softmax layer连接。

输入的所有词向量均汇总到同一个embedding layer;(3)将future words纳入上下文环境。得到CBoW模型,

Skip-Gram模型


(1) 训练目标
skip-gram通过中心词来推断临近词的出现概率,所以模型的训练目标是提高预测的准确率。需要记住的是,一旦模型训练完成,有用的只是隐藏层的矩阵(也叫lookup-table),用作概率预测的输出层将不再使用

(注: 另一种更简单的理解角度为,每个词对应两个向量: 作为中心词时Vc和作为临近词时Uo. 训练的目标是求出每个词的u和v向量)

(2) 训练集
在训练的语料中,对于每个中心词,设置一个window size(如下图中设置为2),来限定临近词的选择范围。从限定的临近词中,随机选择其中一个作为要预测的词语,于是得到训练词对(中心词, 临近词),分别用于模型的输入、输出。对词进行one-hot编码之后,得到向量(x, y)放入训练集合。

(3) forward pass过程

word2vec移除了激活层,采用了两次线性变换(U, V)和一次softmax的过程,如下图。
假设x, y表示one-hot输入向量,且x,y中1的索引分别为c, o,则forward pass的过程为:

(4) backworad pass过程
采用SGD进行参数更新,由链式法则对中心词向量vc和临近词uo可以进行求导

(5) 训练结果
上述训练得到的vc便是索引为c的词的词向量。V称为lookup-table。
这是skip-gram的基本模型,它依然存在着参数空间巨大的问题,即U和V的大小与词典大小成正比。

(参考https://www.jianshu.com/p/5b2fcc106518

#Skip-Gram 模型的前向计算
def skip_gram(center, contexts_and_negatives, embed_v, embed_u):
    v = embed_v(center) # shape of (n, 1, d)
    u = embed_u(contexts_and_negatives) # shape of (n, m, d)
    pred = torch.bmm(v, u.permute(0, 2, 1)) # bmm((n, 1, d), (n, d, m)) => shape of (n, 1, m)
    return pred

3优化算法

权重参数很多,需要大量的训练数据来调整这些权重并且避免过拟合,词汇量*维度

Word2Vec 作者在第二篇论文中的三个创新:

  1. 将常见的单词组合(word pairs)或者词组作为单个“words”来处理。
  2. 对高频次单词进行抽样来减少训练样本的个数。
  3. 对优化目标采用负采样方法,这样每个训练样本的训练只会更新一小部分的模型权重,降低计算负担。

直接对词典里的V个词计算相似度并归一化,显然极其耗时。为此,Mikolov引入了两种优化算法:层次Softmax(Hierarchical Softmax)和负采样(Negative Sampling),常见的组合为 skip-gram+负采样方法

1层次Softmax

输出层从原始模型的利用softmax计算概率值改为了利用Huffman树计算概率值。一开始我们可以用以词表中的全部词作为叶子节点,词频作为节点的权,构建Huffman树,作为输出.利用从根节点出发,到达指定叶子节点的路径来计算指定词的概率,而非用softmax来计算。

2负采样

负采样每次让一个训练样本仅仅更新一小部分的权重,这样就会降低梯度下降过程中的计算量。

4词嵌入进阶

  1. 子词嵌入(subword embedding):FastText 以固定大小的 n-gram 形式将单词更细致地表示为了子词的集合,而 BPE (byte pair encoding) 算法则能根据语料库的统计信息,自动且动态地生成高频子词的集合;
  2. GloVe 全局向量的词嵌入: 通过等价转换 Word2Vec 模型的条件概率公式,我们可以得到一个全局的损失函数表达,并在此基础上进一步优化模型。

常常在大规模的语料上训练这些词嵌入模型,并将预训练得到的词向量应用到下游的自然语言处理任务中。

glove = vocab.GloVe(name='6B', dim=50, cache=cache_dir) #加载预训练好的 GloVe 词向量

求近义词

get_similar_tokens('chip', 3, glove)可以通过寻找空间中的 k 近邻,来查询单词的近义词。

求类比词

除了求近义词以外,我们还可以使用预训练词向量求词与词之间的类比关系,例如“man”之于“woman”相当于“son”之于“daughter”vec(𝑐)+vec(𝑏)−vec(𝑎)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值