《动手学深度学习PyTorch版》打卡_Task7,word2vec,词嵌入进阶

       最近参加了伯禹平台和Datawhale等举办的《动手学深度学习PyTorch版》课程,对word2vec,词嵌入进阶做下笔记。


词嵌入基础

one-hot 词向量无法准确表达不同词之间的相似度,如我们常常使用的余弦相似度,Word2Vec 词嵌入工具的提出正是为了解决上面这个问题,它将每个词表示成一个定长的向量,并通过在语料库上的预训练使得这些向量能较好地表达不同词之间的相似和类比关系,以引入一定的语义信息。基于两种概率模型的假设,我们可以定义两种 Word2Vec 模型:

Skip-Gram 跳字模型:假设背景词由中心词生成,即建模 P(wo∣wc),其中 wc 为中心词,wo 为任一背景词;

Image Name

比如计算由loves (中心词)生成the,man,his,son四个词的概率

CBOW (continuous bag-of-words) 连续词袋模型:假设中心词由背景词生成,即建模 P(wc∣Wo),其中 Wo 为背景词的集合。

Image Name

比如计算由the,man,his,son四个词生成loves (中心词)的概率


建立词语索引:index to token ,token to index

将数据集数字化

二次采样

文本数据中一般会出现一些高频词,如英文中的“the”“a”和“in”。通常来说,在一个背景窗口中,一个词(如“chip”)和较低频词(如“microprocessor”)同时出现比和较高频词(如“the”)同时出现对训练词嵌入模型更有益。因此,训练词嵌入模型时可以对词进行二次采样。 具体来说,数据集中每个被索引词 wi 将有一定概率被丢弃,该丢弃概率为

其中 f(wi) 是数据集中词 wi 的个数与总词数之比,常数 t 是一个超参数(实验中设为 10−4)。可见,只有当 f(wi)>t 时,我们才有可能在二次采样中丢弃词 wi,并且越高频的词被丢弃的概率越大。

提取中心词和背景词

对每个中心词其背景词的窗口大小时随机选取的,中心词需要被排出背景词外

Skip-Gram 跳字模型

在跳字模型中,每个词被表示成两个 d 维向量,用来计算条件概率。假设这个词在词典中索引为 i ,当它为中心词时向量表示为 vi∈Rd,而为背景词时向量表示为 ui∈Rd 。设中心词 wc 在词典中索引为 c,背景词 wo 在词典中索引为 o,我们假设给定中心词生成背景词的条件概率满足下式:

即内积+softmax

embed = nn.Embedding(num_embeddings=10, embedding_dim=4)
print(embed.weight)

x = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.long)
print(embed(x))
Parameter containing:
tensor([[-0.7417, -1.9469, -0.5745,  1.4267],
        [ 1.1483,  1.4781,  0.3064, -0.2893],
        [ 0.6840,  2.4566, -0.1872, -2.2061],
        [ 0.3386,  1.3820, -0.3142,  0.2427],
        [ 0.4802, -0.6375, -0.4730,  1.2114],
        [ 0.7130, -0.9774,  0.5321,  1.4228],
        [-0.6726, -0.5829, -0.4888, -0.3290],
        [ 0.3152, -0.6827,  0.9950, -0.3326],
        [-1.4651,  1.2344,  1.9976, -1.5962],
        [ 0.0872,  0.0130, -2.1396, -0.6361]], requires_grad=True)
tensor([[[ 1.1483,  1.4781,  0.3064, -0.2893],
         [ 0.6840,  2.4566, -0.1872, -2.2061],
         [ 0.3386,  1.3820, -0.3142,  0.2427]],

        [[ 0.4802, -0.6375, -0.4730,  1.2114],
         [ 0.7130, -0.9774,  0.5321,  1.4228],
         [-0.6726, -0.5829, -0.4888, -0.3290]]], grad_fn=<EmbeddingBackward>)

 

PyTorch 预置的 Embedding 层

输入2*3的张量,输出2*3*4的张量,把每个数字变成embedding后的维度

Skip-Gram 模型的前向计算

def skip_gram(center, contexts_and_negatives, embed_v, embed_u):
    '''
    @params:
        center: 中心词下标,形状为 (n, 1) 的整数张量
        contexts_and_negatives: 背景词和噪音词下标,形状为 (n, m) 的整数张量
        embed_v: 中心词的 embedding 层
        embed_u: 背景词的 embedding 层
    @return:
        pred: 中心词与背景词(或噪音词)的内积,之后可用于计算概率 p(w_o|w_c)
    '''
    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

由于 softmax 运算考虑了背景词可能是词典 V 中的任一词,对于含几十万或上百万词的较大词典,就可能导致计算的开销过大。我们将以 skip-gram 模型为例,介绍负采样 (negative sampling) 的实现来尝试解决这个问题。

负采样方法用以下公式来近似条件概率:

其中 P(D=1∣wc,wo)=σ(uo⊤vc),σ(⋅) 为 sigmoid 函数。对于一对中心词和背景词,我们从词典中随机采样 K 个噪声词(实验中设 K=5)。根据 Word2Vec 论文的建议,噪声词采样概率 P(w) 设为 w 词频与总词频之比的 0.75 次方。

训练模型

损失函数

应用负采样方法后,我们可利用最大似然估计的对数等价形式将损失函数定义为如下

根据这个损失函数的定义,我们可以直接使用二元交叉熵损失函数进行计算:

class SigmoidBinaryCrossEntropyLoss(nn.Module):
    def __init__(self):
        super(SigmoidBinaryCrossEntropyLoss, self).__init__()
    def forward(self, inputs, targets, mask=None):
        '''
        @params:
            inputs: 经过sigmoid层后为预测D=1的概率
            targets: 0/1向量,1代表背景词,0代表噪音词
        @return:
            res: 平均到每个label的loss
        '''
        inputs, targets, mask = inputs.float(), targets.float(), mask.float()
        res = nn.functional.binary_cross_entropy_with_logits(inputs, targets, reduction="none", weight=mask)
        res = res.sum(dim=1) / mask.float().sum(dim=1)
        return res

词嵌入进阶

虽然 Word2Vec 已经能够成功地将离散的单词转换为连续的词向量,并能一定程度上地保存词与词之间的近似关系,但 Word2Vec 模型仍不是完美的,它还可以被进一步地改进:

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

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

GloVe 全局向量的词嵌入

GloVe 模型

让我们先回顾一下word2vec中的跳字模型。将跳字模型中使用softmax运算表达的条件概率

10.5. 全局向量的词嵌入(GloVe) - 图1 记作 10.5. 全局向量的词嵌入(GloVe) - 图2 ,即

其中

10.5. 全局向量的词嵌入(GloVe) - 图4 和 10.5. 全局向量的词嵌入(GloVe) - 图5 分别是索引为 10.5. 全局向量的词嵌入(GloVe) - 图6 的词 10.5. 全局向量的词嵌入(GloVe) - 图7 作为中心词和背景词时的向量表示, 10.5. 全局向量的词嵌入(GloVe) - 图8 为词典索引集。

对于词

10.5. 全局向量的词嵌入(GloVe) - 图9 ,它在数据集中可能多次出现。我们将每一次以它作为中心词的所有背景词全部汇总并保留重复元素,记作多重集(multiset) 10.5. 全局向量的词嵌入(GloVe) - 图10 。一个元素在多重集中的个数称为该元素的重数(multiplicity)。举例来说,假设词 10.5. 全局向量的词嵌入(GloVe) - 图11 在数据集中出现2次:文本序列中以这2个 10.5. 全局向量的词嵌入(GloVe) - 图12 作为中心词的背景窗口分别包含背景词索引 10.5. 全局向量的词嵌入(GloVe) - 图13 和 10.5. 全局向量的词嵌入(GloVe) - 图14 。那么多重集 10.5. 全局向量的词嵌入(GloVe) - 图15 ,其中元素1的重数为2,元素2的重数为4,元素3和5的重数均为1。将多重集 10.5. 全局向量的词嵌入(GloVe) - 图16 中元素 10.5. 全局向量的词嵌入(GloVe) - 图17 的重数记作 10.5. 全局向量的词嵌入(GloVe) - 图18 :它表示了整个数据集中所有以 10.5. 全局向量的词嵌入(GloVe) - 图19 为中心词的背景窗口中词 10.5. 全局向量的词嵌入(GloVe) - 图20 的个数。那么,跳字模型的损失函数还可以用另一种方式表达:

10.5. 全局向量的词嵌入(GloVe) - 图21

我们将数据集中所有以词

10.5. 全局向量的词嵌入(GloVe) - 图22 为中心词的背景词的数量之和 10.5. 全局向量的词嵌入(GloVe) - 图23 记为 10.5. 全局向量的词嵌入(GloVe) - 图24 ,并将以 10.5. 全局向量的词嵌入(GloVe) - 图25 为中心词生成背景词 10.5. 全局向量的词嵌入(GloVe) - 图26 的条件概率 10.5. 全局向量的词嵌入(GloVe) - 图27 记作 10.5. 全局向量的词嵌入(GloVe) - 图28 。我们可以进一步改写跳字模型的损失函数为

10.5. 全局向量的词嵌入(GloVe) - 图29

上式中,

10.5. 全局向量的词嵌入(GloVe) - 图30 计算的是以 10.5. 全局向量的词嵌入(GloVe) - 图31 为中心词的背景词条件概率分布 10.5. 全局向量的词嵌入(GloVe) - 图32 和模型预测的条件概率分布 10.5. 全局向量的词嵌入(GloVe) - 图33 的交叉熵,且损失函数使用所有以词 10.5. 全局向量的词嵌入(GloVe) - 图34 为中心词的背景词的数量之和来加权。最小化上式中的损失函数会令预测的条件概率分布尽可能接近真实的条件概率分布。

然而,作为常用损失函数的一种,交叉熵损失函数有时并不是好的选择。一方面,正如我们在“近似训练”一节中所提到的,令模型预测10.5. 全局向量的词嵌入(GloVe) - 图35 成为合法概率分布的代价是它在分母中基于整个词典的累加项。这很容易带来过大的计算开销。另一方面,词典中往往有大量生僻词,它们在数据集中出现的次数极少。而有关大量生僻词的条件概率分布在交叉熵损失函数中的最终预测往往并不准确。

鉴于此,作为在word2vec之后提出的词嵌入模型,GloVe模型采用了平方损失,并基于该损失对跳字模型做了3点改动:

  • 使用非概率分布的变量 10.5. 全局向量的词嵌入(GloVe) - 图36 和 10.5. 全局向量的词嵌入(GloVe) - 图37 ,并对它们取对数。因此,平方损失项是 10.5. 全局向量的词嵌入(GloVe) - 图38 。
  • 为每个词 10.5. 全局向量的词嵌入(GloVe) - 图39 增加两个为标量的模型参数:中心词偏差项 10.5. 全局向量的词嵌入(GloVe) - 图40 和背景词偏差项 10.5. 全局向量的词嵌入(GloVe) - 图41 。
  • 将每个损失项的权重替换成函数 10.5. 全局向量的词嵌入(GloVe) - 图42 。权重函数 10.5. 全局向量的词嵌入(GloVe) - 图43 是值域在 10.5. 全局向量的词嵌入(GloVe) - 图44 的单调递增函数。 如此一来,GloVe模型的目标是最小化损失函数

10.5. 全局向量的词嵌入(GloVe) - 图45

其中权重函数10.5. 全局向量的词嵌入(GloVe) - 图46 的一个建议选择是:当 10.5. 全局向量的词嵌入(GloVe) - 图47 时(如 10.5. 全局向量的词嵌入(GloVe) - 图48 ),令 10.5. 全局向量的词嵌入(GloVe) - 图49 (如 10.5. 全局向量的词嵌入(GloVe) - 图50 ),反之令 10.5. 全局向量的词嵌入(GloVe) - 图51 。因为 10.5. 全局向量的词嵌入(GloVe) - 图52 ,所以对于 10.5. 全局向量的词嵌入(GloVe) - 图53 的平方损失项可以直接忽略。当使用小批量随机梯度下降来训练时,每个时间步我们随机采样小批量非零 10.5. 全局向量的词嵌入(GloVe) - 图54 ,然后计算梯度来迭代模型参数。这些非零 10.5. 全局向量的词嵌入(GloVe) - 图55 是预先基于整个数据集计算得到的,包含了数据集的全局统计信息。因此,GloVe模型的命名取“全局向量”(GlobalVectors)之意。

需要强调的是,如果词10.5. 全局向量的词嵌入(GloVe) - 图56 出现在词 10.5. 全局向量的词嵌入(GloVe) - 图57 的背景窗口里,那么词 10.5. 全局向量的词嵌入(GloVe) - 图58 也会出现在词 10.5. 全局向量的词嵌入(GloVe) - 图59 的背景窗口里。也就是说, 10.5. 全局向量的词嵌入(GloVe) - 图60 。不同于word2vec中拟合的是非对称的条件概率 10.5. 全局向量的词嵌入(GloVe) - 图61 ,GloVe模型拟合的是对称的 10.5. 全局向量的词嵌入(GloVe) - 图62 。因此,任意词的中心词向量和背景词向量在GloVe模型中是等价的。但由于初始化值的不同,同一个词最终学习到的两组词向量可能不同。当学习得到所有词向量以后,GloVe模型使用中心词向量与背景词向量之和作为该词的最终词向量。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值