如何从pandas数据框计算Jaccard相似度

我有一个如下所示的数据框:数据框的形状为(1510, 1399)。列代表产品,行为用户为给定产品分配的值(0或1)。我如何计算jaccard_similarity_score

enter image description here

我创建了一个产品对产品的占位符数据框

data_ibs = pd.DataFrame(index=data_g.columns,columns=data_g.columns)

我不确定如何遍历data_ibs来计算相似度。

for i in range(0,len(data_ibs.columns)) :    # 遍历每一列    for j in range(0,len(data_ibs.columns)) :        .........

回答:

使用pairwise_distances计算距离,然后从1中减去该距离以找到相似度分数:

from sklearn.metrics.pairwise import pairwise_distances1 - pairwise_distances(df.T.to_numpy(), metric='jaccard')

解释:

在scikit-learn的新版本中,jaccard_score的定义类似于维基百科中Jaccard相似系数的定义:

其中

  • M11表示A和B都为1的属性总数。
  • M01表示A为0且B为1的属性总数。
  • M10表示A为1且B为0的属性总数。
  • M00表示A和B都为0的属性总数。

让我们创建一个示例数据集来查看结果是否匹配:

from pandas import DataFrame, crosstabfrom numpy.random import default_rngrng = default_rng(0)# 创建一个40行5列(命名为A, B, C, D, E)的数据框# DataFrame中的每个单元格以50%的概率为0或1df = DataFrame(rng.binomial(1, 0.5, size=(40, 5)), columns=list('ABCDE'))

这将产生以下A和B列的交叉表:

A/B 0 1
0 10 7
1 14 9

根据定义,Jaccard相似度分数为:

M00 = (df['A'].eq(0) & df['B'].eq(0)).sum()  # 10M01 = (df['A'].eq(0) & df['B'].eq(1)).sum()  # 7M10 = (df['A'].eq(1) & df['B'].eq(0)).sum()  # 14M11 = (df['A'].eq(1) & df['B'].eq(1)).sum()  # 9print(M11 / (M01 + M10 + M11))  # 0.3

这正是你使用jaccard_score得到的结果:

from sklearn.metrics import jaccard_scoreprint(jaccard_score(df['A'], df['B']))  # 0.3

jaccard_score函数的问题在于它不是向量化的。你需要遍历所有列来计算每个对应列的相似度分数。为了避免这种情况,你可以使用向量化的距离版本。然而,由于它是“距离”而不是“相似度”,你需要从1中减去该值:

from sklearn.metrics.pairwise import pairwise_distancesprint(1 - pairwise_distances(df.T.to_numpy(), metric='jaccard'))# [[1.         0.3        0.45714286 0.34285714 0.46666667]#  [0.3        1.         0.29411765 0.33333333 0.23333333]#  [0.45714286 0.29411765 1.         0.40540541 0.44117647]#  [0.34285714 0.33333333 0.40540541 1.         0.36363636]#  [0.46666667 0.23333333 0.44117647 0.36363636 1.        ]]

可选地,你可以将其转换回DataFrame:

jac_sim = 1 - pairwise_distances(df.T.to_numpy(), metric='jaccard')jac_sim_df = DataFrame(    1 - pairwise_distances(df.T.to_numpy(), metric='jaccard'),     index=df.columns, columns=df.columns,)#           A         B         C         D         E#  A  1.000000  0.300000  0.457143  0.342857  0.466667#  B  0.300000  1.000000  0.294118  0.333333  0.233333#  C  0.457143  0.294118  1.000000  0.405405  0.441176#  D  0.342857  0.333333  0.405405  1.000000  0.363636#  E  0.466667  0.233333  0.441176  0.363636  1.000000

注意:在之前的答案版本中,计算使用了pairwise_distances的hamming度量,因为在早期的scikit-learn版本中,jaccard_score的计算类似于准确度分数(即(M00 + M11)/(M00 + M01 + M10 + M11))。现在情况不再如此,因此答案已更新为使用jaccard度量而不是hamming度量。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注