2、word2vec ----- CBOW和skip-gram理解

一、什么是word2vec

word2vec,即词向量,就是一个词用一个向量来表示。Word2Vec是用来生成词向量的工具,这样词与词之间就可以定量的去度量他们之间的关系,挖掘词之间的联系。

是2013年Google提出的。word2vec工具主要包含两个模型:跳字模型(skip-gram)和连续词袋模型(continuous bag of words,简称CBOW),以及两种高效训练的方法:负采样(negative sampling)和层序softmax(hierarchical softmax)。


特点:将所有的词表示成低维稠密向量,从而可以在词向量空间上定性衡量词与词之间的相似性。
核心思想:通过将词条转换成向量,从而根据余弦相似度来计算文本之间的相似度。


在这里插入图片描述

词向量的应用

词向量的几种典型应用:

1、把这些对词语理解的向量通过特定方法组合起来,就可以有对某句话的理解了;
2、可以在向量空间中找寻同义词,因为同义词表达的意思相近,往往在空间中距离也非常近;
3、词语的距离换算。

词语距离计算这个比较有意思,比如可以拿词语做加减法。公猫 - 母猫 就约等于 男人 - 女人。
常用的方式是将这些训练好的词向量当做预训练模型,然后放入另一个神经网络(比如RNN)当成输入,使用另一个神经网络加工后,训练句向量。

二、什么是CBOW

CBOW ——Continuous Bag-of-Word :挑一个要预测的词,来学习这个词前后文中词语和预测词的关系。
模型如下:
在这里插入图片描述

举例:
有一句话:好好学习,天天向上。
让我们把这一句话拆分成输入、输出关系。那么这个模型的输入输出可以是:

# 1
# 输入:[好,好] + [习,,]
# 输出:学

# 2
# 输入:[天,天] + [上, 。]
# 输出:向

# 3
# 输入:[学,习] + [天,天]
# 输出:,

通过在大数据量的短语或文章中学习这样的词语关系,这个模型就能理解要预测的词和前后文的关系。
在这里插入图片描述
首先输入的是one-hot向量,第一层是一个全连接层(没有激活函数),输出层是一个softmax层,输出一个概率分布,表示词典中每个词出现的概率。

1 输入层:上下文单词的onehot. {假设单词向量空间dim为V,上下文单词个数为C},假定要预测的单词是学,那么输入层为好、好、习、,,采用one-hot编码,分别为[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]、[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]、[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]、[0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
2 所有onehot分别乘以共享的输入权重矩阵W. {VN矩阵,N为自己设定的数,初始化权重矩阵W}
3 所得的向量 {因为是onehot所以为向量} 相加求平均作为隐层向量, size为1
N.
4 乘以输出权重矩阵W’ {NV}
5 得到向量 {1
V} 激活函数处理得到V-dim概率分布 {其中的每一维度代表着一个单词}
6 概率最大的index所指示的单词为预测出的中间词(target word)与true label的onehot做比较,误差越小越好(根据误差更新权重矩阵)
所以,需要定义loss function(一般为交叉熵代价函数),采用梯度下降算法更新W和W’。训练完毕后,输入层的每个单词与矩阵W相乘得到的向量的就是我们想要的词向量,这个矩阵也叫做look up table,也就是说,任何一个单词的onehot乘以这个矩阵都将得到自己的词向量。
-------该段引用于:https://www.cnblogs.com/cymx66688/p/11185824.html

代码

import torch
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable

torch.manual_seed(1)   #设置随机初始化的种子,让其固定

context_size = 2  # {w_i-2 ... w_i ... w_i+2}
embedding_dim = 10

raw_text = """We are about to study the idea of a computational process.
Computational processes are abstract beings that inhabit computers.
As they evolve, processes manipulate other abstract things called data.
The evolution of a process is directed by a pattern of rules
called a program. People create programs to direct processes. In effect,
we conjure the spirits of the computer with our spells.""".split()

data = []
for i in range(2, len(raw_text) - 2):
    context = [raw_text[i - 2], raw_text[i - 1],
               raw_text[i + 1], raw_text[i + 2]]
    target = raw_text[i]
    data.append((context, target))

vocab = set(raw_text)
#{'conjure', 'with', 'beings', 'of', 'are', 'computers.', 'the', 'direct', 'We', 'directed', 'People', 'In', 'evolution', 'processes.', 'manipulate', 'The', 'is', 'data.', 'inhabit', 'a', 'evolve,', 'idea', 'process.', 'by', 'other', 'create', 'processes', 'things', 'called', 'pattern', 'computer', 'spells.', 'abstract', 'rules', 'Computational', 'computational', 'study', 'they', 'programs', 'process', 'we', 'program.', 'to', 'spirits', 'As', 'about', 'effect,', 'that', 'our'}
vocab_size = len(vocab)  #49

word_to_idx = {word: i for i, word in enumerate(vocab)}
#{'of': 0, 'spells.': 1, 'conjure': 2, 'data.': 3, 'computer': 4, 'rules': 5, 'by': 6, 'study': 7, 'evolution': 8, 'As': 9, 'they': 10, 'is': 11, 'We': 12, 'inhabit': 13, 'beings': 14, 'process': 15, 'things': 16, 'a': 17, 'about': 18, 'program.': 19, 'People': 20, 'the': 21, 'create': 22, 'other': 23, 'directed': 24, 'pattern': 25, 'programs': 26, 'direct': 27, 'effect,': 28, 'we': 29, 'with': 30, 'that': 31, 'processes': 32, 'Computational': 33, 'to': 34, 'manipulate': 35, 'called': 36, 'spirits': 37, 'our': 38, 'abstract': 39, 'computers.': 40, 'computational': 41, 'process.': 42, 'evolve,': 43, 'In': 44, 'The': 45, 'processes.': 46, 'idea': 47, 'are': 48}
idx_to_word = {i: word for i, word in enumerate(vocab)}
#{0: 'of', 1: 'spells.', 2: 'conjure', 3: 'data.', 4: 'computer', 5: 'rules', 6: 'by', 7: 'study', 8: 'evolution', 9: 'As', 10: 'they', 11: 'is', 12: 'We', 13: 'inhabit', 14: 'beings', 15: 'process', 16: 'things', 17: 'a', 18: 'about', 19: 'program.', 20: 'People', 21: 'the', 22: 'create', 23: 'other', 24: 'directed', 25: 'pattern', 26: 'programs', 27: 'direct', 28: 'effect,', 29: 'we', 30: 'with', 31: 'that', 32: 'processes', 33: 'Computational', 34: 'to', 35: 'manipulate', 36: 'called', 37: 'spirits', 38: 'our', 39: 'abstract', 40: 'computers.', 41: 'computational', 42: 'process.', 43: 'evolve,', 44: 'In', 45: 'The', 46: 'processes.', 47: 'idea', 48: 'are'}


class CBOW(nn.Module):    # 用Module构造出来的对象,会根据里面的计算图自动的实现backward过程,也可以自己构建

    def __init__(self, vocab_size, embedding_dim):
        super(CBOW, self).__init__()
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)   #初始化了一个随机矩阵,矩阵长是字典大小,宽是用来表示字典中每个元素的属性向量,向量的维度根据想要的元素的复杂度而定。
        self.hidden = nn.Linear(embedding_dim, 128)
        self.output = nn.Linear(128, vocab_size)

    def forward(self, inputs):        #前馈过程中进行的计算计算
        embeds = sum(self.embeddings(inputs)).view(1, -1)
        out = F.relu(self.hidden(embeds))
        out = self.output(out)
        nll_prob = F.log_softmax(out, dim=-1)
        return nll_prob


model = CBOW(vocab_size, embedding_dim)   #49,10
optimizer = optim.Adam(model.parameters(), lr=0.001)  #lr (float, 可选) – 学习率(默认:1e-3), Adam 是一种可以替代传统随机梯度下降过程的一阶优化算法,它能基于训练数据迭代地更新神经网络权重
losses = []
loss_function = nn.NLLLoss()   #定义损失函数:最大自然/log似然代价函数

def make_context_vector(context, word_to_idx):
    idxs = [word_to_idx[w] for w in context]
    return torch.tensor(idxs, dtype=torch.long)

#反向传播步骤
for epoch in range(100):
    total_loss = 0
    for context, target in data:
        context_vector = make_context_vector(context, word_to_idx)

        model.zero_grad()    #对模型参数的梯度置为0,记住PyTorch计算的梯度

        nll_prob = model(context_vector)
        loss = loss_function(nll_prob, Variable(torch.tensor([word_to_idx[target]])))

        # backpropagation
        loss.backward()
        # update the parameters
        optimizer.step()
        total_loss += loss.item()

    losses.append(total_loss)

print(losses)


print("*************************************************************************")
context = ['process.', 'Computational', 'are', 'abstract']
context_vector = make_context_vector(context, word_to_idx)
a = model(context_vector).data.numpy()
print('Raw text: {}\n'.format(' '.join(raw_text)))
print('Test Context: {}\n'.format(context))
max_idx = np.argmax(a)
print('Prediction: {}'.format(idx_to_word[max_idx]))

运行结果:
在这里插入图片描述

三、什么是skip-gram

之前说明了CBOW模型是使用上下文来预测上下文之间的结果,Skip-Gram 则是把这个过程反过来,使用文中的某个词,然后预测这个词周边的词。
在这里插入图片描述
Skip-Gram 相比 CBOW 最大的不同,就是剔除掉了中间的那个 SUM 求和的过程。
skip-gram模型的输入是一个单词wI,它的输出是wI的上下文w0,1,…,wc-1,C,上下文的窗口大小为C。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值