ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Word2Vec

2022-09-05 09:03:16  阅读:245  来源: 互联网

标签:嵌入 word random batch Word2Vec 向量 size


词嵌入

1.为什么使用词嵌入?

  • one-hot向量(长度为词库大小,去重排序,一个one-hot仅在单词序号处取1,其余均为0)可以表示词,但是各个单词的one-hot乘积均为0,也就是看不出关联.
  • 所以可以用特征化的嵌入向量来表示单词(矩阵列不是序号,而是n个特征,所需空间远少于列长为词库大小的one-hot),然后根据t-SNE算法把n维数据嵌入到而且平面,可以直观看到一些词的相近程度
  • $$嵌入向量=嵌入矩阵*onehot向量$$

2.词嵌入的类比推理

1.观察向量man、woman、king和queen的嵌入向量,可以发现

$$
man-woman≈king-queen
$$

则可以知道单词之间的类比;同时根据向量差也可以看出,man和woman、king和queen在哪些特征上有差别(例如gender)
2.两个单词之间的相似度可以用余弦相似度衡量

3.学习词嵌入

学习词嵌入 -> 建立一个语言模型:

预测下一个单词 初始化一个参数矩阵,乘以各单词的one-hot向量,得到嵌入向量,把这些嵌入向量作为输入x放进神经网络,假设嵌入向量长度为n,句子已知单词数为m,则softmax分类器得到的向量维度是m×n,相当于把几个嵌入向量叠加在一起(实际中会设置一个固定的历史窗口,例如每次只看前/后k个词(也可同时看前和后),即窗口大小=k,,softmax层输入向量维度=k×n)
需要在m*n个可能的输出中预测这个单词(每个隐藏层包括softmax层都有自己的参数W和b)

4.Word2Vec:Skip-Gram(跳字模型)

采用Skip-Gram模型的Word2Vec算法: 基本步骤与3.学习词嵌入相同。不同之处在于,每次给定一个上下文词,然后选择目标词,但是每次并不只选前k个词,而是在一定词距内随机选择一个词
(从目标字词推测原始语句)

5.分级&负采样

由于softmax层向量维度过大,因此实践中往往会采用分级或负采样两种方法降低计算成本

分级

每次并不会直接精确到属于n个词中的哪一个词,而是采用二分类法,不断划分直至最后。分级方法的计算成本与log2(词汇表大小)成正比。
Tips:为了进一步降低成本,常用词往往会放到离树顶更近的位置。

负采样

对于每一个上下文词,在已选择正确的目标词,即有正类样本的基础上,会特意生成一系列负类样本。相当于一个样本一次迭代进行了多次训练。

# 
# code by Tae Hwan Jung @graykode
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt

def random_batch():
    random_inputs = []
    random_labels = []
    random_index = np.random.choice(range(len(skip_grams)), batch_size, replace=False)

    for i in random_index:
        random_inputs.append(np.eye(voc_size)[skip_grams[i][0]])  # target
        random_labels.append(skip_grams[i][1])  # context word

    return random_inputs, random_labels

# Model
class Word2Vec(nn.Module):
    def __init__(self):
        super(Word2Vec, self).__init__()
        # W and WT is not Traspose relationship
        self.W = nn.Linear(voc_size, embedding_size, bias=False) # voc_size > embedding_size Weight
        self.WT = nn.Linear(embedding_size, voc_size, bias=False) # embedding_size > voc_size Weight

    def forward(self, X):
        # X : [batch_size, voc_size]
        hidden_layer = self.W(X) # hidden_layer : [batch_size, embedding_size]
        output_layer = self.WT(hidden_layer) # output_layer : [batch_size, voc_size]
        return output_layer

if __name__ == '__main__':
    batch_size = 2 # mini-batch size
    embedding_size = 2 # embedding size

    sentences = ["apple banana fruit", "banana orange fruit", "orange banana fruit",
                 "dog cat animal", "cat monkey animal", "monkey dog animal"]

    word_sequence = " ".join(sentences).split()
    word_list = " ".join(sentences).split()
    word_list = list(set(word_list))
    word_dict = {w: i for i, w in enumerate(word_list)}
    voc_size = len(word_list)

    # Make skip gram of one size window
    skip_grams = []
    for i in range(1, len(word_sequence) - 1):
        target = word_dict[word_sequence[i]]
        context = [word_dict[word_sequence[i - 1]], word_dict[word_sequence[i + 1]]]
        for w in context:
            skip_grams.append([target, w])

    model = Word2Vec()

    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001)

    # Training
    for epoch in range(5000):
        input_batch, target_batch = random_batch()
        input_batch = torch.Tensor(input_batch)
        target_batch = torch.LongTensor(target_batch)

        optimizer.zero_grad()
        output = model(input_batch)

        # output : [batch_size, voc_size], target_batch : [batch_size] (LongTensor, not one-hot)
        loss = criterion(output, target_batch)
        if (epoch + 1) % 1000 == 0:
            print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))

        loss.backward()
        optimizer.step()

    for i, label in enumerate(word_list):
        W, WT = model.parameters()
        x, y = W[0][i].item(), W[1][i].item()
        plt.scatter(x, y)
        plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
    plt.show()

标签:嵌入,word,random,batch,Word2Vec,向量,size
来源: https://www.cnblogs.com/chengjunkai/p/16656849.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有