一、概述

训练语料来源:维基媒体 https://dumps.wikimedia.org/backup-index.html 汉语数据

用word2vec训练词向量,并用所学得的词向量,计算 pku_sim_test.txt 文件中每行两个词间的余弦距离作为两词相似度,并输出到文件中。

二、数据准备及预处理

语料库的下载地址:https://dumps.wikimedia.org/zhwiki/20191120/zhwiki-20191120-pages-articles-multistream.xml.bz2

语料库文章的提取

下载完成之后,解压缩得到的是一个xml文件,里面包含了许多的文章,也有许多的日志信息。此实验只需要提取xml文件里面的文章就可以了。

可以通过工具WikiExtractor来提取xml文件中的文章。先将整个WikiExtractor项目clone或者下载到本地,通过命令行窗口来运行,命令如下:(每个文件分割的大小为500M)

> git init
> git clone https://github.com/attardi/wikiextractor
> python .\wikiextractor\WikiExtractor.py -b 500M -o zhwiki zhwiki-20190401-pages-articles-multistream.xml.bz2

使用WikiExtractor提取文章,会在指定目录下产生一个AA的文件夹,里面会包含几个文件。

中文简体和繁体的转换

因为维基百科语料库中的文章内容里面的简体和繁体是混乱的,所以我们需要将所有的繁体字转换成为简体。这里我们利用OpenCC来进行转换。

OpenCC项目地址: https://github.com/BYVoid/OpenCC, 将OpenCC安装到本地电脑后,执行命令:(t2s.json: 繁体转简体)

> opencc -i .\zhwiki\AA\wiki_00
-o .\zhwiki\BB\wiki_00
-c D:\opencc-1.0.4-win32\opencc-1.0.4\share\opencc\t2s.json

正则表达式提取文章内容并进行分词:

当前目录下的segmentWords.py中的代码共执行了三个步骤的操作:

(1)过滤标签内容:使用WikiExtractor提取的文章,会包含许多的,所以需要将这些不相关的内容通过正则表达式来去除。

(2)分词及去停用词:通过jieba对文章进行分词,在分词的时候还需要将停用词去除。

(3)合并保存文件:将分割之后的文章保存到文件中,每一行表示一篇文章,每个词之间使用空格进行分隔。

Jieba项目地址:https://github.com/fxsjy/jieba

#segmentWords.py

import logging
import jieba
import os
import re def get_stopwords():
logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s',level=logging.INFO)
#加载停用词表
stopword_set = set()
with open("./stop_words/stopwords.txt",'r',encoding="utf-8") as stopwords:
for stopword in stopwords:
stopword_set.add(stopword.strip("\n"))
return stopword_set '''
使用正则表达式解析文本
'''
def parse_zhwiki(read_file_path,save_file_path):
#过滤掉<doc>
regex_str = "[^<doc.*>$]|[^</doc>$]"
file = open(read_file_path,"r",encoding="utf-8")
#写文件
output = open(save_file_path,"w+",encoding="utf-8")
content_line = file.readline()
#获取停用词表
stopwords = get_stopwords()
#定义一个字符串变量,表示一篇文章的分词结果
article_contents = ""
cnt = 0
while content_line:
match_obj = re.match(regex_str,content_line)
content_line = content_line.strip("\n")
if len(content_line) > 0:
if match_obj:
#使用jieba进行分词
words = jieba.cut(content_line,cut_all=False)
for word in words:
if word not in stopwords:
article_contents += word+" "
else:
if len(article_contents) > 0:
output.write(article_contents+"\n")
article_contents = ""
cnt += 1
if (cnt % 10000 == 0):
print("已处理", cnt/10000, "万行")
content_line = file.readline()
output.close() '''
将维基百科语料库进行分类
'''
def generate_corpus():
zhwiki_path = "./zhwiki/BB"
save_path = "./zhwiki/BB"
for i in range(3):
print("开始处理第", i, "个文件")
file_path = os.path.join(zhwiki_path,str("wiki_0%s"%str(i)))
parse_zhwiki(file_path,os.path.join(save_path,"wiki_corpus0%s"%str(i))) '''
合并分词后的文件
'''
def merge_corpus():
output = open("./zhwiki/BB/wiki_corpus","w",encoding="utf-8")
input = "./zhwiki/BB"
for i in range(3):
print("开始合并第", i, "个文件")
file_path = os.path.join(input,str("wiki_corpus0%s"%str(i)))
file = open(file_path,"r",encoding="utf-8")
line = file.readline()
while line:
output.writelines(line)
line = file.readline()
file.close()
output.close() if __name__ == "__main__":
# # wiki数据处理
print("开始正则,jieba处理数据")
generate_corpus() # 文件合并
print("开始合并文件")
merge_corpus() # 打印数据 显示
input_file = "./zhwiki/BB/wiki_corpus"
file = open(input_file,"r",encoding="utf-8")
line = file.readline()
num = 1
while line:
print(line)
line = file.readline()
num += 1
if num > 10:
break

word2vec模型的训练

当前目录下的train.py中word2vec的参数设置(size=100, window=5, sg=1, hs=0, negative=5),符合实验要求(前后2窗口,100维,SGNS)。

#train.py

import logging
from gensim.models import word2vec def main():
logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s",level=logging.INFO)
sentences = word2vec.LineSentence("./zhwiki/BB/wiki_corpus")
# size:单词向量的维度
# window: 窗口大小
# sg=1: 使用skip-gram
# hs=0: 使用negative sample
model = word2vec.Word2Vec(sentences, size=100, window=5, sg=1, hs=0, negative=5)
# 保存模型 必须3个一起用
# model.save("./model/wiki_corpus.bin")
# model.save("./model/wiki_corpus.model") # 训练为一个单独二进制压缩文件 可独立使用
model.wv.save_word2vec_format("./model/wiki_corpus_binary.bin", binary=True) if __name__ == "__main__":
main()

计算两个词的相似度:

当前目录下的compute.py中的代码共执行了以下步骤:

(1)读取训练得到的模型,以及待计算相似的pku_sim_test.txt文件

(2)字符串以\t\n为分隔符切分为列表格式,并计算相似度

(3)结果保存为result.txt文件

#compute.py

import re
from gensim.models import KeyedVectors def main():
# 读取模型以及待计算数据
model = KeyedVectors.load_word2vec_format("./model/wiki_corpus_binary.bin", binary=True)
f = open('./pku_sim_test.txt', encoding='utf-8')
out = open('result.txt', 'w', encoding='utf-8') # 字符串切分为列表
wordlist = []
while True:
line = f.readline()
if not line:
break
wordlist.append(re.split(r'[\t\n]', line)) # 计算相似度
cnt = 0
resTotal = 0.0
for i in range(len(wordlist)):
words = wordlist[i]
try:
res = model.similarity(words[0], words[1])
except KeyError:
words[2] = 'OOV'
wordlist[i] = words
print(words)
continue words[2] = str("%.4f"%res)
wordlist[i] = words
print(words)
cnt += 1
resTotal += res print("查到的比例为:%.4f"%(cnt/len(wordlist)))
print("平均相似度为:%.4f"%(resTotal/cnt)) # 结果保存
lines = []
for i in range(len(wordlist)):
line = wordlist[i]
oneline = line[0] + '\t' + line[1] + '\t' + line[2] + '\n'
lines.append(oneline)
out.writelines(lines)
f.close()
out.close() if __name__ == '__main__':
main()

【计算语言学实验】基于 Skip-Gram with Negative Sampling (SGNS) 的汉语词向量学习和评估的更多相关文章

  1. word2vec 中的数学原理具体解释(五)基于 Negative Sampling 的模型

      word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了非常多人的关注. 因为 word2vec 的作者 Tomas ...

  2. word2vec原理(三) 基于Negative Sampling的模型

    word2vec原理(一) CBOW与Skip-Gram模型基础 word2vec原理(二) 基于Hierarchical Softmax的模型 word2vec原理(三) 基于Negative Sa ...

  3. 论文解读(SelfGNN)《Self-supervised Graph Neural Networks without explicit negative sampling》

    论文信息 论文标题:Self-supervised Graph Neural Networks without explicit negative sampling论文作者:Zekarias T. K ...

  4. word2vec改进之Negative Sampling

    训练网络时往往会对全部的神经元参数进行微调,从而让训练结果更加准确.但在这个网络中,训练参数很多,每次微调上百万的数据是很浪费计算资源的.那么Negative Sampling方法可以通过每次调整很小 ...

  5. 词表征 2:word2vec、CBoW、Skip-Gram、Negative Sampling、Hierarchical Softmax

    原文地址:https://www.jianshu.com/p/5a896955abf0 2)基于迭代的方法直接学 相较于基于SVD的方法直接捕获所有共现值的做法,基于迭代的方法一次只捕获一个窗口内的词 ...

  6. DL4NLP——词表示模型(三)word2vec(CBOW/Skip-gram)的加速:Hierarchical Softmax与Negative Sampling

    上篇博文提到,原始的CBOW / Skip-gram模型虽然去掉了NPLM中的隐藏层从而减少了耗时,但由于输出层仍然是softmax(),所以实际上依然“impractical”.所以接下来就介绍一下 ...

  7. Notes on Noise Contrastive Estimation and Negative Sampling

    Notes on Noise Contrastive Estimation and Negative Sampling ## 生成负样本 在常见的关系抽取应用中,我们经常需要生成负样本来训练一个好的系 ...

  8. [DeeplearningAI笔记]序列模型2.7负采样Negative sampling

    5.2自然语言处理 觉得有用的话,欢迎一起讨论相互学习~Follow Me 2.7 负采样 Negative sampling Mikolov T, Sutskever I, Chen K, et a ...

  9. 21.实验基于_version进行乐观锁并发控制

    21.实验基于_version进行乐观锁并发控制 主要知识点: 实验基于_version进行乐观锁并发控制 1.实验实战演练基于_version进行乐观锁并发控制 (1)先构造一条数据出来 PUT / ...

随机推荐

  1. Docker 容器数据 持久化(系统学习Docker05)

    写在前面 本来是可以将数据存储在 容器内部 的.但是存在容器内部,一旦容器被删除掉或者容器毁坏(我亲身经历的痛,当时我们的大数据平台就是运行在docker容器内,有次停电后,不管怎样容器都起不来.以前 ...

  2. Java7循环结构综合练习

    import java.util.Scanner; public class jh_01_学员操作_选择游戏 { public static void main(String[] args) { Sc ...

  3. mongodb副本集群搭建

    一.环境介绍 1.机器信息 10.40.6.68 10.40.6.108 10.40.6.110 软件环境为centos 6.x 2.mongodb 下载链接地址 https://www.mongod ...

  4. 06-Spring03-事务管理

    今日知识 1. Spring事务管理 2. 转账案例 Spring事务管理 1. 事务特性(ACID) 1. 原子性:整体 [原子性是指事务包含的所有操作要么全部成功,要么全部失败] 2. 一致性:数 ...

  5. 代码质量:SonarQube

    SonarQube SonarQube的安装 jenkins(十四):Jenkins和sonarqube集成 https://www.cnblogs.com/sunyllove/p/9895373.h ...

  6. filebeat+kafka

    kafka出现接收不到filebeat数据,最后发现版本兼容问题 filebeat换成  filebeat-7.4.2-linux-x86_64 kafka是docker-compose启动的,版本是 ...

  7. k8s系列---Worker节点扩容

    其他有关内容 安装:参考https://www.cnblogs.com/dribs/p/9082458.html 集群故障重置:参考https://www.cnblogs.com/dribs/p/10 ...

  8. 珠峰-cookie相关的东西

    ####  md5 #### #####

  9. Idea操作ElasticSearch

    前提: 1.ES服务成功启动 2.node.js成功启动 一.创建索引库 1.目录展示 2.导入依赖 <dependency> <groupId>org.elasticsear ...

  10. Java中,一个存在了十几年的bug...

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...