当前位置:   article > 正文

中文词向量:使用pytorch实现CBOW_怎样查看torch里有没有cbow

怎样查看torch里有没有cbow

        整个项目和使用说明地址:链接:https://pan.baidu.com/s/1my30wyqOk_WJD0jjM7u4TQ 
                                                   提取码:xxe0 

        关于词向量的理论基础和基础模型都看我之前的文章。里面带有论文和其他博客链接。可以系统学习关于词向量的知识。

之前已经使用numpy手动实现skip-gram,现在使用pytorch框架实现CBOW
这是pytorch官网的CBOW案例的修改,简单明了,没有涉及底层代码,没有层次优化or负采样优化等问题。这里直接使用pytorch实现并且做了结果可视化。

​​​​​​中文词向量:word2vec之skip-gram实现(不使用框架实现词向量模型)_Richard_Kim的博客-CSDN博客

         这一次可以使用完整语料进行训练,不用担心内存爆炸问题,使用了cuda加速。

实验原理还是原来那样。

1. 项目结构

      

 2. 需要的依赖:pytorch,numpy,matplotlib,sklearn,tqdm,jieba。

 3. 中文乱码问题同上面的skip-gram一样

 4.运行

        我只设置了100维,没有像skip-gram设置了300维

中文语料运行结果

完整代码 

  1. #!/usr/bin/endimension python
  2. # -#-coding:utf-8 -*-
  3. # author:by ucas vv
  4. # datetime:2021/11/07 16:45:21
  5. # software:PyCharm
  6. """
  7. 之前已经使用numpy手动实现skip-gram,现在使用pytorch框架实现CBOW
  8. 这是pytorch官网的CBOW案例的修改,简单明了,没有涉及底层代码,没有层次优化or负采样优化等问题
  9. 地址:https://pytorch.org/tutorials/beginner/nlp/word_embeddings_tutorial.html?highlight=cbow
  10. """
  11. import jieba
  12. import torch
  13. import numpy as np
  14. import torch.nn as nn
  15. import torch.nn.functional as F
  16. import torch.optim as optim
  17. from matplotlib import pyplot as plt
  18. from sklearn.decomposition import PCA
  19. from tqdm import tqdm, trange
  20. # 初始化矩阵
  21. torch.manual_seed(1)
  22. # 加载停用词词表
  23. def load_stop_words():
  24. """
  25. 停用词是指在信息检索中,
  26. 为节省存储空间和提高搜索效率,
  27. 在处理自然语言数据(或文本)之前或之后
  28. 会自动过滤掉某些字或词
  29. """
  30. with open('data/stopwords.txt', "r", encoding="utf-8") as f:
  31. return f.read().split("\n")
  32. # 加载文本,切词
  33. def cut_words():
  34. stop_words = load_stop_words()
  35. with open('data/zh.txt', encoding='utf8') as f:
  36. allData = f.readlines()
  37. result = []
  38. for words in allData:
  39. c_words = jieba.lcut(words)
  40. result.append([word for word in c_words if word not in stop_words])
  41. return result
  42. # 用一个集合存储所有的词
  43. wordList = []
  44. # 调用切词方法
  45. data = cut_words()
  46. count = 0
  47. for words in data:
  48. for word in words:
  49. if word not in wordList:
  50. wordList.append(word)
  51. print("wordList=", wordList)
  52. raw_text = wordList
  53. print("raw_text=", raw_text)
  54. # 超参数
  55. learning_rate = 0.001
  56. # 放cuda或者cpu里
  57. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  58. # 上下文信息,即涉及文本的前n个和后n个
  59. context_size = 2
  60. # 词嵌入的维度,即一个单词用多少个浮点数表示比如 the=[10.2323,12.132133,4.1219774]...
  61. embedding_dim = 100
  62. epoch = 10
  63. def make_context_vector(context, word_to_ix):
  64. idxs = [word_to_ix[w] for w in context]
  65. return torch.tensor(idxs, dtype=torch.long)
  66. # 把所有词集合转成dict
  67. vocab = set(raw_text)
  68. vocab_size = len(vocab)
  69. word_to_idx = {word: i for i, word in enumerate(vocab)}
  70. idx_to_word = {i: word for i, word in enumerate(vocab)}
  71. # cbow那个词表,即{[w1,w2,w4,w5],"label"}这样形式
  72. data = []
  73. for i in range(2, len(raw_text) - 2):
  74. context = [raw_text[i - 2], raw_text[i - 1],
  75. raw_text[i + 1], raw_text[i + 2]]
  76. target = raw_text[i]
  77. data.append((context, target))
  78. print(data[:5])
  79. class CBOW(nn.Module):
  80. def __init__(self, vocab_size, embedding_dim):
  81. super(CBOW, self).__init__()
  82. self.embeddings = nn.Embedding(vocab_size, embedding_dim)
  83. self.proj = nn.Linear(embedding_dim, 128)
  84. self.output = nn.Linear(128, vocab_size)
  85. def forward(self, inputs):
  86. embeds = sum(self.embeddings(inputs)).view(1, -1)
  87. out = F.relu(self.proj(embeds))
  88. out = self.output(out)
  89. nll_prob = F.log_softmax(out, dim=-1)
  90. return nll_prob
  91. # 模型在cuda训练
  92. model = CBOW(vocab_size, embedding_dim).to(device)
  93. # 优化器
  94. optimizer = optim.SGD(model.parameters(), lr=0.001)
  95. # 存储损失的集合
  96. losses = []
  97. """
  98. 负对数似然损失函数,用于处理多分类问题,输入是对数化的概率值。
  99. 对于包含N NN个样本的batch数据 D ( x , y ) D(x, y)D(x,y),x xx 是神经网络的输出,
  100. 进行了归一化和对数化处理。y yy是样本对应的类别标签,每个样本可能是C种类别中的一个。
  101. """
  102. loss_function = nn.NLLLoss()
  103. for epoch in trange(epoch):
  104. total_loss = 0
  105. for context, target in tqdm(data):
  106. # 把训练集的上下文和标签都放到GPU中
  107. context_vector = make_context_vector(context, word_to_idx).to(device)
  108. target = torch.tensor([word_to_idx[target]]).cuda()
  109. # print("context_vector=", context_vector)
  110. # 梯度清零
  111. model.zero_grad()
  112. # 开始前向传播
  113. train_predict = model(context_vector).cuda() # 这里要从cuda里取出,不然报设备不一致错误
  114. loss = loss_function(train_predict, target)
  115. # 反向传播
  116. loss.backward()
  117. # 更新参数
  118. optimizer.step()
  119. total_loss += loss.item()
  120. losses.append(total_loss)
  121. print("losses-=", losses)
  122. # 测试一下,用['present', 'food', 'can', 'specifically']这个上下预测一下模型,正确答案是‘surplus’
  123. context = ['粮食', '出现', '过剩', '恰好']
  124. # 这个变量要放到gpu中,不然又要报设备不一致错误,因为只有把这个数据 同cuda里训练好的数据比较,再能出结果。。很好理解吧
  125. context_vector = make_context_vector(context, word_to_idx).to(device)
  126. # 预测的值
  127. predict = model(context_vector).data.cpu().numpy()
  128. print('Raw text: {}\n'.format(' '.join(raw_text)))
  129. print('Test Context: {}\n'.format(context))
  130. max_idx = np.argmax(predict)
  131. # 输出预测的值
  132. print('Prediction: {}'.format(idx_to_word[max_idx]))
  133. # 获取词向量,这个Embedding就是我们需要的词向量,他只是一个模型的一个中间过程
  134. print("CBOW embedding'weight=", model.embeddings.weight)
  135. W = model.embeddings.weight.cpu().detach().numpy()
  136. # 生成词嵌入字典,即{单词1:词向量1,单词2:词向量2...}的格式
  137. word_2_vec = {}
  138. for word in word_to_idx.keys():
  139. # 词向量矩阵中某个词的索引所对应的那一列即为所该词的词向量
  140. word_2_vec[word] = W[word_to_idx[word], :]
  141. print("word2vec=", word_2_vec)
  142. """
  143. 待转换类型的PyTorch Tensor变量带有梯度,直接将其转换为numpy数据将破坏计算图,
  144. 因此numpy拒绝进行数据转换,实际上这是对开发者的一种提醒。
  145. 如果自己在转换数据时不需要保留梯度信息,可以在变量转换之前添加detach()调用。
  146. """
  147. pca = PCA(n_components=2)
  148. principalComponents = pca.fit_transform(W)
  149. # 降维后在生成一个词嵌入字典,即即{单词1:(维度一,维度二),单词2:(维度一,维度二)...}的格式
  150. word2ReduceDimensionVec = {}
  151. for word in word_to_idx.keys():
  152. word2ReduceDimensionVec[word] = principalComponents[word_to_idx[word], :]
  153. # 将生成的字典写入到文件中,字符集要设定utf8,不然中文乱码
  154. with open("CBOW_ZH_wordvec.txt", 'w', encoding='utf-8') as f:
  155. for key in word_to_idx.keys():
  156. f.write('\n')
  157. f.writelines('"' + str(key) + '":' + str(word_2_vec[key]))
  158. f.write('\n')
  159. # 将词向量可视化
  160. plt.figure(figsize=(20, 20))
  161. # 只画出1000个,太多显示效果很差
  162. count = 0
  163. for word, wordvec in word2ReduceDimensionVec.items():
  164. if count < 1000:
  165. plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
  166. plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号,否则负号会显示成方块
  167. plt.scatter(wordvec[0], wordvec[1])
  168. plt.annotate(word, (wordvec[0], wordvec[1]))
  169. count += 1
  170. plt.show()

 QQ:530193235

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/575429
推荐阅读
相关标签
  

闽ICP备14008679号