基本上是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
和{{ 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
列表的函数f
。 M
测量两个列表f(a,b)
和a
之间的相似度。在上面的示例中,b
和t_0
之间的相似度应该很高,而t_1
和t_0
的相似度应该很小。
我的问题:
t_n
的最佳选择是什么? f
之类的矩阵作为输入并产生M
之类的矩阵?最好是一个python包?谢谢,r0f1
答案 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的最佳选择是什么?
鉴于顺序在您的特定情况下确实很重要,我建议您查看排名相关系数,例如:Kendall或Spearman,它们都在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.distance
和scipy.stats
都提供了许多距离和系数函数供您试用。
进一步
答案 2 :(得分:1)
我建议余弦相似度,因为每个列表都是一个向量。
from sklearn.metrics.pairwise import cosine_similarity
cosine_similarity(list0,list1)