在目前的行业应用中我们可以使用skip-gram 和 CBOW 模型来进行此过程。在gensim中已经集成了这个算法。下面使用搜狗实验室的新闻语料集合来实现word2vector
使用的数据:搜狗实验室的搜狗新闻语料库
格式说明:
数据格式为
<doc>
<url>页面URL</url>
<docno>页面ID</docno>
<contenttitle>页面标题</contenttitle>
<content>页面内容</content>
</doc>
注意:content字段去除了HTML标签,保存的是新闻正文文本
对提取关键数据文本:语料库中提供了很多的数据项,执行cat news_sohusite_xml.dat | iconv -f gbk -t utf-8 -c | grep "<content>" > corpus.txt
可以只得到content标签的内容,得到文件名为corpus.txt的文件(注意在linux下打开),语聊的格式如下:
[图片上传失败...(image-424924-1585921968718)]
1. 数据预处理
content = ['hello,你好呀',' dadjofjaojfaTest我是英文中隐藏的汉字','如果想 d联系炼我,那就打电话:110!!!','我爱学NLP,!^-^']
# 让文本只保留汉字
def is_chinese(uchar):
if uchar >= u'\u4e00' and uchar <= u'\u9fa5':
return True
else:
return False
def format_str(content):
content_str = ''
for i in content:
if is_chinese(i):
content_str = content_str + i
return content_str
# 参函数传入的是每一句话
chinese_list = []
for line in content:
chinese_list.append(format_str(line))
print(chinese_list)
'''
output:['你好呀', '我是英文中隐藏的汉字', '如果想联系炼我那就打电话', '我爱学']
'''
2. 分词
中文文件直接传给word2vec是需要分词的,这样才可以较好的表达文本的意思。分词可以采用jieba分词实现。
对原始文本内容进行分词,python 程序如下:
filePath = 'D:\\ML_learning\\NLP_data\\corpus.txt'
fileSegWordDonePath = 'D:\\ML_learning\\NLP_data\\corpusSegDone.txt'
fileTrainRead = pd.read_csv(filePath)
fileTrain = pd.Series(fileTrainRead.iloc[:,0])
f = lambda x: x[9:-11]
fileTrain = fileTrain.apply(f)
fileTrain.dropna(how='any')
fileTrainSeg = []
for line in fileTrain:
data = jieba.cut(line, cut_all=False)
# print(list(data))
fileTrainSeg.append(" ".join(list(data)))
output_list = pd.Series(fileTrainSeg)
output_list.to_csv(fileSegWordDonePath, encoding='utf-8')
可以使用Pandas的特性快速批量的对数据进行格式化:
- 使用pd.apply() 来对每行数据进行处理, 一句语句就可以删除所有string的起始的<content> 和结尾的</content>
- 使用dropna 来去除数据为空的行
-
上面的代码中,pandas的Series是一种类似于一维数组的对象,由一组数据和一组与之相关的数据标签(索引)组成,比如:
pd.Series(0,index=['a','b','c']) ''' 执行结果: a 0 b 0 c 0 '''
-
jieba分词有三种模式:全模式、精确模式、搜索引擎模式。全模式和精确模式通过jieba.cut实现
# 全模式 seg_list = jieba.cut("他来到苏州了", cut_all=True) print("【全模式】:" + "/ ".join(seg_list)) ''' 【全模式】:他/ 来到/ 苏州/ 了 '''
3. 构建词向量
from gensim.models import word2vec
import pandas as pd
mopdelfilePath = 'D:\\ML_learning\\NLP_data\\model.bin'
fileSegWordDonePath = 'D:\\ML_learning\\NLP_data\\corpusSegDone.txt'
fileTrainRead = pd.read_csv(fileSegWordDonePath)
train_sentences = pd.Series(fileTrainRead.iloc[:, 1])
f = lambda x: str(x).split(" ")
train_sentences = train_sentences.apply(f)
model = word2vec.Word2Vec(train_sentences, size=300)
model.save(mopdelfilePath)
上面的代码将读入分词文件,并将其传入到word2vec中用来构建词向量,最后将构建出来的词向量保存。这里我们设置word2vec创建300维的词向量。
Word2Vec 参数:
- min_count
model = Word2Vec(sentences, min_count=10) # default value is 5
在不同大小的语料集中,我们对于基准词频的需求也是不一样的。譬如在较大的语料集中,我们希望忽略那些只出现过一两次的单词,这里我们就可以通过设置min_count参数进行控制。一般而言,合理的参数值会设置在0~100之间。
- size
model = Word2Vec(sentences, size=200) # default value is 100
size参数主要是用来设置神经网络的层数,Word2Vec 中的默认值是设置为100层。更大的层次设置意味着更多的输入数据,不过也能提升整体的准确度,合理的设置范围为 10~数百。
- workers
model = Word2Vec(sentences, workers=4) # default = 1 worker = no parallelization
workers参数用于设置并发训练时候的线程数,不过仅当Cython安装的情况下才会起作用:
4. 显示并使用词向量
from gensim.models import word2vec
mopdelfilePath = 'D:\\ML_learning\\NLP_data\\model.bin'
model = word2vec.Word2Vec.load(mopdelfilePath)
print(model.wv['中国'])
可以得到如下结果(300维的一个向量):
[ 2.2904966 -2.2582266 -2.7562246 1.2342433 2.717599 1.377568
2.720106 0.9635297 -1.6690013 1.2432543 2.7351687 2.4857194
....
0.6931309 -1.1371846 -0.8067352 2.2179334 -1.1542435 1.1875417
0.76617193 1.3922322 -2.2338731 0.97370434 1.9159969 -1.706138 ]
保存 and 加载词向量的三种不同格式:
- 以model.save()方法保存词向量(上面用的方法)
- model.save(mopdelfilePath)
- word2vec.Word2Vec.load(model)
- 保存为二进制的词向量
- model.wv.save_Word2Vec_format(embedding_path,binary=True)
- model.wv.save_Word2Vec_format(embedding_path,binary=False)
- gensim.models.KeyedVectors.load_word2vec_format(embedding_path,binary=True)
使用numpy进行保存和加载
保存数组数据的文件可以是二进制格式或者文本格式,二进制格式的文件可以是Numpy专用的二进制类型和无格式类型
5. 查看词表中的词
from gensim.models import word2vec
mopdelfilePath = 'D:\\ML_learning\\NLP_data\\model.bin'
model = word2vec.Word2Vec.load(mopdelfilePath)
index = 1000
print (model.wv.index2word[1000])
得到结果如下:
存款
可以得到词表中第1000个词为: 存款
model.wv['sky']
: 表示输出sky这个词的特征映射结果
model.wv.index2words
: 输出经过映射后的特征名,输出经过映射词的名字
6. 显示空间距离相近的词
一个好的词向量可以实现词义相近的一组词在词向量空间中也是接近的,可以通过显示词向量空间中相近的一组词并判断它们语义是否相近来评价词向量构建的好坏:
from gensim.models import word2vec
mopdelfilePath = 'D:\\ML_learning\\NLP_data\\model.bin'
model = word2vec.Word2Vec.load(mopdelfilePath)
indexes = model.wv.most_similar_cosmul('中国')
for index in indexes:
print(index)
得到的结果如下 与给定词最相近的词以及相似度:
('我国', 0.8150987029075623)
('亚洲', 0.794571578502655)
('印度', 0.7809259295463562)
('国内', 0.7792256474494934)
('日本', 0.7718893885612488)
('美国', 0.7644745707511902)
('全球', 0.7569549083709717)
('本国', 0.7533475160598755)
model.wv.most_similar_cosmul
使用余弦相似度来度量各个单词之前的相似度
7. 查找异类词
model.wv.doesnt_match(['中国','美国','叙利亚','水果'])
上面的输出如下:
'水果'