好吧,在处理文本的过程中有陷入了一个胡同,不知道接下来该做啥了。于是又在网上找相关的资料,无意间发现了两篇写得超级超级好的博客,是讲文本相似度,之前也学过,但是这两篇博文写得非常棒,深入浅出。然后也按照博文进行了代码实现,在此记录下,也作为文本相似度相关文章的第一篇。
1 功能分析
通过词频和余弦相似性定理计算句子间的相似度,具体理论讲解见上面提到的两篇博文。
1、TF-IDF与余弦相似性的应用(一):自动提取关键词
2、TF-IDF与余弦相似性的应用(二):找出相似文章
2 代码实现
根据上面博文的讲解,写了一个简单的程序,代码如下,涉及到的余弦定理的计算和角度计算见参考资料。
#-*- coding: UTF-8 -*-
# @Time : 2018/3/23 19:39
# @Author : beibei
# @Site :
# @File : 利用余弦相似性计算句子的相似度.py
# @Software: PyCharm
import sys
import jieba
import numpy as np
def compete_similar(sen1,sen2):
# 1分词
sege1=jieba.cut(sen1)
wordlist_1=[word for word in sege1]
sege2=jieba.cut(sen2)
wordlist_2=[word for word in sege2]
# 2列出所有的词、
word_dict=[]
for word in wordlist_1:
# 如果当前词没有加入词汇表,则将该词加入词汇表
if word not in word_dict:
word_dict.append(word)
else:
continue
for word in wordlist_2:
if word not in word_dict:
word_dict.append(word)
else:
continue
# 3计算词频、4写出词频向量
word_count_1={}
word_count_2={}
word_count_vec_1=[]
word_count_vec_2=[]
# 对于词汇表中的每一个词,统计他在每句话中出现的次数
for word in word_dict:
num1=sen1.count(word)
num2=sen2.count(word)
word_count_1[word]=num1
word_count_2[word]=num2
word_count_vec_1.append(num1)
word_count_vec_2.append(num2)
# 计算相似度
vec_1=np.array(word_count_vec_1)
vec_2=np.array(word_count_vec_2)
one_dot_two=np.dot(vec_1,vec_2)
L1=np.sqrt(np.dot(vec_1,vec_1))
L2=np.sqrt(np.dot(vec_2,vec_2))
# 余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,这就叫"余弦相似性"。
cos_angle=one_dot_two/(L1*L2)
angle_pi=np.arccos(cos_angle)
angle=angle_pi*360/2/np.pi
return angle
# 提示参数问题
def usage():
print (sys.argv[0], " first sentence"," second sentence")
#程序的入口函数
if __name__ == '__main__':
arg_len = len(sys.argv)
# 判断参数是否正确!
if arg_len!=3:
usage()
sys.exit(-1)
# 获取两句话
sentence1=sys.argv[1]
sentence2=sys.argv[2]
# 计算相似性
result=compete_similar(sentence1,sentence2)
# 输出结果
print(result)
运行结果为:
Prefix dict has been built succesfully.
19.1066053509