实验——wiki训练词向量

前言

下面的步骤是个人实验过程。亲测可行,实验结果是利用维基百科的数据训练了100维的词向量,已完成的词向量分享给大家。附下载链接。大家也可按照实验步骤自行尝试。

数据下载

我们使用维基百科训练词向量。附:维基百科数据下载地址

抽取wiki正文内容

下载下来的wiki是XML格式,需要提取其正文内容。无论是python2.7还是3.X版本,我们都可以使用一个开源的解压项目来抽取数据正文。具体流程是:
1.将刚才下载到未解压的维基百科也放入该项目目录下
2.使用cmd进入该项目目录下。
3.执行命令:WikiExtractor.py -cb 1200M -o extracted zhwiki-latest-pages-articles.xml.bz2。该命令的含义是:-cb 1200M表示以 1200M 为单位切分文件,-o 后面接出入文件,最后是输入文件。
注:有的博客是使用开源工具wikipedia extractor完成正文的提取。该py文件只适用于2.7版本。如果你是3.5版本,还需要修改该py文件引入的包名,比较麻烦。而上面github项目的文件,在代码中加入了版本判断条件,运行时自动引用该版本的包模块,编写更完善合理,所以不分版本都可以运行。执行完毕如下:
这里写图片描述执行后,我们得到提取的文件,位于wiki_download\wikiextractor-master\extracted\AA,文件名为wiki.00的压缩文件。

繁体转简体

大多使用工具opencc来转换。使用ubuntu系统,终端下执行sudo apt-get install opencc安装opencc,将上一步我们得到的wiki.00文件解压,并将解压后文件重命名为wiki.txt,在终端下进入wiki.txt所在目录,执行opencc -i wiki.txt -o wiki.zh.text.jian -c zht2zhs.ini 大概三四分钟,得到新简体文件wiki.zh.text.jian。
转换前:
这里写图片描述
转换后:
这里写图片描述
注:我尝试了windows下使用opencc,尝试运行opencc -i wiki.00 -o wiki.zh.jian.text -c t2s.json提示错误:opencc不是内部或外部命令…….,失败。尝试下载不同的opencc均报该错误,不知道怎么解决,就放弃这种方法了。有解决的朋友赐教一下。

分词

这里我们使用jieba分词工具进行分词。首先安装jieba模块:在cmd中输入pip install jieba即可安装,然后使用下面的程序对wiki.zh.text.jian文件进行分词。

import jieba
import jieba.analyse
import jieba.posseg as pseg
import codecs,sys
def cut_words(sentence):
    #print sentence
    return " ".join(jieba.cut(sentence)).encode('utf-8')
f=codecs.open('wiki.zh.text.jian','r',encoding="utf8")
target = codecs.open("wiki.zh.jian.seg.txt", 'w',encoding="utf8")
print ('open files')
line_num=1
line = f.readline()
while line:
    print('---- processing', line_num, 'article----------------')
    line_seg = " ".join(jieba.cut(line))
    target.writelines(line_seg)
    line_num = line_num + 1
    line = f.readline()
f.close()
target.close()
exit()
while line:
    curr = []
    for oneline in line:
        #print(oneline)
        curr.append(oneline)
    after_cut = map(cut_words, curr)
    target.writelines(after_cut)
    print ('saved',line_num,'articles')
    exit()
    line = f.readline1()
f.close()
target.close()


'''作者:wwlovett
链接:https://www.jianshu.com/p/af02db32fac2
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
'''

得到分词后的文件:wiki.zh.jian.seg.txt
这里写图片描述

使用word2vec训练词向量

使用以下python代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import os
import sys
import multiprocessing

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))

    model = Word2Vec(LineSentence("wiki.zh.jian.seg.txt"), size=100, window=5, min_count=5,
                     workers=multiprocessing.cpu_count(),iter=100)

    # trim unneeded model memory = use(much) less RAM
    # model.init_sims(replace=True)
    model.save("model/model_gram.bin")
    model.wv.save_word2vec_format("model/model_vec.bin", binary=False)

运行时报错:UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xff in position 0: invalid start byte。

文件中包含非utf-8字符,我们可以用iconv来处理这个问题。iconv(http://www.gnu.org/software/libiconv/)是一个开源的字符编码转换库,可以“方便”的完成几乎所有的编码转换工作。
linux系统下默认已经引入,可以直接输入命令iconv -c -t UTF-8 wiki.zh.jian.seg.txt > wiki.zh.text.jian.seg.utf-8即可得到转换后的wiki.zh.text.jian.seg.utf-8文件(若运行该命令出现错误:iconv: unable to allocate buffer for input: Cannot allocate memory,不用担心,尝试重新运行该命令即可)。windows下必须要自己下载iconv.exe。将该exe放入任意目录,cmd进入该目录后,输入上述命令即可转换成功。

以上解决来自博客。按理说工具和命令都没有错,可是我转换后打开文件wiki.zh.text.jian.seg.utf-8发现里面乱码,我暂时忽略继续训练词向量,训练出来的vector也是乱码。证明是转码出现了问题。下面是我自己解决问题的方法:
首先,我用以下代码检测文件wiki.zh.jian.seg.txt的编码方式:

# -*- coding: utf-8 -*-
import chardet
f = open('wiki.zh.jian.seg.txt','rb')# 要有"rb",如果没有这个的话,默认使用gbk读文件。          
data = f.read()
print(chardet.detect(data))
f.close()

输出显示是utf-16编码。接着用下面的自己编写的代码进行转码:

# -*- coding: utf-8 -*-  
import sys,io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') 
with open('wiki.zh.jian.seg.utf8.txt', 'w', encoding='UTF-8') as source:
    file = open('e:/wiki.zh.jian.seg.txt', 'r', encoding='utf-16')
    for line in file:
        source.write(line+'\n')
    file.close()

打开转码后的文件wiki.zh.jian.seg.utf8.txt发现正常显示。好,我们开始训练词向量。首先,新建test.py文件,代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import os
import sys
import multiprocessing

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=100, window=5, min_count=5,
                     workers=multiprocessing.cpu_count(),iter=100)

    # trim unneeded model memory = use(much) less RAM
    # model.init_sims(replace=True)
    model.save(outp1)
    model.wv.save_word2vec_format(outp2, binary=False)
  • 其中word2vec的常用参数解释如下:
    · size:是指特征向量的维度,默认为100。大的size需要更多的训练数据,但是效果会更好. 推荐值为几十到几百。
    · window:表示当前词与预测词在一个句子中的最大距离是多少
    · alpha: 是学习速率
    · seed:用于随机数发生器。与初始化词向量有关。
    · min_count: 可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5
    在命令行中输入运行指令:python test.py wiki.zh.jian.seg.utf8.txt wiki.zh.text.model wiki.zh.text.vector

运行过程:
这里写图片描述

运行完成后得到四个文件wiki.zh.text.model、wiki.zh.text.model.syn1neg.npy、wiki.zh.text.model.wv.syn0.npy、wiki.zh.text.vector
其中,最后一个文件存储着我们训练得到的词向量,大致内容如下:
这里写图片描述

实验测试

以下是测试代码:

import gensim

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

print (model['计算机'])

结束

本来想直接引用别人训练好的资源,结果运行github上的现有项目出错了,所以自己动手做一遍。网上有很多类似的教程,一开始觉得很简单照做就是了,但结果发现每个教程每个阶段的实验结果跟自己的不完全相同,结果我找四五个博客尝试了三次才成功。花费了两三天的时间(只是训练词向量阶段就要十几个小时)。最后,有以下建议:

  • 每一个实验阶段,可以使用utltraedit编辑器打开看看文件内容,有助于定位问题所在
  • 每次训练需要十几个小时,所以当不确定自己是否得到正确的分词文件,可以先取一小部分快速进行训练,看看是否正确运行,能生成对应文件。
发布了164 篇原创文章 · 获赞 69 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/wqy20140101/article/details/79129889