从标签列表 python 创建关联矩阵的快速方法?

Fast way to create incidence matrix from list of label python?

我有一个数组 y, len(y) = M,其中包含来自 0 -> N 的值。例如,使用 N = 3:

y = [0, 2, 0, 1, 2, 1, 0, 2]

关联矩阵A定义如下:

一个简单的算法是:

def incidence(y):
    M = len(y)
    A = np.zeros((M,M))
    for i in range(M):
        for j in range(M):
            if y[i]==y[j]:
                A[i,j] = 1
    return A

但这很慢。有什么办法可以更快地做到这一点?例如,使用列表理解或矢量化。

你可以利用 numpy broadcasting 在我们的 python 上获得一些效率,只需询问 y 是否等于它的转置:

import numpy as np

y = np.array([1, 2, 1, 0, 0, 1, 2])

def mat_me(y):
    return (y == y.reshape(-1, 1)).astype(int)

mat_me(y)

产生:

array([[1, 0, 1, 0, 0, 1, 0],
       [0, 1, 0, 0, 0, 0, 1],
       [1, 0, 1, 0, 0, 1, 0],
       [0, 0, 0, 1, 1, 0, 0],
       [0, 0, 0, 1, 1, 0, 0],
       [1, 0, 1, 0, 0, 1, 0],
       [0, 1, 0, 0, 0, 0, 1]])

比较:

y = np.random.choice([1, 2, 3], size=3000)

def mat_me_py(y):
    return (y == y.reshape([-1, 1])).astype(int)

%timeit mat_me_py(y)  
# 28.6 ms ± 1.11 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

对比

y = np.random.choice([1, 2, 3], size=3000)
y = list(y)

def mat_me_py(y):
    return [[int(a == b) for a in y] for b in y]

%timeit mat_me_py(y)
# 4.16 s ± 213 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

在较大的列表中差异会变得非常明显。