【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. 这种推荐方法其实很容易有两个商品的值都一样的情况,当然在本题本题中不会出现。一般我们应对这种问题的处理方法就是将两个商品打包或者继续继续观察这两个商品的受众。
相关推荐
奔跑中的小象1 小时前
统信UOS + 天数AI卡部署SGLang服务手册
人工智能·uos·sglang·天数智芯
DevSecOps选型指南1 小时前
中国版Mythos,为何是悬镜安全灵脉CodeAI?
人工智能·安全
Shockang1 小时前
LangGraph 状态机实战
人工智能
DLYSB_1 小时前
存储运维实战:基于 Ceph Event 监听与 Python 适配器的分布式存储健康度物理声光响应架构
运维·ceph·python·报警灯
刹那芳华19921 小时前
循环神经网络的从零开始实现(RNN)
人工智能·rnn·深度学习
阿童木写作2 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
科技之门2 小时前
AI3D从建模到贴图、绑骨和动画的完整流程怎么做?V2Fun完整工作流指南
人工智能·3d·贴图
宇宙第一小趴菜2 小时前
二、机器学习的应用领域和发展史
人工智能·机器学习
前端开发江鸟2 小时前
我写过 MCP Server,却一直以为 MCP 只有 Tool
人工智能
天国梦2 小时前
自习室智能化升级避坑指南:天学网AI智习室方案实测与选型建议
大数据·人工智能