我有一个字典,如下所示:
dic = {a1: [a,b,c], b1:[b,k,l]}.
我想为每个键的值列表创建一个相似度矩阵。例如,对于键a1
,我想使用假设方法(a,b), (a,c) and (b,c)
计算f
之间的相似度。 f((a,a)) = 1
。我们可以通过创建向量并通过(a,b), (a,c) and (b,c)
之间的相似度值为其元素建立索引,并对b重复相同的过程(即(b,a), (b,b), and (b,c)
等)来实现。但由于(b,a) =(a,b)
的相似性,因此没有必要。那么如何解决呢?如何创建这样的矩阵呢?
然后将相同的方法应用于dic的每个键(例如b1等)
答案 0 :(得分:1)
如果f
价格昂贵且无法矢量化,则可以按照以下方式使用np.tri
和朋友
>>> import numpy as np
>>> from operator import itemgetter as iget
>>>
# set up an example
>>> a1, b1 = 'a1', 'b1'
>>> a, b, c, k, l = np.random.randint(0, 10, (5, 3))
>>> dic = {a1: [a,b,c], b1: [b,k,l]}
>>> f = np.dot
>>>
# do the computation
>>> RES = {}
>>> for k, v in dic.items():
... N = len(v)
... res = np.ones((N, N))
... I, J = np.triu_indices_from(res, 1)
... res[I, J] = np.fromiter(map(f, iget(*I.tolist())(v), iget(*J.tolist())(v)), float, N*(N-1)//2)
... np.copyto(res, res.T, where=np.tri(*res.shape, -1, bool))
... RES[k] = res
...
# check
>>> RES
{'a1': array([[ 1., 108., 122.],
[108., 1., 120.],
[122., 120., 1.]]), 'b1': array([[ 1., 42., 66.],
[42., 1., 20.],
[66., 20., 1.]])}
您也可以使用map(f, iget(...
代替itertools.starmap(f, itertools.combinations(v, 2))
。