使用Python语言利用余弦相似度进行文本选择
余弦相似性简介
余弦相似性相关知识请参考:百度百科(余弦相似度)
二维余弦相似度计算公式: c o s ( θ ) cos(\theta) cos(θ)= x 1 x 2 + y 1 y 2 x 1 2 + y 1 2 ∗ x 2 2 + y 2 2 {x_1x_2+y_1y_2}\over{\sqrt {x_1^2+y_1^2}*\sqrt {x_2^2+y_2^2}} x12+y12∗x22+y22x1x2+y1y2
N维余弦相识度计算公式:
c
o
s
(
θ
)
cos(\theta)
cos(θ)=
∑
k
→
1
k
→
n
x
1
k
x
2
k
∑
k
→
1
k
→
n
x
1
k
∗
∑
k
→
1
k
→
n
x
2
k
{\displaystyle \sum^{k \to n}_{k \to 1}{x_{1k}x_{2k}}}\over{\sqrt {\displaystyle \sum^{k \to n}_{k \to 1}{x_{1k}}}*\sqrt {\displaystyle \sum^{k \to n}_{k \to 1}{x_{2k}}}}
k→1∑k→nx1k∗k→1∑k→nx2kk→1∑k→nx1kx2k
Makedown公式:
'''
$cos(\theta)$=${x_1x_2+y_1y_2}\over{\sqrt {x_1^2+y_1^2}*\sqrt {x_2^2+y_2^2}}$
$cos(\theta)$=${\displaystyle \sum^{k \to n}_{k \to 1}{x_{1k}x_{2k}}}\over{\sqrt {\displaystyle \sum^{k \to n}_{k \to 1}{x_{1k}}}*\sqrt {\displaystyle \sum^{k \to n}_{k \to 1}{x_{2k}}}}$'''
设计思路
从不同数据源抽取的数据进行ETL时候需要从多个相同的备选字段选取一个作为ETL后的字段,于是想到利用余弦相似性选取候选列表里比较靠近质点向量的作为选取属性。
此函数相对简单,至于更为复杂的可能需要自己添加userdict和stopword,或者对字典进行调整。
对所选的字段没有特殊规定,只希望选取有一定的原则(什么原则则无要求),这是简单的算法符合需求的原因。
Python实现
import jieba
import numpy
import sklearn.feature_extraction.text
def getCenterVectorMatrix(text):
'''text为待分析的文本数据列表(矩阵版本)'''
if text:
_text=[]
jieba.enable_paddle()
for item in text:
_text.append(' '.join(jieba.lcut(item,cut_all=False,use_paddle=True)))
#类 CountVectorizer 实现词语切分,频数统计,生成关键词稀疏矩阵
vectorizer = sklearn.feature_extraction.text.CountVectorizer()
#生成列表的TF-IDF词频稀疏矩阵
csr_matrix=vectorizer.fit_transform(_text)
#转换成矩阵
matrix=csr_matrix.todense()
rows,columns=matrix.shape
#求列表向量的质点
particle=[]
for c in range(columns):
sum_column=float(sum(matrix[:,c]))
particle.append(round(sum_column/rows,8))
particle=numpy.array(particle)
#取离质点最近的向量
distance_max=numpy.dot(matrix[0],particle)/(numpy.linalg.norm(matrix[0])*(numpy.linalg.norm(particle)))
number_choice=0
for r in range(rows):
distance=numpy.dot(matrix[r],particle)/(numpy.linalg.norm(matrix[r])*(numpy.linalg.norm(particle)))
if distance_max<distance:
distance_max=distance
number_choice=r
return text[number_choice]
else:
return None