【Educoder数据挖掘实训】相似度与相异度

【Educoder数据挖掘实训】相似度与相异度

开挖!!!!!!

T1 用相关系数计算直线之间的相似度

这关分为没啥关系的三部分,分别是欧几里得相关系数、余弦相关系数和泊松相关系数。

他们的公式都比较直观:

欧几里得相关系数的计算方式是按照对应点的相对距离来算的,也就是 d ( x , y ) = ∑ i = 1 n ( x i − y i ) 2 d(x,y) = \sqrt{\sum\limits_{i = 1}^{n}(x_i - y_i)^2} d(x,y)=i=1∑n(xi−yi)2 .

余弦相关系数则将两个数据看做两个 n n n维向量,计算方式为: c o s ( θ ) = ∑ i = 1 n ( x i × y i ) ∑ i = 1 n x i 2 ∑ i = 1 n y i 2 cos(\theta) = \frac{\sum\limits_{i = 1}^n (x_i\times y_i)}{\sum\limits_{i = 1}^{n}x_i^2\sum\limits_{i = 1}^{n}y_i^2} cos(θ)=i=1∑nxi2i=1∑nyi2i=1∑n(xi×yi)。

泊松相关系数将两个数据看成是数据集,计算方式为: ρ X Y = E ( ( X − E X ) ( Y − E Y ) ) D X D Y \rho_{XY} = \frac{E((X - EX)(Y - EY))}{\sqrt{DX}\sqrt{DY}} ρXY=DX DY E((X−EX)(Y−EY))。

其中第一部分代码只需要按照公式复刻一遍即可。

泊松部分的代码需要认真看一眼实训,实训给出的样例中提及了日期,只需要复制另一个人的日期即可。

代码如下:

python 复制代码
# 欧几里得相关系数
def euclidean(p, q):
    # 如果两数据集数目不同,计算两者之间都对应有的数
    same = 0
    for 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.0
    yy = 0.0
    xy = 0.0
    for 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
    yy_sqrt = yy ** 0.5
    cos = xy/(xx_sqrt*yy_sqrt)
    return cos
print('余弦相关系数计算出的相似度为',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)

T2 基于相似度度量的商品推荐

这一关主要提及了 J a c c a r d Jaccard Jaccard 公式和余弦相似度,并在代码里要求复现余弦相似度的过程。

这个过程的核心思想是,将用户的喜欢商品列表转换成:每个商品被哪些用户喜欢。

我们将喜欢列表成为表 1 1 1,被喜欢列表成为表 2 2 2。

在构造系数的时候,对于两个不同的用户取二者表 1 1 1的交集计算数量加到一个横纵元素都为全体用户的表中,例如用户 A A A和用户 B B B共同喜欢三个商品 a , b , c a,b,c a,b,c,那么空表中 ( A , B ) , ( B , A ) (A,B),(B,A) (A,B),(B,A)都为 3 3 3。

然后我们用余弦计算公式把该表中所有整数都计算为余弦相似度。

对于每个用户 P P P在推荐商品的时候,对于一个商品 x x x, x x x的表 2 2 2中每一个用户除去 P P P的余弦值加在一起,成为 x x x的推荐度。取所有 P P P的表 1 1 1里没有的商品中推荐值最大的商品推荐给 P P P即可。

python 复制代码
# (一):找到与目标用户兴趣相似的用户集合
########## 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_list
    new_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] + 1
    df.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商品同样感兴趣!")

补充:

  1. 代码里有个明显笔误,无论如何都推荐商品 e e e。
  2. 这种推荐方法其实很容易有两个商品的值都一样的情况,当然在本题本题中不会出现。一般我们应对这种问题的处理方法就是将两个商品打包或者继续继续观察这两个商品的受众。
相关推荐
lzqrzpt11 分钟前
临沂LED驱动电源工程选型标准与工艺对比解析
python·单片机·嵌入式硬件·物联网
专业程序开发源12 分钟前
django新闻推荐系统70655-计算机课程设计、毕业设计
java·javascript·spring boot·后端·python·django·课程设计
成为深度学习高手17 分钟前
TimeBridge:用Integrated Attention与Cointegrated Attention分别桥接短期平稳与长期协整的时序预测模型
人工智能·机器学习·数据挖掘
知几蜗牛18 分钟前
Java 17调用Embeddings API:余弦相似度与FAQ拒答阈值
人工智能
知几蜗牛21 分钟前
Python消费Responses SSE事件:增量文本、超时与取消
人工智能
AI日报派送佬22 分钟前
2026年10月4日AI行业日报|AI智能体自主能力升级,模型落地与安全规范双向迭代
人工智能·智能体·ai安全·开源ai·ai日报·人工智能前沿·ai科研
蒲公英eric22 分钟前
人口增长问题:从 Malthus 到 Logistic 的建模之旅
人工智能·python·数学建模·人口增长问题
知几蜗牛23 分钟前
Python调用Audio Speech REST API:文本分段、超时与原子落盘
人工智能
全栈练习生23 分钟前
大模型原理之 Softmax
python·ai
迅猛龙办公室23 分钟前
python获取星期字符串
开发语言·python