余弦相似度

目录

一、基本算法--余弦相似度

二、计算余弦相似度

2.1、python实现

2.2、sklearn

2.3、scipy  ---最快

2.4、pytorch

三、参考

一、基本算法--余弦相似度

1、使用TF-IDF算法,找出两篇文章的关键词; 
2、每篇文章各取出若干个关键词(比如20个),合并成一个集合,计算每篇文章对于这个集合中的词的词频TF(为了避免文章长度的差异,可以使用相对词频);
3、生成两篇文章各自的词频向量;
4、计算两个向量的余弦相似度,值越大就表示越相似
   假设向量a、b的坐标分别为(x1,y1)、(x2,y2) 。则:
   
   设向量 A = (A1,A2,...,An),B = (B1,B2,...,Bn) 。推广到多维,数学家已经帮我们证明了,所以你只要记住下面的公式:
   
   简单来说可以写成下面的式子:
   
举一个具体例子,我们先从句子开始:
    句子A:我喜欢看电视,不喜欢看电影。
    句子B:我不喜欢看电视,也不喜欢看电影。
第一步:分词
    句子A:我/喜欢/看/电视,不/喜欢/看/电影。
    句子B:我/不/喜欢/看/电视,也/不/喜欢/看/电影。
第二步:列出所有的词
    我,喜欢,看,电视,电影,不,也
第三步:计算词频
    句子A:我 1,喜欢 2,看 2,电视 1,电影 1,不 1,也 0
    句子B:我 1,喜欢 2,看 2,电视 1,电影 1,不 2,也 1
第四步:写出词频向量
    句子A:[1, 2, 2, 1, 1, 1, 0]
    句子B:[1, 2, 2, 1, 1, 2, 1]
第五步:计算余弦值
   余弦相似度_第1张图片
    余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,这就叫"余弦相似性"
    简单来说上面计算出的值代表两个句子大概九成相似,越接近1就越相似。
     余弦相似度_第2张图片

二、计算余弦相似度

余弦相似度(值越大,两者越相似,向量夹角越小,极限是重合,夹角为0,此时余弦相似度是1)。

2.1、python实现

自己实现一个,按照cos的计算公式——向量的内积除以向量模长的积代码如下:
def python_cos(q_vec, b_vec):
    """
    计算余弦相似度
    :param q_vec: 一维数组
    :param b_vec: 一维数组
    :return:
    """
    dot_q_b = 0
    q_vec_length = 0
    b_vec_length = 0
    for q, b in zip(q_vec, b_vec):
        dot_q_b += q * b
        q_vec_length += q * q
        b_vec_length += b * b
    length = (q_vec_length ** (1 / 2)) * (b_vec_length ** (1 / 2))
    cos_sim = dot_q_b / length  # 向量的内积除以向量模长的积
    return cos_sim

a = [1, 2, 2, 1, 1, 1, 0]
b = [1, 2, 2, 1, 1, 2, 1]
print(python_cos(a, b))   # cos_sim 0.9381941874331419。

2.2、sklearn

sklearn机器学习算法常用库,这个就比较简单了只需要直接调用sklearn中相关的API即可:
pip3 install -U scikit-learn
from sklearn.metrics.pairwise import cosine_similarity

def cos(a, b):
    """
    a和b都要是2维
    """
    cos = cosine_similarity(a,b)
    return cos

a = [[1,2,3],[3,2,1], [3,4,5]]
b = [[3,2,1],[1,2,3]]
print(cos(a, b))

'''结果    a中的每一项与b中每一项的相似度
[[0.71428571  1.        ]
 [1.          0.71428571]
 [0.83152184  0.98270763]]
'''

注意这里的参数,a和b都必须是二维的,不然会报错;a和b中的元素个数不定。

2.3、scipy  ---最快

import scipy.spatial

@coast_time
def cos(a, b):
    '''
    a和b都要是2维,a和b中的元素个数不定
    '''
    dis = scipy.spatial.distance.cdist(a,b,'cosine')
    cos = 1 - dis[0]
    return cos

a = [[1,2,3]]
b = [[3,2,1],[4,5,6], [2,2,3]]
print(cos(a, b))
'''结果
func cos coast time:0.00006230 s
[0.71428571 0.97463185 0.97230559]
'''

注意这里的参数,a和b的数据类型可以是数组、np.array();a和b都必须是二维的;a和b中的元素个数不定。这里dis可以理解为余弦距离,要用1-dis才是余弦相似度。

2.4、pytorch

sklearn机器学习算法常用库,这个就比较简单了只需要直接调用sklearn中相关的API即可:
RuntimeError: expected dtype Double but got dtype Float 问题解决__忽如远行客的博客-CSDN博客
PyTorch  windows安装torch: pip3 install torch torchvision torchaudio
import torch
torch.set_default_tensor_type(torch.FloatTensor)

@coast_time
def torch_cos_new(a, b):
    """
    a,b必须是tensor张量;torch_cos中有个bug,a和b的第一维只能是1,不然会出现错误结果
    """
    cos = torch.cosine_similarity(a, b, dim=1)
    return cos

a = torch.tensor([[1,2,3]]).float()  # 转化为tensor张量
b = torch.tensor([[3,2,1],[4,5,6], [2,2,3]]).float()
print(torch_cos_new(a, b))

'''结果
tensor([0.7143, 0.9746, 0.9723])
func torch_cos_new coast time:0.00072610 s
'''

三、参考

https://www.haitaoseo.com/950191.html  文章相似度检测工具(一种简单高效的算法)

https://github.com/zhao-dapeng/Cosine   zhao-dapeng/Cosine

余弦相似度计算的实现方式_colourmind的博客-CSDN博客_余弦相似度计算代码

你可能感兴趣的:(算法,余弦相似度)