1、给定训练语料生成语料的tfidf向量和lsi向量;
2、对新的测试语料,用tfidf和lsi 判断其和训练语料的相似度。
import jieba
from gensim import corpora, models
from gensim.similarities import Similarity
#jieba.load_userdict("userdict.txt")
stopwords = set(open('./doc/stopword.txt',encoding='utf8').read().strip('\n').split('\n')) #读入停用词
raw_documents = [ '0无偿居间介绍买卖毒品的行为应如何定性', '1吸毒男动态持有大量毒品的行为该如何认定', '2如何区分是非法种植毒品原植物罪还是非法制造毒品罪', '3为毒贩贩卖毒品提供帮助构成贩卖毒品罪', '4将自己吸食的毒品原价转让给朋友吸食的行为该如何认定', '5为获报酬帮人购买毒品的行为该如何认定', '6毒贩出狱后再次够买毒品途中被抓的行为认定', '7虚夸毒品功效劝人吸食毒品的行为该如何认定', '8妻子下落不明丈夫又与他人登记结婚是否为无效婚姻', '9一方未签字办理的结婚登记是否有效', '10夫妻双方1990年按农村习俗举办婚礼没有结婚证 一方可否起诉离婚', '11结婚前对方父母出资购买的住房写我们二人的名字有效吗', '12身份证被别人冒用无法登记结婚怎么办?', '13同居后又与他人登记结婚是否构成重婚罪', '14未办登记只举办结婚仪式可起诉离婚吗', '15同居多年未办理结婚登记,是否可以向法院起诉要求离婚' ]
corpora_documents = []
for item_text in raw_documents:
item_str = jieba.lcut(item_text)
corpora_documents.append(item_str)
dictionary = corpora.Dictionary(corpora_documents)
print("dictionary"+str(dictionary))
# dictionary.save('dict.txt') #保存生成的词典
#dictionary=Dictionary.load('dict.txt')#加载
# 通过下面一句得到语料中每一篇文档对应的稀疏向量(这里是bow向量)
corpus = [dictionary.doc2bow(text) for text in corpora_documents]
# 向量的每一个元素代表了一个word在这篇文档中出现的次数
print("corpus:"+str(corpus))
#转化成tf-idf向量
# corpus是一个返回bow向量的迭代器。下面代码将完成对corpus中出现的每一个特征的IDF值的统计工作
tfidf_model=models.TfidfModel(corpus)
corpus_tfidf = [tfidf_model[doc] for doc in corpus]
print('语料的TFIDF向量',corpus_tfidf)
'''''
#查看model中的内容
for item in corpus_tfidf:
print(item)
# tfidf.save("data.tfidf")
# tfidf = models.TfidfModel.load("data.tfidf")
# print(tfidf_model.dfs)
'''
#转化成lsi向量
lsi= models.LsiModel(corpus_tfidf,id2word=dictionary,num_topics=50)
corpus_lsi = [lsi[doc] for doc in corpus]
print("语料的LSI:"+str(corpus_lsi))
similarity_lsi=Similarity('Similarity-Lsi-index', corpus_lsi, num_features=400,num_best=5)
# 1.测试数据
test_data_1 = '你好,我想问一下我想离婚他不想离,孩子他说不要,是六个月就自动生效离婚'
test_cut_raw_1 = jieba.lcut(test_data_1)
print('测试数据',test_cut_raw_1)
# 2.转换成bow向量 # [(51, 1), (59, 1)],即在字典的52和60的地方出现重复的字段,这个值可能会变化
test_corpus_3 = dictionary.doc2bow(test_cut_raw_1)
print('测试语料',test_corpus_3)
# 3.计算tfidf值 # 根据之前训练生成的model,生成query的TFIDF值,然后进行相似度计算
test_corpus_tfidf_3 = tfidf_model[test_corpus_3]
print('TFIDF值',test_corpus_tfidf_3) # [(51, 0.7071067811865475), (59, 0.7071067811865475)]
# 4.计算lsi值
test_corpus_lsi_3 = lsi[test_corpus_tfidf_3]
print('LSI值',test_corpus_lsi_3)
# lsi.add_documents(test_corpus_lsi_3) #更新LSI的值
print('——————————————lsi———————————————')
# 返回最相似的样本材料,(index_of_document, similarity) tuples
print('相似度:',similarity_lsi[test_corpus_lsi_3])
问题及思考:
1、LsiModel里面的num_topic=50,预设最多有50个主题,但其实只有语料库只有15个文档,即生成的lsi向量的长度为15。所谓隐语义模型,其本质是topic作为中间量。
2、产生的LSI向量到底是什么? 源码里解释如下,model[语料],可知,LSI向量其实是右奇异值矩阵,每个文档和主题的对应关系。在这种情况下,U∈ℝ^(m⨉t)是我们的文档-主题矩阵,而 V∈ℝ^(n⨉t)则成为我们的术语-主题矩阵。在矩阵 U 和 V 中,每一列对应于我们 t 个主题当中的一个。在 U 中,行表示按主题表达的文档向量;在 V 中,行代表按主题表达的术语向量。
Notes
-----
* :attr:`gensim.models.lsimodel.LsiModel.projection.u` - left singular vectors,
* :attr:`gensim.models.lsimodel.LsiModel.projection.s` - singular values,
* ``model[training_corpus]`` - right singular vectors (can be reconstructed if needed).