本文的目标是先熟悉文本相似度比较的流程,初衷前文也提过了主要是为了比较两个不同的地址体系,避免纯人工干预,相信论文查重也是部分利用这一原理,当然我对这些package未必理解,先解决会用能解决问题吧。
后续会继续拿神雕三部曲来做示范,把相关流程组装起来。
用Python进行简单的文本相似度分析
使用jieba进行中文分词
利用gensim包分析文档相似度
通过corpora.Dictionary创建预料特征
通过dictionary.doc2bow转换成稀疏矩阵
通过models.TfidfModel完成tfidf统计
通过similarities.SparseMatrixSimilarity进行文档相似度比较
代码示例
代码语言:javascript复制#"""
#用Python进行简单的文本相似度分析
#使用jieba进行中文分词
#利用gensim包分析文档相似度
# 通过corpora.Dictionary创建预料特征
# 通过dictionary.doc2bow转换成稀疏矩阵
# 通过models.TfidfModel完成tfidf统计
# 通过similarities.SparseMatrixSimilarity进行文档相似度比较
import matplotlib
import numpy as np
import jieba
from gensim import corpora,models,similarities
from matplotlib import pyplot as plt
#完成数据初始化工作
doc0 = "海南省金江口花园"
doc1 = "海南省海口市金江口花园"
doc2 = "海南省海口市海甸二西路金江口花园"
doc3 = "金江口花园小区"
doc4 = "金江小区"
doc5 = "海甸二西路"
doc6 = "我住在金江口花园"
doc7 = "金江口花园好玩吗"
doc_test="金江口花园"
#初始化数组,方便后续处理
all_doc = []
all_doc.append(doc0)
all_doc.append(doc1)
all_doc.append(doc2)
all_doc.append(doc3)
all_doc.append(doc4)
all_doc.append(doc5)
all_doc.append(doc6)
all_doc.append(doc7)
print(all_doc)
#all_doc= ['海南省金江口花园', '海南省海口市金江口花园', '海南省海口市海甸二西路金江口花园', '金江口花园小区', '金江小区', '海甸二西路', '我住在金江口花园', '金江口花园好玩吗']
#初始化分词后的数组
all_doc_list = []
#需要对个别词进行自定义词典
jieba.add_word('金江口')
for doc in all_doc:
doc_list = [word for word in jieba.cut(doc)]
all_doc_list.append(doc_list)
#all_doc_list= <class 'list'>:
# [['海南省', '金江口', '花园'],
# ['海南省', '海口市', '金江口', '花园'],
# ['海南省', '海口市', '海甸二', '西路', '金江口', '花园'],
# ['金江口', '花园', '小区'],
# ['金江', '小区'],
# ['海甸二', '西路'],
# ['我', '住', '在', '金江口', '花园'],
# ['金江口', '花园', '好玩', '吗']]
#对目标文章进行分词
doc_test_list = [word for word in jieba.cut(doc_test)]
print('doc_test_list=',doc_test_list)
#doc_test_list= ['金江口', '花园']
#doc_test_list= ['金', '江口', '花园']
#调用Gensim提供的API建立语料特征(此处即是word)的索引字典
# texts就是若干个被拆成单词集合的文档的集合
# 而dictionary就是把所有单词取一个set()
# 并对set中每个单词分配一个Id号的map;
dictionary = corpora.Dictionary(all_doc_list)
print('dictionary=',dictionary)
#dictionary= Dictionary(13 unique tokens: ['海南省', '花园', '金江口', '海口市', '海甸二']...)
#dictionary= Dictionary(14 unique tokens: ['江口', '海南省', '花园', '金', '海口市']...)
#打印语料特征索引字典的key值
print('dictionary.keys=',dictionary.keys())
#dictionary.keys= [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
#dictionary.keys= [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
#打印语料特征索引字典内容
print('dictionary.token2id=',dictionary.token2id)
#dictionary.token2id= {'海南省': 0, '花园': 1, '金江口': 2, '海口市': 3, '海甸二': 4, '西路': 5, '小区': 6, '金江': 7, '住': 8, '在': 9, '我': 10, '吗': 11, '好玩': 12}
#dictionary.token2id= {'江口': 0, '海南省': 1, '花园': 2, '金': 3, '海口市': 4, '海甸二': 5, '西路': 6, '小区': 7, '金江': 8, '住': 9, '在': 10, '我': 11, '吗': 12, '好玩': 13}
#dictionary.doc2bow(doc)是把源文档 doc变成一个稀疏向量,[(0, 1), (1, 1)],表明id为0,1的词汇出现了1次,至于其他词汇,没有出现。
corpus = [dictionary.doc2bow(doc) for doc in all_doc_list]
print('corpus=',corpus)
#corpus= [[(0, 1), (1, 1), (2, 1)], [(0, 1), (1, 1), (2, 1), (3, 1)], [(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1)], [(1, 1), (2, 1), (6, 1)], [(6, 1), (7, 1)], [(4, 1), (5, 1)], [(1, 1), (2, 1), (8, 1), (9, 1), (10, 1)], [(1, 1), (2, 1), (11, 1), (12, 1)]]
#corpus= [[(0, 1), (1, 1), (2, 1), (3, 1)], [(0, 1), (1, 1), (2, 1), (3, 1), (4, 1)], [(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)], [(0, 1), (2, 1), (3, 1), (7, 1)], [(7, 1), (8, 1)], [(5, 1), (6, 1)], [(0, 1), (2, 1), (3, 1), (9, 1), (10, 1), (11, 1)], [(0, 1), (2, 1), (3, 1), (12, 1), (13, 1)]]
#dictionary.doc2bow(doc)是把目标文档 doc变成一个稀疏向量,[(0, 1), (1, 1)],表明id为0,1的词汇出现了1次,至于其他词汇,没有出现。
doc_test_vec = dictionary.doc2bow(doc_test_list)
print('doc_test_vec=',doc_test_vec)
#doc_test_vec= [(1, 1), (2, 1)]
#doc_test_vec= [(0, 1), (2, 1), (3, 1)]
# corpus是一个返回bow向量的迭代器。
# 下面将完成对corpus中出现的每一个特征的IDF值的统计工作,对源文档
tfidf = models.TfidfModel(corpus)
corpus_tfidf = tfidf[corpus]
print('tfidf=',tfidf)
#tfidf= TfidfModel(num_docs=8, num_nnz=29)
#tfidf= TfidfModel(num_docs=8, num_nnz=35)
print('tfidf[doc_test_vec]=',tfidf[doc_test_vec])
#tfidf[doc_test_vec]= [(1, 0.7071067811865476), (2, 0.7071067811865476)]
#tfidf[doc_test_vec]= [(0, 0.5773502691896257), (2, 0.5773502691896257), (3, 0.5773502691896257)]
#查看model中的内容
for item in corpus_tfidf:
print(item)
# 下面将完成对corpus中出现的每一个特征的IDF值的统计工作,对目标文档
print('tfidf[doc_test_vec]=',tfidf[doc_test_vec])
#tfidf[doc_test_vec]= [(1, 0.7071067811865476), (2, 0.7071067811865476)]
#tfidf[doc_test_vec]= [(0, 0.5773502691896257), (2, 0.5773502691896257), (3, 0.5773502691896257)]
##对每个目标文档,分析测试文档的相似度
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=len(dictionary.keys()))
sim = index[tfidf[doc_test_vec]]
print('index=',index)
#index= <gensim.similarities.docsim.SparseMatrixSimilarity object at 0x00000167D46412B0>
#index= <gensim.similarities.docsim.SparseMatrixSimilarity object at 0x0000028C96C922B0>
print('sim=',sim)
#sim= [0.38314244 0.23298258 0.15496162 0.28159946 0. 0. 0.11224506 0.1370406 ]
#sim= [0.45292395 0.2815491 0.18865925 0.33824706 0. 0. 0.1370406 0.16705726]
#按顺序打印相似度的文档
print(sorted(enumerate(sim), key=lambda item: -item[1]))
#[(0, 0.38314244), (3, 0.28159946), (1, 0.23298258), (2, 0.15496162), (7, 0.1370406), (6, 0.11224506), (4, 0.0), (5, 0.0)]
#[(0, 0.45292395), (3, 0.33824706), (1, 0.2815491), (2, 0.18865925), (7, 0.16705726), (6, 0.1370406), (4, 0.0), (5, 0.0)]
fig,ax=plt.subplots()
pos=np.arange(0,len(all_doc)) #pos= [0 1 2 3 4 5 6 7]
xlabel=['第' str(x 1) '行' for x in range(len(all_doc))]
#xlabel= ['第1章', '第2章', '第3章', '第4章', '第5章', '第6章', '第7章', '第8章']
matplotlib.rcParams['font.sans-serif']=['SimHei'] # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus']=False # 正常显示负号
ax.bar(pos,sim,0.5)
ax.set_xticks(range(len(xlabel)))
ax.set_xticklabels(xlabel)
plt.xticks(rotation=90) # 将字体进行旋转
plt.show()
# 文章相似度比较的步骤和流程
# 1、读取文档
# 2、 对要计算的多篇文档进行分词
# 3、对文档进行整理成指定格式,方便后续进行计算
# 4、计算出词语的词频
# 5、【可选】对词频低的词语进行过滤
# 6、建立语料库词典
# 7、加载要对比的文档
# 8、将要对比的文档通过doc2bow转化为词袋模型
# 9、对词袋模型进行进一步处理,得到新语料库
# 10、将新语料库通过tfidfmodel进行处理,得到tfidf
# 11、通过token2id得到特征数
# 12、稀疏矩阵相似度,从而建立索引
# 13、得到最终相似度结果