马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
词嵌入算法 word2vec
word2vec是一种高效练习词向量的模子,根本出发点是上下文相似的两个词。它们的词向量也应该相似。一样寻常分为CBOW(Continuous Bag-of-Words)与 Skip-Gram
- CBOW 词袋模子,使用中心词四周的词来推测中心词,中心词是目的,四周词是输入
- Skip-gram 根据中心词来推测四周词,中心词是输入,四周词是目的
- 左图为CBOW 右图是Skip-gram
CBOW模子
连续词袋模子,根据上下文来推测目的单词的模子。使用上下文各词的词向量的均值作为拼接起来的词向量。
对小型的数据比力符合
- import numpy as np
- import torch
- import torch.nn as nn
- import torch.optim as optim
- import matplotlib.pyplot as plt
- # 定义数据类型为浮点数
- dtype = torch.FloatTensor
- # 语料库,包含训练模型的句子
- sentences = ["i like dog", "i like cat", "i like animal",
- "dog cat animal", "apple cat dog like", "cat like fish",
- "dog like meat", "i like apple", "i hate apple",
- "i like movie book music apple", "dog like bark", "dog friend cat"]
- # 将所有句子拼接为一个字符串并按空格分词
- word_sequence = ' '.join(sentences).split()
- # 获取词汇表中的所有唯一词
- word_list = list(set(word_sequence))
- # 创建词典,词汇表中的每个词都分配一个唯一的索引
- word_dict = {w: i for i, w in enumerate(word_list)}
- # 创建跳字模型的训练数据
- cow = [] # 训练数据
- for i in range(1, len(word_sequence) - 1):
- # 获取两个上下文词对应的id
- context = [word_dict[word_sequence[i - 1]], word_dict[word_sequence[i + 1]]]
- # 当前词对应的id
- target = word_dict[word_sequence[i]]
- # 将目标词与上下文词配对,添加到训练数据中
- cow.append([context,target])
- # print(cow)
- # 定义嵌入维度(嵌入向量的大小)为2
- embedding_size = 2
- # 每次训练的批量大小
- batch_size = 5
- voc_size = len(word_list)
- # 定义CBOW模型
- class CBOW(nn.Module):
- def __init__(self):
- super(CBOW, self).__init__()
- # 定义词嵌入矩阵W,随机初始化,大小为(voc_size, embedding_size)
- self.embed = nn.Embedding(voc_size,embedding_size)
- self.l = nn.Linear(embedding_size,voc_size)
- # 前向传播
- def forward(self, x):
- x = self.embed(x)
- x = torch.mean(x,dim=1) # 自动降维
- x = self.l(x)
- return x
- # 创建模型实例
- model = CBOW()
- # 定义损失函数为交叉熵损失
- criterion = nn.CrossEntropyLoss()
- # 使用Adam优化器
- optimizer = optim.Adam(model.parameters(), lr=0.001)
- # 定义随机批量生成函数
- def random_batch(data, size):
- random_inputs = [] # 输入批次
- random_labels = [] # 标签批次
- # 从数据中随机选择size个索引
- random_index = np.random.choice(range(len(data)), size, replace=False)
- # 根据随机索引生成输入和标签批次
- for i in random_index:
- random_inputs.append(data[i][0])
- random_labels.append(data[i][1])
- return random_inputs, random_labels
- # 训练模型
- for epoch in range(10000):
- # 获取随机的输入和目标
- inputs, labels = random_batch(cow, batch_size)
- #转为张量
- input_batch = torch.LongTensor(inputs)
- label_batch = torch.LongTensor(labels)
- optimizer.zero_grad() # 梯度清零
- output = model(input_batch)
- # 计算损失函数
- loss = criterion(output, label_batch.view(-1))
- 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 = model.embed.weight.data.numpy()
- x,y = float(W[i][0]),float(W[i][1])
- plt.scatter(x, y) # 绘制散点图
- plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
- plt.show()
复制代码

skip-grams
根据目的单词推测上下文单词的模子
- import torch
- import torch.nn as nn
- import torch.optim as optim
- import numpy as np
- import matplotlib.pyplot as plt
- # 语料库,包含训练模型的句子
- sentences = ["i like dog", "i like cat", "i like animal",
- "dog cat animal", "apple cat dog like", "cat like fish",
- "dog like meat", "i like apple", "i hate apple",
- "i like movie book music apple", "dog like bark", "dog friend cat"]
- # 构建词表
- word_sentences = ' '.join(sentences).split()
- word_list = list(set(word_sentences))
- word_index = {w: i for i, w in enumerate(word_list)}
- index_word = {i: w for i, w in enumerate(word_list)}
- vocab_size = len(word_list)
- # print(word_index)
- # 创建词表
- skip_grams = []
- for i in range(1, len(word_sentences) - 1):
- # 当前词的id
- input_word = word_index[word_sentences[i]]
- # 获得上下文
- context = [word_index[word_sentences[i - 1]], word_index[word_sentences[i + 1]]]
- for w in context:
- # 当前词和上下文词组合形成的skip-gram数据集
- skip_grams.append([input_word, w])
- # 定义超参数
- # 词嵌入维度
- emb_dim = 2
- bach_size = 5
- vocab_size = len(word_list)
- # skip-gram 模型
- class Word2Vec(nn.Module):
- def __init__(self):
- super().__init__()
- self.w1 = nn.Parameter(torch.rand(vocab_size, emb_dim).type(torch.FloatTensor))
- self.w2 = nn.Parameter(torch.rand(emb_dim, vocab_size).type(torch.FloatTensor))
- def forward(self, x):
- x = torch.matmul(x, self.w1)
- x = torch.matmul(x, self.w2)
- return x
- # 模型训练
- model = Word2Vec()
- # 损失函数
- criterion = nn.CrossEntropyLoss()
- optimizer = optim.Adam(model.parameters(), lr=0.001)
- def random_bath(data, size):
- label_list = []
- input_list = []
- random_index = np.random.choice(range(len(data)), size, replace=False)
- # 随机索引生成输入和标签批次
- for i in random_index:
- # 目标词one-hot 编码
- input_list.append((np.eye(vocab_size)[data[i][0]]))
- # 上下文
- label_list.append((data[i][1]))
- return input_list, label_list
- for epoch in range(10000):
- # 获得数据
- inputs, labels = random_bath(skip_grams, bach_size)
- # 转换为张量
- input_bach = torch.Tensor(inputs)
- label_bach = torch.LongTensor(labels)
- optimizer.zero_grad()
- out = model(input_bach)
- loss = criterion(out, label_bach)
- 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 = float(W[i][0]), float(W[i][1])
- plt.scatter(x, y) # 绘制散点图
- plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
- plt.show()
复制代码

使用API调用
Gensim(generate similarity)是一个简单高效的自然语言处置惩罚Python库,用于抽取文档的语义主题(semantic topics)。Gensim的输入是原始的、无结构的数字文本(纯文本),内置的算法包罗Word2Vec,FastText,潜伏语义分析(Latent Semantic Analysis,LSA),潜伏狄利克雷分布(Latent Dirichlet Allocation,LDA)等,通过盘算练习语料中的统计共现模式自动发现文档的语义结构。这些算法都好坏监督的,这意味着不必要人工输入——仅仅必要一组纯文本语料。一旦发现这些统计模式后,任何纯文本(句子、短语、单词)就能接纳语义体现轻巧地表达。
model.wv: 这个对象包罗了全部单词的词嵌入向量。常用的方法有:
- model.wv[word]:返回某个特定单词的向量。
- model.wv.most_similar(word):获取与某个单词最相似的词。
- model.wv.similarity(word1, word2):盘算两个词之间的相似度。
- import numpy as np
- import matplotlib.pyplot as plt
- from gensim.models import Word2Vec
- sentences = "Word embedding is the collective name for a set of language modeling and feature learning techniques in natural language processing (NLP) where words or phrases from the vocabulary are mapped to vectors of real numbers."
- # 每个句子分成单词表
- token_list = [sentences.split()] # 增加一个维度
- print(token_list)
- # 定义模型
- model = Word2Vec(token_list, vector_size=2,window=1,min_count=0)
- # 参数 语料库列表 size 词向量的维度 window窗口大小 最小出现次数、
- # 获取词汇表 model.wv 映射矩阵 的对象
- word_list = list(model.wv.index_to_key)
- print(word_list)
- # 可视化
- # 设置matplotlib支持中文
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体
- plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
- #可视化词嵌入
- for i, word in enumerate(word_list):
- W = model.wv[word]
- x,y = float(W[0]),float(W[1])
- plt.scatter(x, y) # 绘制散点图
- plt.annotate(word, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
- word_vector = [model.wv[word] for word in word_list]
- sen_vector = np.mean(word_vector,axis=0)
- print('句向量',sen_vector)
- # 可视化
- plt.scatter(sen_vector[0],sen_vector[1])
- plt.annotate('句向量', xy=(sen_vector[0],sen_vector[1]), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
- plt.show()
复制代码

参考博客:
Gensim简介-CSDN博客
|