PySpark - 从共现矩阵获取杰卡德相似度

Ank*_*pta 2 python pyspark

我在 pyspark 中有一个共现矩阵,用于某些关键字 A、B、C 的共现

    A   B   C
A   5   1   0
B   1   3   2
C   0   2   3
Run Code Online (Sandbox Code Playgroud)

如何在 Python 中计算所有关键字的该矩阵的 jaccard 相似度。是否有任何库可以做到这一点,或者我应该简单地使用 Jaccard 相似度公式来计算相似度?

Pra*_*adi 5

假设共现矩阵以列表的形式给出:

\n
com = [[5, 1, 0], \n       [1, 3, 2],\n       [0, 2, 3]]\nn_elem = len(com)\n
Run Code Online (Sandbox Code Playgroud)\n

两个集合的Jaccard相似度AB由 给出|A \xe2\x88\xa9 B| / |A \xe2\x88\xaa B||A|共现矩阵给出、|B|和的值|A \xe2\x88\xa9 B|。的值|A \xe2\x88\xaa B|很简单|A| + |B| - |A \xe2\x88\xa9 B|,我们可以找到 Jaccard 索引。

\n

首先,让我们创建一个列表列表,其中包含与 大小相同的列表com。默认值是1因为集合与其自身的相似度指数为1,我们不会计算这些元素:

\n
similarity = [[1 for _ in row] for row in com]\n
Run Code Online (Sandbox Code Playgroud)\n

现在,我们可以循环遍历每对值com并计算相似度。内循环从 开始,i+1因为similarity[i][j]与 相同similarity[j][i],所以我们只需要计算矩阵的上三角形:

\n
for i in range(n_elem):\n    a = com[i][i]               # |A|\n    for j in range(i+1, n_elem):\n        b = com[j][j]           # |B|\n        aib = com[i][j]         # |A \xe2\x88\xa9 B|\n        aub = a + b - aib       # |A \xe2\x88\xaa B|\n        # Set both off-diagonal elements simultaneously\n        similarity[i][j] = similarity[j][i] = aib / aub\n
Run Code Online (Sandbox Code Playgroud)\n

这给我们留下了以下similarity矩阵:

\n
[[1                  , 0.14285714285714285, 0.0], \n [0.14285714285714285, 1                  , 0.5], \n [0.0                , 0.5                , 1]]\n
Run Code Online (Sandbox Code Playgroud)\n
\n

现在,如果您的共现矩阵是 numpy 数组(或者您愿意使用 numpy),您可以通过将循环外包给 numpy 的 C 后端来加速计算。

\n
import numpy as np\ncom_arr = np.array([[5, 1, 0], \n       [1, 3, 2],\n       [0, 2, 3]])\nn_elem = com_arr.size\n
Run Code Online (Sandbox Code Playgroud)\n

首先,我们可以使用矩阵的对角线得到每个元素的出现次数:

\n
occ = np.diag(com_arr) # array([5, 3, 3])\n
Run Code Online (Sandbox Code Playgroud)\n

接下来,创建 的矩阵|A \xe2\x88\xaa B|。请记住,|A \xe2\x88\xa9 B|已经由 指定com_arr

\n
aub = occ[:, None] + occ[None, :] - com_arr\n
Run Code Online (Sandbox Code Playgroud)\n

由于occ是一维数组,因此添加索引将分别创建一列(形状为 的列向量)和一行(形状为 的行向量)None的二维数组。将行向量添加到列向量时,numpy 会自动广播维度,以便最终得到形状为 的(在本例中)方阵。现在,看起来像这样:(3, 1)(1, 3)(3, 3)aub

\n
array([[5, 7, 8],\n       [7, 3, 4],\n       [8, 4, 3]])\n
Run Code Online (Sandbox Code Playgroud)\n

最后,将交集除以并集:

\n
similarity = com_arr / aub\n
Run Code Online (Sandbox Code Playgroud)\n

瞧,我们的值与以前相同:

\n
array([[1.        , 0.14285714, 0.        ],\n       [0.14285714, 1.        , 0.5       ],\n       [0.        , 0.5       , 1.        ]])\n
Run Code Online (Sandbox Code Playgroud)\n