Word2Vec直观理解(全)

①在理解Word2Vec之前,我们需要首先明白一个问题:

为什么不用one-hot?

其实,无论是one-hot,抑或是Word2Vec,都是对词进行向量表示的一种手段,只不过one-hot更加简单,没有考虑上下文的关联,且任意两个one-hot向量的cosine similarity(余弦相似度,值越大夹角越小,我们认为两个向量越相近)都为0。

此外,one-hot会随词表变大而变大,且特征极为稀疏。

②Word2Vec的核心思维

我们希望模型能够通过一个中心词去很好的预测其周围的单词,或利用周围的单词去预测某个中心词。

或者可以这么说:我们希望周围词的整合向量和中心词的向量越接近越好,或者说中心词和周围词向量越接近越好,这样,我们就可以利用周围词的整合向量来替代中心词,或由中心词去替代周围词。而Word2Vec的核心公式也是由此得来的。

③Word2Vec的两个模型

跳字模型(skip-gram)连续词袋模型(CBOW)

首先跳字模型就是我们②中说的希望利用中心词去更好的预测周围词,于是我们会希望当中心词出现的时候,其周围词出现的概率越高越好,其数学表达式如下

这里的t代表了t时刻,m代表了在t时刻其窗口的大小,可以知道,这里的窗口为2m。

需要注意的是,这里我们假设每个单词生成的概率都是独立的,于是我们这个概率可以直接累乘。(独立事件概率的乘积)

我们想要最大化这个概率,实际上等同于最小化下面的式子:

那么下面的问题来了,我们如何去定义这个条件概率?

回过头想想,其实我们是想要找到向量来代表我们的某个词,所以向量是我们需要学习的参数,我们要把这个参数融入到我们的这个函数中,才能够在最小化函数的过程中找到合适的向量。

于是,我们有了下面的式子:

这里面的Vc代表了某一中心词,Uo代表了其周围词,还记得我们之前说的Word2Vec的另一种理解吗?

我们希望中心词和周围词越相近越好,于是我们利用了两个向量的内积来表示其相近的分数,我们希望出现在同一窗口的中心词和周围词向量更加的相近,得到的分数更高,这个分数再通过softmax做正则化,无非是使得不同分数累和之后和为1,更符合概率的意义。

损失函数融入我们希望更新的参数后,就可以对不同参数进行求导迭代更新了,例如:

④如何用神经网络实现?

说了这么多数学式子,乍一看,感觉用神经网络比较难以实现,其实不然,这两者内在有着非常明显的关联。

下面我们介绍一下Word2Vec的神经网络模型,理解之后,反过头来看式子会非常简单。

首先我们需要明确的是,普通的Word2Vec模型就只不过是一个两层的神经网络,并且这个神经网络在第一层中没有激活函数。

我们知道,前馈神经网络,或者说全连接神经网络的本质就是向量乘以矩阵,由于我们的输入是某个中心单词对应的one-hot向量,其只有对应的索引维度为1,其余维度为0,那么我们用这个one-hot向量去乘第一层的权重矩阵的时候,无非是去取对应行所代表的向量

看到了吗,我们在第一层首先要将one-hot转为其对应的一个向量(这实际上就是③中所说的中心词向量Vc),然后我们再将这个one-hot对应的向量(从权重矩阵中抽出的向量,这也解释了我们是怎么去训练参数来获得Vc的表示的),去乘第二层的权重矩阵,这个权重矩阵(隐藏层维度*词表长)的每一列代表了每个词的另一种表示(这实际上就是③中所说的Uo),注意,第二层的神经网络是有激活函数的,而其激活函数就是softmax,这样,我们的原始one-hot向量乘以第一层的权重矩阵获得其第一种表示方式Vc后,再乘以第二层的权重矩阵,这就相当于和所有单词的第二种表示Ui向量挨个做内积,由于第二层有激活函数softmax,于是我们的神经网络完美复刻了③中的公式。

现在回头看看③中的损失函数

1.首先这里面的Vc是通过one-hot和第一层权重矩阵相乘得到的,权重矩阵是可以训练的,所以Vc也是可以通过训练得到的。

2.这里面的Ui就是第二层权重矩阵的每一列,我们用第二层得到的向量乘以第二层权重矩阵,就相当于把Vc和所有Ui做内积,并且通过激活函数softmax,就相当于实现了公式中的条件概率。

3.由于我们的损失函数对应的是交叉熵,我们要拟合的分布是中心词对应周围的几个单词维度上面的为1,即p(x)为1,而其他非周围单词的p(x)自然为0,根据交叉熵公式:求和-p(x)logq(x),我们得到的损失函数也正好对应到了公式。

了解了skip-gram的核心机制,反过头看看CBOW,也就非常简单了

首先我们看看CBOW的损失函数

在网络中,输入改为了多个单词,实际上也就是在对应的维度上填1,如[1, 0, 1, 0, 1]

整合后的向量再去乘第一层的权重向量,就相当于将这些输入的单词在第一层权重矩阵的对应向量累和(用上面的向量乘一个矩阵试试),为了满足公式,我们要将乘出的结果做个平均,再去乘以第二层的权重矩阵并过一个softmax激活函数,就可以完美复刻公式。

⑤近似计算

由于计算过程中向量在第二层权重矩阵会与每一列相乘,这个乘积的次数是字典长度,这个体现在公式中分母的softmax累和,当字典非常大的时候,这个时间复杂度是我们无法接受的。

于是我们想利用其他的方式来近似原有的损失函数,或者说近似原来的那个条件概率。这就产生了两种方法:

负采样层序softmax

首先说层序softmax,我们知道无论是CBOW还是skip-gram在第一层都是非常简单的直接提取对应行即可,计算量大就大在了第二层的softmax计算,那层序softmax的思维是什么呢?

实际上,层序softmax的核心思维,就是通过一个二叉树(哈夫曼树),将一个原本多分类的问题,近似为了一个多次二分类的过程,从而将原来的条件概率的式子替换。

这个二分类的计算,实际上就是我们的输入单词向量,和某一个非叶节点向量相乘后通过sigmoid计算出来的,于是,整个路径的概率就是:

(其中x是我们的输入向量,θ是非叶节点向量,d是哈夫曼0,1编码。)

这个概率,也就是我们用来替换原来条件概率的式子,可以发现,其计算次数和树的高度有关,为log|V|。

而我们希望找到合适的x和θ,去最小化更改后的损失函数。

值得注意的是,使用哈夫曼树可以保证频率高的词总是处在离根节点最近的地方,这些词更容易被产生,但是产生的过程中相较于低频词计算的次数更少,符合贪心策略。

还有一点,虽然在训练过程中减少了计算量,但是在测试过程中我们依然要计算出所有叶节点的概率然后选出大者。

再说一下负采样

负采样的核心思维也是想办法修改原来的条件概率式子,使得其不存在softmax累加所有单词的过程。

负采样将中心词生成背景词这一事件,改为了由两个独立事件的联合概率(就是将两个概率相乘)近似。

这两个事件分别为:

1.中心词和背景词同时出现在窗口

2.中心词和采样的噪声词不同时出现在窗口。

我们用下面的式子定义1的概率:

这是一个非常简单的sigmoid函数,即我们使用中心词和背景词做内积然后通过sigmoid函数来定义我们这个概率。

我们再引入2的概率,再将所有概率相乘,得联合概率:

损失函数就变为了:

此时损失函数的计算量与噪声单词数k有关。

下面是对应的代码:

 def forward(self, input_labels, pos_labels, neg_labels):
        '''
        input_labels: 中心词, [batch_size]
        pos_labels: 中心词周围 context window 出现过的单词 [batch_size * (window_size * 2)]
        neg_labelss: 中心词周围没有出现过的单词,从 negative sampling 得到 [batch_size, (window_size * 2 * K)]
        
        return: loss, [batch_size]
        '''
        
        batch_size = input_labels.size(0)
        
        input_embedding = self.in_embed(input_labels) # B * embed_size
        pos_embedding = self.out_embed(pos_labels) # B * (2*C) * embed_size
        neg_embedding = self.out_embed(neg_labels) # B * (2*C * K) * embed_size
      
        log_pos = torch.bmm(pos_embedding, input_embedding.unsqueeze(2)).squeeze() # B * (2*C)
        log_neg = torch.bmm(neg_embedding, -input_embedding.unsqueeze(2)).squeeze() # B * (2*C*K)

        log_pos = F.logsigmoid(log_pos).sum(1)
        log_neg = F.logsigmoid(log_neg).sum(1) # batch_size
       
        loss = log_pos + log_neg
        
        return -loss

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值