1, 前言
本来不打算使用python版的Word2Vec的。但是考虑到以后方便更新词向量库,所以就研究了下利用python从原始语料入手,生成一个词向量的过程。
2,环境
python 2.7
gensim 2.3.0
scipy 0.19.1
Word2Vec在gensim库中,所以要先安装gensim。使用命令 pip install gensim是可以直接一步安装的。但是谁让python是外国人发明的呢,下载速度感人。基本上使用pip安装的时候都会出现time out的错误。所以建议先把whl文件下载到本地,再安装。博主在安装gensim的时候还会需要若干个其他的文件,根据安装gensim的提示的错误分别下载所需要的文件即可。还有gensim对其他文件版本还有若干要求。总之,就是因为网的问题,本来一个命令就可以完成的事,搞得比较麻烦。
3,分词
使用的分词工具是结巴分词的python版本。详情参考https://github.com/fxsjy/jieba。
4,Word2Vec
google提出的Word2Vec,对于NLP有极大的帮助促进作用。它能根据原始文本语料对每个词生成一个词向量。有了词向量,我们就能利用机器学习的相关算法来方便的处理文本信息,像文本的情感分析,文本分类等。Word2Vec的算法有两种,CBOW和Skip-gram。python版本的Word2Vec只实现了Skip-gram。两种算法生成的词向量是不能相互引用的,博主先开始利用python程序引用使用cbow生成的词向量集,结果程序直接报错
再安装好gensim库后,训练语料就非常简单了,使用如下一句就可以:
model = word2vec.Word2Vec('分好词的原始数据', 其他参数)
然后如果想要保存训练好的数据集的话使用
model.save('要保存的文件名路径')
如果需要某个词的词向量使用
model[u'喜欢']
就会返回一个list表示的词向量了。
5,输入的原始数据的格式
Word2Vec最早是在linux上用C写的。如果在官网上安装了C版本的Word2Vec的话,会提供几个demo示例。在linux下使用 ./demo-word.sh 就会下载一个text8文件内容大致如下:
我们可以发现英文要训练的数据集只是单纯的用空格分隔了每一个词。所以对于中文语料只需要将每个句子分词,然后用空格分开就可以了。
所以本文对原始文本分词处理的方法是:原始文本中每一句话占文本一行,除去句中除中文英文以及数字之外的所有符号,词与词之间利用空格分开。word2vec中是以行为单位来处理文本的,所以尽量每一个句子占一行。
大致代码如下:
def get_fenci(inputfilename, outputfilename):
# jieba.initialize()
inf = open(inputfilename, 'r')
inf1 = open(outputfilename, 'a')
all_text = re.split(u'。|;|!|?|\.|;|!|\?', inf.read().strip())
# print all_text
for i in range(all_text.__len__()):
words = jieba.lcut(all_text[i])
for word in words:
if not check_contain_other_words(word):
inf1.write(word + ' ')
inf1.write('\n') #每个句子占分词文件的一行
inf.close()
inf1.close()
def check_contain_other_words(check_str):
"""判断字符串是否只含有汉字数字和英文字母,含有其他字符返回Ture"""
for ch in check_str.decode('utf-8'):
if not (is_chinese(ch) or is_number(ch) or is_alphabet(ch)):
return True
return False
def is_chinese(uchar):
"""判断一个unicode是否是汉字"""
if u'\u4e00' <= uchar <= u'\u9fa5':
return True
else:
return False
def is_number(uchar):
"""判断一个unicode是否是数字"""
if u'\u0030' <= uchar <= u'\u0039':
return True
else:
return False
def is_alphabet(uchar):
"""判断一个unicode是否是英文字母"""
if (u'\u0041' <= uchar <= u'\u005a') or (u'\u0061' <= uchar <= u'\u007a'):
return True
else:
return False
得到的数据集大致如下所示:
6,原始数据集
由于博主目前只是为了验证一下,因此使用的数据集很小。只是采用了搜狗实验室新闻报道数据集中的财经类数据。分词后大概有12M。在博主这四五年前的笔记本上跑,大概跑了一分多钟吧(尴尬脸)
原始数据集如下:
总结
由于博主也是最近才开始接触机器学习相关的知识的。而对文本的情感分析比较感兴趣。所以就研究了下关于这方面的知识。也算是一个学习记录的过程吧。最后,完整的代码和原始数据集以及分好词的数据集请在这里获取
上传的文件被很多人举报了,说我发布虚假文件,骗他们积分。好吧,对此我表示无语。给各位大佬跪了。
还有本人现在已经不搞机器学习了(苦笑脸),专心做研发。
告辞!
2019-03-13 16:17