离散数据、Jaccard系数和并行处理

2021-04-21 11:11:12 浏览数 (1)

磐创AI分享

作者 | Casey Whorton 编译 | VK 来源 | Towards Data Science

佛罗里达的机场比海德拉巴的机场更接近底特律机场,我们知道这一点,因为我们用经纬度来测量距离(海德拉巴是印度的一个大城市)。

但是,我们怎么说一个购物篮的内容更接近另一个呢?或者一片森林和另一片森林在动物方面更相似?我们可以将这些作为集合之间的比较,并使用Jaccard的系数来度量它们之间的相似性(或不相似性)(我们可以互换地使用Jaccard系数和相似性得分)。

对于大型数据集,这可能是一项艰巨的任务,因此我们可以使用并行处理来缩短时间。查看kaggle上的完整笔记本:https://www.kaggle.com/caseyw/jaccard-s-metric-introduction

例子

因此,当比较两个集合(可以是数组、序列,甚至是二元值的向量)时,分子是集合之间共享的元素的个数,分母是两个集合中元素的个数。

在我们的例子中,分母是任意一个集合的大小,所以我们也可以说这个相似度分数是共享元素的数量除以可以共享的元素的数量。

我们来看一个简单的例子:

代码语言:javascript复制
from sklearn.metrics import jaccard_score
from scipy.spatial.distance import jaccard

x = [[1,1,1],[1,0,1],[0,0,0]]

print(x)
[[1, 1, 1], [1, 0, 1], [0, 0, 0]]

jaccard(x[0],x[1])
0.33

jaccard_score(x[0],x[1])
0.66

数组x有三行。

第一行将是我们希望比较的观察结果。注意,Jaccard函数返回前两行之间没有共享的元素数量的。jaccard_score函数返回相反的结果:它是前两行之间共享的元素数量。一个表示不同,另一个表示相似。我个人更喜欢scikit-learn中提供的相似度评分,但重要的是你要意识到其中的差异。

(进一步注意,有些人认为计算中根本不应该包含元素0。在某些情况下,这是有道理的。)

现在我们已经在一个简单的例子中看到了这个度量,让我们将它应用到一个更大的数据集。

基于Jaccard的距离测量及并行处理

代码语言:javascript复制
import numpy as np
import pandas as pd

x0 = np.random.choice([0, 1], size=(100000,100), p=[4./5, 1./5])
x1 = np.random.choice([0, 1], size=(100000,100), p=[1./3, 2./3])
x2 = np.random.choice([0, 1], size=(100000,100), p=[1./2, 1./2])

colnames = ['x_' str(i) for i in range(0,100)]

X = pd.DataFrame(data = np.stack([x0,x1,x2]).reshape(300000,100))
X.columns = colnames

target = np.ones(100).astype(int)

我们的目标是一个所有特征都设置为1的观测值。想象一下,一个篮子已经购买了web商店中所有可用的商品,你想看看哪些观察结果最接近它。这主要是为了示例的目的,但是你可以看到如何将其扩展到其他用例。

用二值数据(1和0)创建了一个巨大的300k观测值数组,以代替指示器特征或虚拟变量。

前三分之一的为1概率是(1/5),后三分之一的概率是(2/3),最后三分之一的概率是(1/2)。让我们看看有多少观测结果与我们的目标重叠,重叠多少!但首先,让我们利用multiprocessing包并创建一个部分函数来并行地将几个观察结果与目标进行比较(这将节省大量时间和内存)。

代码语言:javascript复制
from functools import partial
import multiprocessing as mp

partial_jaccard = partial(jaccard_score, target)

with mp.Pool() as pool:
    results = pool.map(partial_jaccard, [row for row in X.values])

上面的代码几乎需要1分钟(~50秒)。这是经过并行处理30万个100个特征的样本的结果。你可能会遇到具有更多特征和更多观察的数据集。尝试在循环中完成上述任务会导致我的电脑完全崩溃(蓝屏/皱眉脸),但如果你有勇气,那么你应该尝试一个子集的数据,看看它需要多长时间。

下面是结果。你会看到,对于前三分之一的数据(1/5概率为1的数据),你会看到有一个峰值,Jaccard的相似性得分为0.2(20%)。其他山峰也一样。这证实了我们的multiprocessing和partial函数的比较是有效的。

结论

当你有二值数据(如指标特征或虚拟变量),并希望在观察数据之间创建某种距离度量时,请考虑这个Jaccard系数/相似性得分。这是相当直观的,但是需要一些额外的工作来在大量的数据上进行测量。

参考引用

https://en.wikipedia.org/wiki/Jaccard_index

https://scikit-learn.org/stable/modules/generated/sklearn.metrics.jaccard_score.html

https://docs.python.org/3/library/multiprocessing.html

0 人点赞