3

我有一个对称相似度矩阵,我只想保留每行中的 k 个最大值。

这是一些完全符合我要求的代码,但我想知道是否有更好的方法。特别是展平/重塑有点笨拙。提前致谢。

请注意,nrows(如下)必须扩展到数万。

from scipy.spatial.distance import pdist, squareform
random.seed(1)
nrows = 4
a = (random.rand(nrows,nrows))

# Generate a symmetric similarity matrix
s = 1-squareform( pdist( a, 'cosine' ) )
print "Start with:\n", s

# Generate the sorted indices
ss = argsort(s.view(np.ndarray), axis=1)[:,::-1]
s2 = ss + (arange(ss.shape[0])*ss.shape[1])[:,None]

# Zero-out after k-largest-value entries in each row
k = 3 # Number of top-values to keep, per row
s = s.flatten()
s[s2[:,k:].flatten()] = 0
print "Desired output:\n", s.reshape(nrows,nrows)

给出:

Start with:
[[ 1.          0.61103296  0.82177072  0.92487807]
 [ 0.61103296  1.          0.94246304  0.7212526 ]
 [ 0.82177072  0.94246304  1.          0.87247418]
 [ 0.92487807  0.7212526   0.87247418  1.        ]]
Desired output:
[[ 1.          0.          0.82177072  0.92487807]
 [ 0.          1.          0.94246304  0.7212526 ]
 [ 0.          0.94246304  1.          0.87247418]
 [ 0.92487807  0.          0.87247418  1.        ]]
4

2 回答 2

1

不是一个可观的改进,但为了避免扁平化和重塑,您可以使用np.put

# Generate the sorted indices
ss = np.argsort(s.view(np.ndarray), axis=1)[:,::-1]
ss += (np.arange(ss.shape[0])*ss.shape[1])[:,None] #Add in place, probably trivial improvement

k=3
np.put(s,ss[:,k:],0) #or s.flat[ss[:,k:]]=0
print s

[[ 1.          0.          0.82177072  0.92487807]
 [ 0.          1.          0.94246304  0.7212526 ]
 [ 0.          0.94246304  1.          0.87247418]
 [ 0.92487807  0.          0.87247418  1.        ]]
于 2013-08-15T21:42:51.657 回答
1

如果您发现自己在数组中生成了长长的索引列表,那么很有可能可以使用布尔矩阵以更优雅的方式解决它。在你的情况下:

a = np.random.rand(5, 5)
a = a + a.T # make it symmetrical

sort_idx = np.argsort(np.argsort(a, axis=1), axis=1)
k = 3 # values to keep
# if you want a copy of the original
mask = (sort_idx >= a.shape[1] - k) # positions we want to keep
b = np.zeros_like(a)
b[mask] = a[mask]

# if you wantrd to do the operation in-place
# mask = (sort_idx < a.shape[1] - k) # positions we want to zero
# a[mask] = 0

>>> a
array([[ 1.87816548,  0.86562424,  1.94171234,  0.96565312,  0.53451029],
       [ 0.86562424,  1.13762348,  1.48565754,  0.78031763,  0.51448499],
       [ 1.94171234,  1.48565754,  1.39960519,  0.57456214,  1.32608456],
       [ 0.96565312,  0.78031763,  0.57456214,  1.56469221,  0.74632264],
       [ 0.53451029,  0.51448499,  1.32608456,  0.74632264,  0.55378676]])
>>> b
array([[ 1.87816548,  0.        ,  1.94171234,  0.96565312,  0.        ],
       [ 0.86562424,  1.13762348,  1.48565754,  0.        ,  0.        ],
       [ 1.94171234,  1.48565754,  1.39960519,  0.        ,  0.        ],
       [ 0.96565312,  0.78031763,  0.        ,  1.56469221,  0.        ],
       [ 0.        ,  0.        ,  1.32608456,  0.74632264,  0.55378676]])
于 2013-08-16T15:25:42.227 回答