相似度与相异度

2024-02-04 10:30
文章标签 相似 相异

本文主要是介绍相似度与相异度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

第1关:用相关系数计算直线之间的相似度

任务描述

相关知识

欧几里得相关系数

余弦相关系数

泊松相关系数

编程要求

测试说明

代码:

第2关:基于相似度度量的商品推荐

相关知识

协同过滤算法基本原理

协同过滤算法的实现步骤

编程要求

测试说明

代码:


第1关:用相关系数计算直线之间的相似度

任务描述

本关任务:计算各种相关系数方法下的直线(数据)相似度

相关知识

为了完成本关任务,你需要掌握:

  1. 欧几里得相关系数
  2. 余弦相关系数
  3. 泊松相关系数(也称皮尔逊相关系数)

欧几里得相关系数

利用欧几里得相关系数计算数据集的的相似度,一般是基于每对对象间的距离计算的。 其原理公式为:

def euclidean(p, q):# 如果两数据集数目不同,计算两者之间都对应有的数same = 0for j in p:if j in q:same += 1# 计算欧几里德距离,并将其标准化e = sum([(p[j] - q[j]) ** 2 for j in range(same)]) return 1 / (1 + e ** 0.5) 
euclidean([1, 2, 3, 4, 5],[2, 4, 6, 8, 10]) 

输出:0.3090169943749474

余弦相关系数

余弦相似度,取值在-1和1之间。如果两个向量方向相反,那么等于-1;如果两个向量方向相同,那么等于1。所以,两个向量之间的夹角越小,其夹角余弦越大(越相似)。因此余弦相似度可以用来度量两个变量之间的相似程度。

因为我们需要对比的是直线之间的相似度,根据数据集之间的数据距离来计算相似度明显不太可取。所以,我们需要利用余弦相关系数来计算直线之间的相似度。就比如直线y=5x+3与直线y=5x+8的相似度。即可以看出两个数据集[5,3]与[5,8].计算它们之间的相似度如下: 余弦相关系数原理公式为:

代码如下:

def cosine_similarity(x, y):xx = 0.0yy = 0.0xy = 0.0for i in range(len(x)):xx += x[i] * x[i]yy += y[i] * y[i]xy += x[i] * y[i] xx_sqrt = xx ** 0.5print(xx)print(yy)print(xy)yy_sqrt = yy ** 0.5cos = xy/(xx_sqrt*yy_sqrt)return cos
cosine_similarity([5,3],[5,8])

输出:0.890761869708233

泊松相关系数

上述余弦相关系数所使用的数据(两条直线)是二维数据,当我们将数据集扩增到多维数据时,即数据集(x1,x2,...,xn)与数据集(y1,y2,...,yn),对这些数据进行标准化,获得的向量之间的夹角的余弦,即皮尔逊相关系数。 其原理如图所示:

接下来我们选取deaths.csv(已上传数据集)中的一部分数据,即选取用户用户(UID)84001001与用户(UID)84001003从2004/1/20到2004/20/20这段日期的数据,再比较相似度。 获取数据代码如下:

import pandas as pd
df=pd.csv('./deaths.csv')
print(df.head)
print(df.loc[[0,1,16],'2004/1/20':'4/20/20'].values.tolist()) # 选取了第0,1,16行的用户从2004/1/20到2004/20/20这段日期的数据

print(df.head)的截图如下:

获得的三行数据如下: [[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

#泊松相关系数
import scipy
import numpy
from scipy.stats import pearsonr
x =numpy.array([0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,1])
y =numpy.array([1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,3])
r_row, p_value = pearsonr(x, y)
print ("用户(UID)84001001与用户(UID)84001003从2004/1/20到4/20/20这段日期的相似度为",r_row)
# print (p_value)

输出如下: 用户(UID)84001001与用户(UID)84001003从2004/1/20到4/20/20这段日期的相似度为 0.5508226327552435

编程要求

请从数据集中获得数据,计算用户(UID)84001033与用户(UID)84001003从2004/1/20到4/20/20这段日期的相似度(其中用户84001033序号即为16)

测试说明

平台会对你编写的代码进行测试: 预期输出:用户(UID)84001033与用户(UID)84001003从2004/1/20到4/20/20这段日期的相似度为 0.44908871313907184。

代码:

# 欧几里得相关系数
def euclidean(p, q):# 如果两数据集数目不同,计算两者之间都对应有的数same = 0for i in p:if i in q:same += 1# 计算欧几里德距离,并将其标准化########## Begin ##########e = sum([(p[i] - q[i]) ** 2 for i in range(same)])########## End ##########    return 1 / (1 + e ** 0.5)print("欧几里得计算出的相似度为",euclidean([1, 2, 3, 4, 5], [2, 4, 6, 8, 10]))# 余弦相似度
def cosine_similarity(x, y):xx = 0.0yy = 0.0xy = 0.0for i in range(len(x)):xx += x[i] * x[i]yy += y[i] * y[i]xy += x[i] * y[i]xx_sqrt = xx ** 0.5
#     print(xx)
#     print(yy)
#     print(xy)yy_sqrt = yy ** 0.5cos = xy/(xx_sqrt*yy_sqrt)return cosprint('余弦相关系数计算出的相似度为',cosine_similarity([5,3],[5,8]))#泊松相关系数
import scipy
import numpy
from scipy.stats import pearsonr########## Begin ##########
x =numpy.array([0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1])
########## End ##########
y =numpy.array([1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,3])r_row, p_value = pearsonr(x, y)
print ("用户(UID)84001033与用户(UID)84001003从2004/1/20到4/20/20这段日期的相似度为",r_row)
# print (p_value)

第2关:基于相似度度量的商品推荐

任务描述

本关任务:通过协同过滤算法完成推荐系统应用实例。

相关知识

为了完成本关任务,你需要掌握:

  1. 了解协同过滤算法原理,
  2. 通过协同过滤算法实现商品推荐。

协同过滤算法基本原理

俗话说“物以类聚、人以群分”,如果你喜欢看《海贼王》、《火影忍者》等动漫,另外有个人也都喜欢这些动漫,而且他还喜欢《死神》,则很有可能你也喜欢《死神》这部动漫。

基本思想:购买了商品A的客户可能也会购买与商品A相似的商品B;与用户A相似的用户B可能也会购买用户A买过的上。

协同过滤算法的实现步骤

(一):找到与目标用户兴趣相似的用户集合

通常用 Jaccard 公式或者余弦相似度计算两个用户之间的相似度。设 N(u) 为用户 u 喜欢的物品集合,N(v)为用户 v 喜欢的物品集合,那么 u 和 v 的相似度是多少呢:

通过第一关的知识,我们了解到Jaccard 公式余弦相似度计算公式为:

Jaccard 公式:

余弦相似度:

假设目前共有4个用户: A、B、C、D;共有5个物品:a、b、c、d、e。用户与物品的关系(用户喜欢物品),如下图所示:

# 目标用户(A用户喜欢a、b、d商品)
target_user = {'A':['a','b','d']}
print(f'目标用户:{target_user}')
# 相似用户用户()
alike_user = {'B': ['a','c'],'C': ['b','e'],'D':['c','d','e']}
print(f'相似用户:{alike_user}')

输出:目标用户:{'A': ['a', 'b', 'd']} 相似用户:{'B': ['a', 'c'], 'C': ['b', 'e'], 'D': ['c', 'd', 'e']}

# 总共商品类型
key_value = []
value1 = target_user.values()
for item in value1:for good in item:# 如果不再就添加到键值(错别字2333)if good not in key_value:key_value.append(good)
value2 = alike_user.values()
for item in value2:for good in item:if good not in key_value:key_value.append(good)
print(f'总共商品类型:{key_value}')

输出:总共商品类型:['a', 'b', 'd', 'c', 'e']

为计算方便,通常首先需要建立“物品—用户”的倒排表,如下图所示:

new_table = []
for good in key_value:new_dict = {}user_list = []# 目标用户key_value_list = target_user.items()# print(key_value_list)for key_value in key_value_list:key = key_value[0]value = key_value[1]if (good in value) & (key not in user_list):user_list.append(key)# new_dict[good] = user_list# new_table.append(new_dict)# 相似用户key_value_list = alike_user.items()# print(key_value_list)for key_value in key_value_list:key = key_value[0]value = key_value[1]if (good in value) & (key not in user_list):user_list.append(key)new_dict[good] = user_listnew_table.append(new_dict)
print(new_table)

输出:[{'a': ['A', 'B']}, {'b': ['A', 'C']}, {'d': ['A', 'D']}, {'c': ['B', 'D']}, {'e': ['C', 'D']}]

如果喜欢物品 a 的用户有 A 和 B,那么在矩阵中他们两两加1,如下图所示:

计算用户两两之间的相似度,以余弦相似度为例,对上图进行进一步计算:

# 计算余弦相似度
import pandas as pd
import numpy as np
df = pd.DataFrame(data=np.zeros((4,4)), columns=['A','B','C','D'],index=['A','B','C','D'])
print(df)
# 统计交集
for item in new_table:print(list(item.values())[0])label = list(item.values())[0]x = label[0]y = label[1]df.loc[x,y] = df.loc[x,y] + 1df.loc[y,x] = df.loc[y,x] + 1
print(df)
# 计算两两之间的相似度
count_list = {}
for i in ['A','B','C','D']:count = df.loc[i,:].sum()count_list[i] = count
print(count_list)

输出:A B C D A 0.0 0.0 0.0 0.0 B 0.0 0.0 0.0 0.0 C 0.0 0.0 0.0 0.0 D 0.0 0.0 0.0 0.0 ['A', 'B'] ['A', 'C'] ['A', 'D'] ['B', 'D'] ['C', 'D'] A B C D A 0.0 1.0 1.0 1.0 B 1.0 0.0 0.0 1.0 C 1.0 0.0 0.0 1.0 D 1.0 1.0 1.0 0.0 {'A': 3.0, 'B': 2.0, 'C': 2.0, 'D': 3.0}

for i in ['A','B','C','D']:for j in ['A', 'B', 'C', 'D']:df.loc[i,j] = df.loc[i,j] / np.sqrt(count_list[i] * count_list[j])
print(df)

(二):根据用户集合给目标用户推荐物品 首先需要从矩阵中找出与目标用户 u 最相似的 K 个用户,用集合 S(u,K) 表示,将 S 中用户喜欢的物品全部提取出来,并去除 u 已经喜欢的物品。对于每个候选物品 i ,用户 u 对它感兴趣的程度用如下公式计算:

其中 rvi​ 表示用户 v 对 i 的喜欢程度,在本例中都是为1,在一些需要用户给予评分的推荐系统中,则要代入用户评分。

举个例子,假设我们要给 A 推荐物品,选取 K = 3 个相似用户,相似用户则是: B、C、D,那么他们喜欢过并且 A 没有喜欢过的物品有:c、e,那么分别计算p(A,c)p(A,e)

看样子用户 A 对 c 和 e 的喜欢程度可能是一样的,在真实的推荐系统中,只要按得分排序,取前几个物品就可以了。

# 计算p(A,c)和p(A,e)
p_Ac = df.loc['A','B'] + df.loc['A','D']
print(f'p(A,c):{p_Ac}')
p_Ae = df.loc['A','C'] + df.loc['A','D']
print(f'p(A,e):{p_Ae}')
if p_Ac > p_Ae:print("用户A对c商品更感兴趣,将e商品推荐给A")
elif p_Ac < p_Ae:print("用户A对e商品更感兴趣,将e商品推荐给A")
else:print("用户A对c商品和e商品同样感兴趣!")

输出: p(A,c):0.7415816237971964 p(A,e):0.7415816237971964 用户A对c商品和e商品同样感兴趣!

编程要求

根据本节关卡知识,完成本关实训。

测试说明

代码:

# (一):找到与目标用户兴趣相似的用户集合
# ########## Begin ##########
# 目标用户(A用户喜欢a、b、d商品)
target_user = {'A':['a','b','d']}
print(f'目标用户:{target_user}')
# 相似用户用户()
alike_user = {'B':['a','c'],'C':['b','e'],'D':['c','d','e']}
print(f'相似用户:{alike_user}')
# ########## End ##########
# 倒排表"""
a A B C
"""
# 总共商品类型
key_value = []
value1 = target_user.values()
for item in value1:for good in item:# 如果不在就添加到键值if good not in key_value:key_value.append(good)
value2 = alike_user.values()
########## Begin ##########
for item in value2:for good in item:if good not in key_value:key_value.append(good)
print(f'总共商品类型:{key_value}')
########## End ##########
new_table = []
for good in key_value:new_dict = {}user_list = []# 目标用户key_value_list = target_user.items()# print(key_value_list)for key_value in key_value_list:key = key_value[0]value = key_value[1]if (good in value) & (key not in user_list):user_list.append(key)# new_dict[good] = user_list# new_table.append(new_dict)# 相似用户key_value_list = alike_user.items()# print(key_value_list)for key_value in key_value_list:key = key_value[0]value = key_value[1]if (good in value) & (key not in user_list):user_list.append(key)new_dict[good] = user_listnew_table.append(new_dict)
print(new_table)
########## Begin ##########
# 计算余弦相似度
import pandas as pd
import numpy as np
df = pd.DataFrame(data=np.zeros((4,4)), columns=['A','B','C','D'],index=['A','B','C','D'])
print(df)
# 统计交集
for item in new_table:print(list(item.values())[0])label = list(item.values())[0]x = label[0]y = label[1]df.loc[x,y] = df.loc[x,y] + 1df.loc[y,x] = df.loc[y,x] + 1
print(df)
########## End ########### 计算两两之间的相似度
count_list = {}
for i in ['A','B','C','D']:count = df.loc[i,:].sum()count_list[i] = count
print(count_list)
# 计算余弦相似度
########## Begin ##########
for i in ['A','B','C','D']:for j in ['A', 'B', 'C', 'D']:df.loc[i,j] = df.loc[i,j] / np.sqrt(count_list[i] * count_list[j])
########## End ##########
print(df)
########## Begin ##########
# 计算p(A,c)和p(A,e)
p_Ac = df.loc['A','B'] + df.loc['A','D']
print(f'p(A,c):{p_Ac}')
p_Ae = df.loc['A','C'] + df.loc['A','D']
print(f'p(A,e):{p_Ae}')
########## End ##########
if p_Ac > p_Ae:print("用户A对c商品更感兴趣,将e商品推荐给A")
elif p_Ac < p_Ae:print("用户A对e商品更感兴趣,将e商品推荐给A")
else:print("用户A对c商品和e商品同样感兴趣!")

开始你的任务吧,祝你成功!

这篇关于相似度与相异度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/677174

相关文章

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

线性代数 第六讲 特征值和特征向量_相似对角化_实对称矩阵_重点题型总结详细解析

文章目录 1.特征值和特征向量1.1 特征值和特征向量的定义1.2 特征值和特征向量的求法1.3 特征值特征向量的主要结论 2.相似2.1 相似的定义2.2 相似的性质2.3 相似的结论 3.相似对角化4.实对称矩阵4.1 实对称矩阵的基本性质4.2 施密特正交化 5.重难点题型总结5.1 判断矩阵能否相似对角化5.2 已知两个矩阵相似,求某个矩阵中的未知参数5.3 相似时,求可逆矩阵P,使

SimD:基于相似度距离的小目标检测标签分配

摘要 https://arxiv.org/pdf/2407.02394 由于物体尺寸有限且信息不足,小物体检测正成为计算机视觉领域最具挑战性的任务之一。标签分配策略是影响物体检测精度的关键因素。尽管已经存在一些针对小物体的有效标签分配策略,但大多数策略都集中在降低对边界框的敏感性以增加正样本数量上,并且需要设置一些固定的超参数。然而,更多的正样本并不一定会带来更好的检测结果,事实上,过多的正样本

Matlab)实现HSV非等间隔量化--相似判断:欧式距离--输出图片-

%************************************************************************** %                                 图像检索——提取颜色特征 %HSV空间颜色直方图(将RGB空间转化为HS

【python 走进NLP】两两求相似度,得到一条文本和其他文本最大的相似度

应用场景: 一个数据框里面文本,两两求相似度,得到一条文本和其他文本最大的相似度。 content source_id0 丰华股份军阀割据发生的故事大概多少w 11 丰华股份军阀割据发生的故事大概多少 22 丰华股份军阀割据发生的故事大概多少 33 丰华股份军阀割据发生的故事大概多少

【java 走进NLP】simhash 算法计算两篇文章相似度

python 计算两篇文章的相似度算法simhash见: https://blog.csdn.net/u013421629/article/details/85052915 对长文本 是比较合适的(超过500字以上) 下面贴上java 版本实现: pom.xml 加入依赖 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</a

【python 走进NLP】simhash 算法计算两篇文章相似度

互联网网页存在大量的重复内容网页,无论对于搜索引擎的网页去重和过滤、新闻小说等内容网站的内容反盗版和追踪,还是社交媒体等文本去重和聚类,都需要对网页或者文本进行去重和过滤。最简单的文本相似性计算方法可以利用空间向量模型,计算分词后的文本的特征向量的相似性,这种方法存在效率的严重弊端,无法针对海量的文本进行两两的相似性判断。模仿生物学指纹的特点,对每个文本构造一个指纹,来作为该文本的标识,从形式上来

【python 走进NLP】文本相似度各种距离计算

计算文本相似度有什么用? 1、反垃圾文本的捞取 “诚聘淘宝兼职”、“诚聘打字员”…这样的小广告满天飞,作为网站或者APP的运营者,不可能手动将所有的广告文本放入屏蔽名单里,挑几个典型广告文本,与它满足一定相似度就进行屏蔽。 2、推荐系统 在微博和各大BBS上,每一篇文章/帖子的下面都有一个推荐阅读,那就是根据一定算法计算出来的相似文章。 3、冗余过滤 我们每天接触过量的信息,信息之间存在大量

【python 走进NLP】句子相似度计算--余弦相似度

余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中,如最常见的二维空间。 github 参考链接:https://github.com/ZhanPwBibiBibi/CHlikelihood # -*- coding: utf-8 -*-import jiebaimport numpy as npimpor

【python 图片搜索】python 快速计算两个图片的相似度

一、图片相似度检测算法原理 我们日常中处理的数据大多数是文本和图片,既然文本有文本相似度,图片肯定也有图片相似度呀,是不是。下面介绍图片相似度检测的算法:检查两个图片的相似度,一个简单而快速的算法:感知哈希算法(Perceptual Hash),通过某种提取特征的方式为每个图片计算一个指纹(哈希),这样对比两个图片相似与否就变成了对比两个指纹异同的问题。 二、应用 相似图片搜索图片相似度比较百度