本文将展示gensim的一些用法。python环境:Anaconda3(Python3.7)
使用gensim做自然语言处理的一般思路是:使用(处理)字典 ----> 生成(处理)语料库 ----> 自然语言处理(tf-idf的计算等)
利用列表生成字典(dict):
#导入模块
from gensim import corpora
from pprint import pprint #格式化输出
#三个存放分好词的文本列表
word_list1 = ['我','来自','中国','我']
word_list2 = ['我们','来自','火星']
word_list3 = ['你','来自','何方']
#利用list1和list2生成一个词典
dict = corpora.Dictionary([word_list1,word_list2])
print('由list1和list2生成的词典:')
print(dict)
dict.add_documents([word_list3])
print('由list3拓展生成的词典:')
print(dict)
dict.save('test.dict') #保存字典
dict = corpora.Dictionary.load('test.dict') #加载字典
需要注意的是,corpora.Dictionary()方法,括号里面的对象的形式是这样的:[ [list1] , [list2] ]。
以上代码的运行结果如下:
由list1和list2生成的词典:
Dictionary(5 unique tokens: ['中国', '我', '来自', '我们', '火星'])
由list3拓展生成的词典:
Dictionary(7 unique tokens: ['中国', '我', '来自', '我们', '火星']...)
表明已经生成了字典对象。接下来,通过一些方法来查看字典对象的一些属性:
dict.dfs | 返回字典:{ 单词id:在多少文档中出现 } |
dict.num_docs | 返回文档数目 |
dict.num_pos | 返回词的总数(不去重) |
dict.token2id | 返回字典:{ 单词:id } |
dict.id2token | 返回字典:{ id: 单词 } |
dict.items() | 返回对象:[(id,词)],查看需要循环 |
token:百度的意思是标记,但实际情况是表示字典中的词;id:则是每一个词在字典中独一无二的编号。(词袋中的索引值)
下面用代码来演示以下dict的属性。
print ('dfs:', dict.dfs) # 字典词频,{单词id,在多少文档中出现}
print ('num_docs:', dict.num_docs) # 文档数目
print ('num_pos:', dict.num_pos ) # 所有词的个数(不去重)
word_id_dict = dict.token2id # 生成{词:id}这样一个字典
id_word_dict = dict.id2token # 生成{id:词}这样一个字典
print('word_id_dict:',word_id_dict)
print('id_word_dict:',id_word_dict)
id_word_list = dictionary.items()
print ('id_word_dict:',id_word_list)
for itm in id_word_list:
print (itm[0], itm[1])
运行结果如下:
dfs: {1: 1, 2: 3, 0: 1, 3: 1, 4: 1, 6: 1, 5: 1}
num_docs: 3
num_pos: 10
word_id_dict: {'中国': 0, '我': 1, '来自': 2, '我们': 3, '火星': 4, '何方': 5, '你': 6}
id_word_dict: {} #这里本应是与上一行相反的结果,未找出原因,后面更正
#理论上结果为:
#id_word_dict: { 0 :'中国', 1 :'我', 2 :'来自', 3 :'我们', 4 :'火星', 5 :'何方', 6:'你' }
id_word_dict: ItemsView()
0 中国
1 我
2 来自
3 我们
4 火星
5 何方
6 你
得到一个字典后,如果想要进行过滤(或者说去除处理),那么可以使用以下方法:
print(dictionary) #未过滤前的字典
dictionary.filter_n_most_frequent(1) #过滤掉出现频率最高的1个单词(参数决定)
print(dictionary) #过滤后的字典
#运行结果:少了‘来自’这个词
Dictionary(7 unique tokens: ['中国', '我', '来自', '我们', '火星']...)
Dictionary(6 unique tokens: ['中国', '我', '我们', '火星', '何方']...)
过滤词汇还可以使用 :dict.filter_extremes()
它有四个参数:no_below, no_above, keep_n, keep_tokens。遵循以下原则:
下面用代码来演示一下:
#以下是我们的字典及其在文档出现的文档数
#{'中国': 1, '我': 1, '来自': 3, '我们': 1, '火星': 1, '何方': 1, '你': 1}
print(dict)
dict.filter_extremes(no_below=2, no_above=0.5, keep_n=1000, keep_tokens=['中国','我'])
#no_below:不要少于多少文档;no_above:不要超过多少(百分数)文档
#keep_n:受前面约束保留的前几个词;keep_tokens:不受约束保留的具体的词
print(dict)
#运行结果
Dictionary(7 unique tokens: ['中国', '我', '来自', '我们', '火星']...)
Dictionary(2 unique tokens: ['中国', '我'])
以上代码去除的是:只在一篇文档出现的,多于一半文档出现的。理论上所有的会过滤掉。但是我们保留了'中国','我'两个词,最终结果也只剩下这两个。
接下来的步骤进行语料库的处理:
word_bow1 = dictionary.doc2bow(word_list1, allow_update=False) #词袋[(id,num)],稀疏向量
word_bow2 = dictionary.doc2bow(word_list2) #将词列表转换成稀疏词袋向量
word_bow3 = dictionary.doc2bow(word_list3) #将词列表转换成稀疏词袋向量
print ('word_bow1:', word_bow1)
print ('word_bow2:', word_bow2)
print ('word_bow3:', word_bow3)
corpus = [word_bow1, word_bow2, word_bow3] #由词袋向量组成的列表构成语料
print(corpus)
#运行结果
word_bow1: [(0, 1), (1, 2), (2, 1)]
word_bow2: [(2, 1), (3, 1), (4, 1)]
word_bow3: [(2, 1), (5, 1), (6, 1)]
[[(0, 1), (1, 2), (2, 1)], [(2, 1), (3, 1), (4, 1)], [(2, 1), (5, 1), (6, 1)]]
词袋形象地解释便是:将文本中的词放入一个袋子里,在袋子中,词拥有两个属性编号和数目(id,num)。一个词袋对应一篇文档。由元组(id,num)构成的 [(0, 1), (1, 2), (2, 1)] 则称作稀疏向量。一般语料库都是用这种方式来表示(gensim中)。
接下来,便是使用模型来计算tf-idf:
from gensim import models
#根据语料库和字典生成模型
tfidf_model = models.TfidfModel(corpus=corpus, dictionary=dict)
tfidf_model.save('test_tfidf.model') #保存模型到本地
tfidf_model = models.TfidfModel.load('test_tfidf.model') #载入模型
corpus_tfidf = [tfidf_model[doc] for doc in corpus]
print ('TF-IDF:')
for tfidf in corpus_tfidf:
print (tfidf)
#运行结果
TF-IDF:
[(0, 0.4472135954999579), (1, 0.8944271909999159)]
[(3, 0.7071067811865475), (4, 0.7071067811865475)]
[(5, 0.7071067811865475), (6, 0.7071067811865475)]
以上便是gensim库的简单使用,具体情况再具体分析。