文本中词语的二阶同时出现

时间:2018-12-18 12:49:31

标签: python matrix nlp

基本上是I want to reimplement this video

给出大量的文档,我想找到最相似的术语。

我能够使用this SO thread生成同现矩阵,并使用视频生成关联矩阵。接下来,我想生成一个二阶共生矩阵。

问题陈述:考虑一个矩阵,其中矩阵的行对应于一个术语,而行中的条目对应于与该术语相似的前k个术语。假设k = 4,并且字典中有n个词,则矩阵Mn行和4列。

有:

M = [[18,34,54,65],   # Term IDs similar to Term t_0
     [18,12,54,65],   # Term IDs similar to Term t_1
     ...
     [21,43,55,78]]   # Term IDs similar to Term t_n.

因此,对于每个术语ID,M包含最相似的术语ID。现在,我想检查一下有多少个相似的术语匹配。在上述M的示例中,术语t_0和术语t_1似乎非常相似,因为四个术语中有三个匹配,而t_0和{{ 1}}不相似,因为没有任何术语匹配。让我们将t_n写成一系列列表。

M

想要:

M = [list_0,   # Term IDs similar to Term t_0
     list_1,   # Term IDs similar to Term t_1
     ...
     list_n]   # Term IDs similar to Term t_n.

我想找到矩阵C = [[f(list_0, list_0), f(list_0, list_1), ..., f(list_0, list_n)], [f(list_1, list_0), f(list_1, list_1), ..., f(list_1, list_n)], ... [f(list_n, list_0), f(list_n, list_1), ..., f(list_n, list_n)]] ,该矩阵具有一个应用于C列表的函数fM测量两个列表f(a,b)a之间的相似度。在上面的示例中,bt_0之间的相似度应该很高,而t_1t_0的相似度应该很小。

我的问题:

  1. 比较两个列表的顺序的最佳选择是什么?也就是说,函数t_n的最佳选择是什么?
  2. 是否已有可用的转换将f之类的矩阵作为输入并产生M之类的矩阵?最好是一个python包?

谢谢,r0f1

3 个答案:

答案 0 :(得分:3)

实际上,在这种情况下,余弦相似度可能还不错。问题是,您不想使用索引向量(例如[18,34,54,65],依此类推),但是您希望长度为n的向量在所有地方都为零,除了中的值您的索引向量。幸运的是,您不必显式创建这些向量,而只需计算两个索引向量共有多少个索引:

def f(u, v):
    return len(set(u).intersection(set(v)))

在这里,我省略了常数归一化因子k。还可以做一些更复杂的事情(例如TF-IDF内核),但是我一开始会坚持做下去。

为了使用numpy有效地运行此程序,您需要做两件事:

f转换为ufunc,即numpy向量化函数。您可以通过uf = np.frompyfunc(f, 2, 1)来做到这一点(假设您在某个时候做过import numpy as np)。

M存储为一维列表数组(基本上是您在第二个代码列表中声明的内容)。这有点棘手,因为numpy试图在这里变得聪明,但您还需要其他东西。因此,这是操作方法:

n = len(M)
Marray = np.empty(n, dtype='O')  # dtype='O' allows you to have elements of type list
for i in range(n):
    Marray[i] = M[i]

现在,Marray基本上包含您在第二个代码清单中描述的内容。然后,您可以使用新的ufunc的{​​{1}}方法来获取相似度矩阵。在示例中(假设outer),这一切将与您的M一起工作:

n=3

我希望能回答您的问题。

答案 1 :(得分:2)

您问了两个问题,一个问题是开放式的(第一个),另一个问题有明确的答案,所以我将从第二个问题开始:

  

是否已有可用的转换作为输入   像M的矩阵并产生像C的矩阵?最好是一条蟒蛇   包装?

答案是肯定的,有一个名为scipy.spatial.distance的软件包,其中包含一个函数,该函数采用M之类的矩阵,并产生C之类的矩阵。以下示例显示了该功能:

import numpy as np
from scipy.spatial.distance import pdist, squareform

# initial data
M = [[18, 34, 54, 65],
     [18, 12, 54, 65],
     [21, 43, 55, 78]]

# convert to numpy array
arr = np.array(M)

result = squareform(pdist(M, metric='euclidean'))
print(result)

输出

[[ 0.         22.         16.1245155 ]
 [22.          0.         33.76388603]
 [16.1245155  33.76388603  0.        ]]

从上面的示例中可以看出,pdist采用M矩阵并生成C矩阵。请注意,pdist的输出是凝聚距离矩阵,因此您需要使用squareform将其转换为正方形。现在进入第二个问题:

  

比较两个列表的顺序的最佳选择是什么?那   是,函数f的最佳选择是什么?

鉴于顺序在您的特定情况下确实很重要,我建议您查看排名相关系数,例如:KendallSpearman,它们都在scipy.stats包中提供,整堆其他系数。用法示例:

import numpy as np
from scipy.spatial.distance import pdist, squareform
from scipy.stats import kendalltau, spearmanr

# distance function
kendall = lambda x, y : kendalltau(x, y)[0]
spearman = lambda x, y : spearmanr(x, y)[0]


# initial data
M = [[18, 34, 54, 65],
     [18, 12, 54, 65],
     [21, 43, 55, 78]]

# convert to numpy array
arr = np.array(M)

# compute kendall C and convert to square form
kendall_result = 1 - squareform(pdist(arr, kendall))  # subtract 1 because you want a similarity
print(kendall_result)
print()

# compute spearman C and convert to square form
spearman_result = 1 - squareform(pdist(arr, spearman))  # subtract 1 because you want a similarity
print(spearman_result)
print()

输出

[[1.         0.33333333 0.        ]
 [0.33333333 1.         0.33333333]
 [0.         0.33333333 1.        ]]

[[1.  0.2 0. ]
 [0.2 1.  0.2]
 [0.  0.2 1. ]]

如果这些都不满足您的需求,您可以查看Hamming distance,例如:

import numpy as np
from scipy.spatial.distance import pdist, squareform

# initial data
M = [[18, 34, 54, 65],
     [18, 12, 54, 65],
     [21, 43, 55, 78]]

# convert to numpy array
arr = np.array(M)

# compute match_rank C and convert to square form
result = 1 - squareform(pdist(arr, 'hamming'))
print(result)

输出

[[1.   0.75 0.  ]
 [0.75 1.   0.  ]
 [0.   0.   1.  ]]

最后,相似性功能的选择将取决于最终应用程序,因此您将需要尝试不同的功能并查看适合您需求的功能。 scipy.spatial.distancescipy.stats都提供了许多距离和系数函数供您试用。

进一步

  1. 以下paper包含有关列表相似性的部分

答案 2 :(得分:1)

我建议余弦相似度,因为每个列表都是一个向量。

     from sklearn.metrics.pairwise import cosine_similarity

     cosine_similarity(list0,list1)