基本上,I want to reimplement this video .
给定一个文档语料库,我想找到彼此最相似的术语。
我能够使用 this SO thread 生成共现矩阵并使用视频生成关联矩阵。接下来,我想生成一个二阶共现矩阵。
问题陈述:考虑一个矩阵,其中矩阵的行对应于一个术语,行中的条目对应于与该术语相似的前 k 个术语。比如说,k = 4,我们的字典中有 n 个术语,那么矩阵 M 有 n 行和 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 和 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,它的元素是一个应用于 M 列表的函数 f。 f(a,b) 衡量两个列表a 和b 之间的相似程度。继续上面的例子,t_0和t_1的相似度应该很高,而t_0和的相似度>t_n 应该很低。
我的问题:
- 比较两个列表的顺序的最佳选择是什么?也就是说,函数
f的最佳选择是什么? - 是否已经有一种转换可以将像
M这样的矩阵作为输入并生成像C这样的矩阵?最好是 python 包?
谢谢你,r0f1
请您参考如下方法:
事实上,在这种情况下,余弦相似度可能还不算太差。问题是,您不想使用索引向量(即 [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 存储为列表的一维数组(基本上是您在第二个代码 list 中声明的内容)。这有点棘手,因为 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 基本上包含您在第二个代码 list 中描述的内容。然后,您可以使用新的 ufunc 的 outer 方法来获取相似度矩阵。以下是示例中的 M 所有这些如何协同工作(假设 n=3):
M = [[18, 34, 54, 65],
[18, 12, 54, 65],
[21, 43, 55, 78]]
n = len(M) # i.e. 3
uf = np.frompyfunc(f, 2, 1)
Marray = np.empty(n, dtype='O')
for i in range(n):
Marray[i] = M[i]
similarities = uf.outer(Marray, Marray).astype('d') # convert to float instead object type
print(similarities)
# array([[4., 3., 0.],
# [3., 4., 0.],
# [0., 0., 4.]])
我希望这能回答您的问题。
