基于维基百科的中文词语相关度计算

首先来一个简单的问题,“乔布斯”和“苹果”这两个词有关联吗?如果有,有多大的相关度?

背景介绍

传统的文档相关度一般是基于特征提取所得的向量相关度,而词语相关度也经常在不少实际应用中涉及到。对于要比较的两个词语,相对于仅仅在“相等”和“不等”这两者间做一个选择,更好的方法应当是对相关度的大小作一个数值性刻画。如果“1”对应完全相关,“0”对应完全不相关(当然也可以将相关度最小值设为-1),那么可以用“0”至“1”之间的一个浮点数来刻画两个词语的相关度。

衡量两个词语的相关度一般通过比较其上下文环境来实现,越相似或者说越相关的两个词越有可能同时出现在一段话中,或者出现在类似的上下文环境中。所以我们需要一个完整且丰富的语料来构建所有词语可能出现的上下文环境,在此语料的基础上训练得到包含于其中的任意词语两两之间的相关度。

看到“我爱nlp”网站上的一篇文章,讲解如何基于维基百科数据计算词语的相关度,点击阅读原文即可访问。维基百科可以说是最常用最权威的开放网络数据集之一,作为极少数的人工编辑、内容丰富、格式规范的文本语料,各类语言的维基百科在NLP等诸多领域应用广泛。维基百科提供了开放的词条文本整合下载,可以找到你需要的指定时间、指定语言、指定类型、指定内容的维基百科数据。

gensim是一个NLP的主题模型(Topic Model)python库,其包含的word2vec模型可用来训练文本数据,即将词语映射为向量,通过计算向量的相关度来实现词语间相关度的计算,接下来将详细讲述这一过程。

预备工作

gensim的安装不用多说,pip或者easy_install皆可,详情请参考其主页或者Github上的安装介绍。

因为手边有一些中文新闻分析的需求,所以针对中文维基百科数据进行处理,下载数据压缩包,文件大概1G左右。

数据提取

首先需要从压缩包中提取出中文维基的条目文本。在压缩包路径下编辑process_wiki.py文件,内容如下:

#!/usr/bin/env python # -*- coding: utf-8 -*- import logging import os.path import sys from gensim.corpora import WikiCorpus if __name__ == '__main__': program = os.path.basename(sys.argv[0]) logger = logging.getLogger(program) logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s') logging.root.setLevel(level=logging.INFO) logger.info("running %s" % ' '.join(sys.argv)) # check and process input arguments if len(sys.argv) < 3: print globals()['__doc__'] % locals() sys.exit(1) inp, outp = sys.argv[1:3] space = " " i = 0 output = open(outp, 'w') wiki = WikiCorpus(inp, lemmatize=False, dictionary={}) for text in wiki.get_texts(): output.write(space.join(text) + "\n") i = i + 1 if (i % 10000 == 0): logger.info("Saved " + str(i) + " articles") output.close() logger.info("Finished Saved " + str(i) + " articles")

之后在终端中执行以下命令即可得到中文维基数据,保存至wiki.zh.text文件中,一共25W多行,每行对应一条维基条目的所有文本内容。

python process_wiki.py zhwiki-latest-pages-articles.xml.bz2 wiki.zh.text

中文维基的一个很大的问题是混杂了很多繁体字,不便于阅读和使用。可以使用开源工具opencc进行繁简中文的转化。我的环境是macos,使用brew即可方便安装。opencc配置好后,在终端中运行以下命令进行繁简转化,将简体中文维基数据保存至wiki.zh.jian.text中。

opencc -i wiki.zh.text -o wiki.zh.jian.text -c t2s.json

现在每行对应一条维基条目的文本内容,我们需要对语句进行中文分词,这样得到的数据才是由一个个词语组成的语料。还是在压缩包所在的路径下,编辑segment_wiki.py,使用结巴分词进行中文分词。编辑好后运行即可,分词结果保存至wiki.zh.word.text中。

#!/usr/bin/env python # coding:utf8 import jieba import sys reload(sys) sys.setdefaultencoding('utf8') jieba.enable_parallel(4) fr = open('wiki.zh.jian.text', 'r') fw = open('wiki.zh.word.text', 'w') count = 0 for line in fr: count += 1 print count result = '' line = line.rstrip('\n').split() for item in line: item = jieba.cut(item) for i in item: result += i + ' ' fw.write(result[:-1] + '\n') fr.close() fw.close()

这样,就基本完成模型训练之前的数据准备工作了。

模型训练

我们使用gensim包提供的word2vec模型进行训练,还是在压缩包所在路径下,编辑train_word2vec_model.py文件,内容如下:

#!/usr/bin/env python # -*- coding: utf-8 -*- import logging import os.path import sys import multiprocessing from gensim.corpora import WikiCorpus from gensim.models import Word2Vec from gensim.models.word2vec import LineSentence if __name__ == '__main__': program = os.path.basename(sys.argv[0]) logger = logging.getLogger(program) logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s') logging.root.setLevel(level=logging.INFO) logger.info("running %s" % ' '.join(sys.argv)) # check and process input arguments if len(sys.argv) < 4: print globals()['__doc__'] % locals() sys.exit(1) inp, outp1, outp2 = sys.argv[1:4] model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count()) # trim unneeded model memory = use(much) less RAM #model.init_sims(replace=True) model.save(outp1) model.save_word2vec_format(outp2, binary=False)

之后在终端中执行以下命令即可进行模型的训练,训练过程可能需要十几分钟的时间,耐心等待不要着急,训练完毕后会生成wiki.zh.text.model、wiki.zh.text.model.syn0.npy、wiki.zh.text.model.syn1.npy、wiki.zh.text.vector四个文件。

python train_word2vec_model.py wiki.zh.word.text wiki.zh.text.model wiki.zh.text.vector

模型使用

现在我们可以使用训练好的模型来获取词语之间的相关度了,使用以下命令加载训练好的模型:

import gensim model = gensim.models.Word2Vec.load("wiki.zh.text.model")

此处的model提供了两个有用的函数:most_similar()和similarity()。前者对于给定词语遍历其他所有词语并返回与其相关度最高的10个词语,后者则直接返回两个词语的相关度。看看以下例子,和我们的日常生活认知还是挺吻合的。

>> result = model.most_similar(u'足球') >> for e in result: ... print e[0], e[1] ... 甲级联赛 0.728107869625 联赛 0.624911427498 乙级 0.619551062584 足球联赛 0.61553055048 俱乐部 0.600710988045 中作赛 0.588489711285 印超 0.583016633987 fwa 0.58231317997 港超联 0.582292079926 中国足球协会 0.579757452011 >> print model.similarity(u'男人', u'女人') 0.773828387262 >> print model.similarity(u'男人', u'老人') 0.204776343779

后记

word2vec为词语间相关度的计算提供了一个更好的解决方案,也有利于帮我们寻找类似“乔布斯”和“苹果”这样的词语之间所隐含的关联,在具体应用中往往能实现更符合语义要求的结果。现在模型已经有了,不妨大开脑洞去实践一些有意思的应用吧!

原文发布于微信公众号 - 宏伦工作室(HonlanFarm)

原文发表时间:2016-01-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端布道

JavaScript设计模式与开发实践 - 策略模式

引言 本文摘自《JavaScript设计模式与开发实践》 在现实中,很多时候也有多种途径到达同一个目的地。比如我们要去某个地方旅游,可以根据具体的实际情况来选择...

3888
来自专栏PPV课数据科学社区

【完整案例】如何用R实现空间数据可视化

image.png 流行病学的数据讲究“三间分布”,即人群分布、时间分布和空间分布。其中的“空间分布”最好是在地图上展示,才比较清楚。R软件集统计分析与高级...

1.2K7
来自专栏数据派THU

手把手教你用R处理常见的数据清洗问题(附步骤解析、R语言代码)

R是进行运算、清洗、汇总及生成概率统计等数据处理的一个绝佳选择。此外,由于它独立于平台、短期内不会消失,所以生成的程序可以在任何地方运行。并且,它具备非常棒的辅...

4193
来自专栏大数据挖掘DT机器学习

利用pandas+python制作100G亚马逊用户评论数据词云

我们手里面有一个差不多100G的亚马逊用户在购买商品后留下的评论数据(数据格式为json)。我们需要统计这100G数据中,出现频率最高的100个词语。然后制作一...

3122
来自专栏数据结构与算法

P1064 金明的预算方案

题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布...

3658
来自专栏Crossin的编程教室

【每周一坑】图像的指纹:数字水印 + 【解答】鸡兔同笼

曾经有过这样的新闻:某公司的员工将内网论坛上的言论截屏发布到互联网上,引发了热议。于是公司通过截图定位到了员工的身份,将其开除。

1822
来自专栏CSDN技术头条

Weiflow:微博也有机器学习框架?

本文从开发效率(易用性)、可扩展性、执行效率三个方面,介绍了微博机器学习框架Weiflow在微博的应用和最佳实践。 在上期《基于Spark的大规模机器学习在微博...

3318
来自专栏企鹅号快讯

数据分析:寻找Python最优计算性能

1、场景描述 在数据统计分析过程中,求累计值(总和)是最常用的统计指标之一,市面上的各种流行数据库均支持的查询方式基本如下: select sum(c) fro...

2257
来自专栏CDA数据分析师

手把手教你用Python分析豆瓣电影——以《我不是药神》《邪不压正》为例

《我不是药神》是由文牧野执导,宁浩、徐峥共同监制的剧情片,徐峥、周一围、王传君、谭卓、章宇、杨新鸣等主演 。影片讲述了神油店老板程勇从一个交不起房租的男性保健品...

3513
来自专栏数据派THU

一文盘点三大顶级Python库(附代码)

Python在许多方面有着强大的吸引力 - 例如效率、代码可读性和速度方面,也正因为如此,对于希望提升应用程序功能的数据科学家和机器学习专家来说,Python通...

1914

扫码关注云+社区

领取腾讯云代金券