Python 如何以完全矢量化的方式确定多行之间的行相等性?

Python 如何以完全矢量化的方式确定多行之间的行相等性?,python,numpy,vectorization,similarity,Python,Numpy,Vectorization,Similarity,我有一个numpy.ndarray称为分组,大小为(S,N)。分组的每一行为我提供了数据样本的组标签。我运行算法S次,并在每次迭代中获得新的组标签 我想确定在整个S迭代中,我的每个数据样本与我的每个其他数据样本以完全矢量化的方式具有相同组标签的次数 以不完全矢量化的方式: sim_matrix = np.zeros((N, N)) for s in range(S): sim_matrix += np.equal.outer(grouping[s, :], grouping[s, :])

我有一个
numpy.ndarray
称为
分组
,大小为
(S,N)
分组的每一行
为我提供了数据样本的组标签。我运行算法
S
次,并在每次迭代中获得新的组标签

我想确定在整个
S
迭代中,我的每个数据样本与我的每个其他数据样本以完全矢量化的方式具有相同组标签的次数

以不完全矢量化的方式:

sim_matrix = np.zeros((N, N))
for s in range(S):
    sim_matrix += np.equal.outer(grouping[s, :], grouping[s, :])

一种矢量化方法是使用-

对于性能,我们可以使用-


您想要比较相同的行。一种方法是将原始块中的整行分组:

S,N=12,2
a=np.random.randint(0,3,(S,N)) #12 samples of two labels.

#a
    0  1
0   2  2
1   2  0
2   1  2
3   0  0
4   0  1
5   1  1
6   0  1
7   0  1
8   0  1
9   0  0
10  2  2
11  0  0

samples=np.ascontiguousarray(a).view(dtype((void,a.strides[0])))
sample.shape
则是(S,1)

现在,您可以使用
np.unique
清点您的样本,并使用Pandas数据帧创建漂亮的报告:

_,inds,invs=np.unique(samples,return_index=True, return_inverse=True)

df=pd.DataFrame(invs)
result=df.reset_index().groupby(0).index.apply(list).to_frame()
result['sample']=[list(x) for x in a[inds]]
为了


如果样本之间的拟合度很小,则可以是O(S lns),而您的样本是O(N²S)

equal.outer的和是计算列的所有对相似性的一种神秘方法:

sum_i sum_jk (A[i,j] == A[i,k])  is the same as
sum_jk sum_i (A[i,j] == A[i,k])
其中,
sum_i
在行上循环,
sum_jk
在所有列对上循环。 通过计算两个向量不同的位置数来比较两个向量 被称为 . 如果我们将上面的
==
更改为
=,相似性与距离=nrows-相似性
(最相似⇔ 距离0),我们得到了问题:
求一串向量的所有对之间的汉明距离:

def allpairs_hamming( A, dtype=np.uint32 ):
    """ -> Hamming distances between all pairs of rows of A """
    nrow, ncol = A.shape
    allpair_dist = np.zeros( [nrow, nrow], dtype=dtype )
    for j in xrange(nrow):
        for k in xrange( j + 1, nrow ):
            allpair_dist[j,k] = allpair_dist[k,j] = (A[j] != A[k]).sum()  # row diff
    return allpair_dist

allpairs_hamming: 30.7 sec, 3 ns per cmp  Nvec 2000  Veclen 5000  A 10m  pairdist uint32 15m
几乎所有的cpu时间都在diff行中,而不是在j。。。对于k来说,在一台普通mac电脑上,每标量比较3纳秒也不错。 但是,如果每一行
A[j]
位于连续内存中,则内存缓存速度会快得多, 对于numpy C阶数组。 除此之外,无论是“所有行对”还是“所有列对” 没关系,只要你清楚

(是否有可能在时间和空间上找到“附近”的配对 另请参见:
(bug:hamming.mean not.sum)


数据样本总是有用的。
S
N
的典型值是什么?@Divakar S大约是5000,N在1000的10秒内。您真的需要完整的模拟矩阵吗?或者,这是一个衍生数量的实际利益?一次调用np.equal.outer的典型稀疏度(非零的百分比)是多少?在这种情况下,对于您提到的序列号,我认为这个循环解决方案非常有效!但是它完全消耗了我的内存,而for循环没有。我投了更高的票。@NewNameStat是的,这是这里的权衡。
          index samples
0                      
0    [3, 9, 11]  [0, 0]
1  [4, 6, 7, 8]  [0, 1]
2           [5]  [1, 1]
3           [2]  [1, 2]
4           [1]  [2, 0]
5       [0, 10]  [2, 2]
sum_i sum_jk (A[i,j] == A[i,k])  is the same as
sum_jk sum_i (A[i,j] == A[i,k])
def allpairs_hamming( A, dtype=np.uint32 ):
    """ -> Hamming distances between all pairs of rows of A """
    nrow, ncol = A.shape
    allpair_dist = np.zeros( [nrow, nrow], dtype=dtype )
    for j in xrange(nrow):
        for k in xrange( j + 1, nrow ):
            allpair_dist[j,k] = allpair_dist[k,j] = (A[j] != A[k]).sum()  # row diff
    return allpair_dist

allpairs_hamming: 30.7 sec, 3 ns per cmp  Nvec 2000  Veclen 5000  A 10m  pairdist uint32 15m