windows环境下使用wiki中文百科及gensim工具库训练词向量

       以前做图像算法,面对的都是一幅图像、m*n个像素点,对于词向量完全没有概念,在接触自然语言处理一些算法后,才知道这个概念,想必做自然语言处理的同学都训练过词向量。 训练词向量的相关文章已经很多,不过由于大家使用的操作系统不同, 每个人的做法可能都不一样,没有标准做法,大家使用的工具库可能有些也是不同的,相信每个人都在寻找最佳的训练方法。本文主要介绍windows环境下使用python语言,调用gensim工具库训练词向量的过程。说了这么多,那到底什么是词向量呢,为啥要训练这个东东? 自然语言处理的都是文字,比如要对100个文字的小段文本做分析,而算法运算需要的输入是数字,比如y=w*x +b,不管你是中文汉字还是英文字母,都需要将文字映射成数字才行,映射后的结果就是词向量了。比如:
【苹果】这个词,训练后的词向量为:
(-0.289151 0.025888 0.135030 0.075366 0.099814 -0.001124 0.162626 0.090600 -0.350755 0.250274),
       一般词向量都是高维向量,比如我在工作中训练的词向量是200维,这里仅仅以10维向量为例。有了这个词向量后,就可以将其作为神经网络模型的输入,用于训练文本分类模型等,还可以用于计算词和词之间的相似性,在词向量空间,苹果和桔子两个词是很接近的,同样麻辣烫和酸辣粉是很接近的。训练词向量,首先要有语料库,语料库就是分好词的、每个文本占据一行的大集合,制作语料库是一个繁琐的事情,原材料选择上一般大家会选择wiki中文百科,下载地址:https://dumps.wikimedia.org/zhwiki/,不过一般下载比较慢,推荐找一些镜像网站下载,比如: http://dumps.wikimedia.your.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2  下载稍微快一些。如果使用程序下载可参考下面python代码:
size = 0
chunk_size = 1024*1000
req = requests.get("http://dumps.wikimedia.your.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2", stream=True)
fwiki = open("wiki_download/zhwiki-latest-pages-articles.xml.bz2", "wb")
for chunk in req.iter_content(chunk_size=1024):
    if chunk:
        fwiki.write(chunk)
        size += 1024
        if ((size % chunk_size) == 0):
            print("download finished: " + str(size/1000000) + "M")

fwiki.flush()
fwiki.close()
       下载完成后就自动将该压缩包保存至wiki_download文件夹内。下载完成后,下一步就是解压缩并提取文本,可以使用开源工具wiki extractor(https://github.com/attardi/wikiextractor)完成。这一步比较简单,只需要将该文件保存到自己工程目录下,然后运行命令:
cmd = "python wiki_extractor.py -b 1200M -o wiki_download/extracted wiki_download/zhwiki-latest-pages-articles.xml.bz2"
subprocess.call(cmd, shell=True)
       -b 1200M表示以 1200M 为单位切分文件,-o 后面接出入文件,最后是输入文件,这个抽取过程还是比较漫长的。上面是写代码、程序化的方式,如果在控制台敲命令也可以,但是如果将整个过程程序化的一键自动完成,那么简单写下上面代码就可以了。抽取后的文本是一个巨大的文件,大概长这样:
       
       下一步就是分词前的数据预处理工作,通过上面图也可以看到,文本里面包含了很多wiki文档特有的标记及特殊字符,比如<doc>、“”、《》等等,需要依次剔除,当然还有很多繁体字,需要统一转成简体字。这里简单说一下繁简转换,本来打算用opencc,但是发现在纯python环境下无法使用,opencc需要依赖一个.so库。只好用其他库了,后来我选择的是hanziconv,效果也不错的。简单示例代码如下:
line = HanziConv.toSimplified(line)
       数据预处理完成后就可以进行分词了,示例代码如下:
seg_list = jieba.cut(line, HMM=True)
       由于是python环境,我这里用的是jieba分词,在java环境下我也用过HanLP分词工具库,真心佩服这些开源库的作者,代码质量都蛮高的。这两个分词库各有千秋,HanLP库运行速度更快,而对于淘宝体文字,比如:【透气拖鞋夏季一字拖男女士韩版学生简约魔术贴沙滩鞋帆布防滑凉拖
结巴分词结果:透气 拖鞋 夏季 一字 拖 男 女士 韩版 学生 简约 魔术 贴 沙滩鞋 帆布 防滑 凉 拖
HanLP分词结果:透气 拖鞋 夏季一 字 拖 男 女士 韩版 学生 简约 魔术 贴 沙滩 鞋 帆布 防滑 凉 拖
个人感觉jieba分词在淘宝体上效果更准一些。
       分完词后,wiki相关文件就可以删除了,文件很大,比较占用空间,示例代码如下:
os.remove("wiki_download/extracted/AA/wiki_00")
os.remove("wiki_download/zhwiki-latest-pages-articles.xml.bz2")
       至此,语料库就生成好了,大概长这个样子(这是我某个版本的语料库,里面有些字符没有剔除):
          
       下面就可以使用gensim工具库训练词向量了,相比较训练过程反而简单了,代码量很少,这也得益于gensim工具库的强大。 示例代码如下:
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logging.info("running %s" % ' '.join(sys.argv))

model = Word2Vec(LineSentence("corpus/corpus_results.txt"), size=200, window=10, min_count=15, workers=4)
model.save("model/model_gram.bin")
model.wv.save_word2vec_format("model/model_vec.bin", binary=True)
       上面的size=200,就是要训练的词向量维度;window=10,为窗口大小,也就是训练时计算当前词和周围多少个词,这个概念有点像卷积核的长度;min_count=5,最小阈值,对于出现次数少于该值的词,会被抛弃掉;workers=4,为训练时开启的线程数量。其他还有很多参数,这里就不一一列举了。训练好词向量后,验证过程也比较简单,示例代码如下:
model = Word2Vec.load('model/model_gram.bin')
result = model.most_similar("麻辣烫")
for word in result:
    print(word.__str__())
       由于我在实际训练时还使用了其他语料,所以是下面这样的结果:
          
       整个训练过程需要用到多个工具库,每个工具库安装及使用都会颇费一些周折,不过按照流程动手做一次,回头再看就很简单了。至于词向量的理论相关知识本文就不做过多介绍了,码字可以,编辑公式有时感觉好繁琐。文章最后还是想吐槽csdn,这次改版真别扭,是为了方便移动端阅读吗?可是大家多数都是在工作时,pc端浏览csdn的,可能是我的猜测过于武断。



猜你喜欢

转载自blog.csdn.net/u013085897/article/details/78575850