Python 按索引生成序列/一个热编码

Python 按索引生成序列/一个热编码,python,numpy,Python,Numpy,我有一个序列s=[4,3,1,0,5]和num_classes=6,我想生成一个形状的Numpy矩阵m(len(s),num_classes)其中m[I,j]=1,如果s[I]=j,否则0 Numpy中是否有这样一个函数,我可以在其中传递s和num_类 这也称为k中的1或一个热编码 timeit结果: def b(): m = np.zeros((len(s), num_classes)) m[np.arange(len(s)), s] = 1 return m

我有一个序列
s=[4,3,1,0,5]
num_classes=6
,我想生成一个形状
的Numpy矩阵
m
(len(s),num_classes)
其中
m[I,j]=1,如果s[I]=j,否则0

Numpy中是否有这样一个函数,我可以在其中传递
s
num_类

这也称为k中的1或一个热编码


timeit
结果:

def b():
     m = np.zeros((len(s), num_classes))
     m[np.arange(len(s)), s] = 1
     return m

In [57]: timeit.timeit(lambda: b(), number=1000)
Out[57]: 0.012787103652954102

In [61]: timeit.timeit(lambda: (np.array(s)[:,None]==np.arange(num_classes))+0, number=1000)
Out[61]: 0.018411874771118164

由于您希望每行有一个
1
,因此可以沿第一个轴使用
arange(len(s))
,沿第二个轴使用
s

s = [4,3,1,0,5]
n = len(s)
k = 6
m = np.zeros((n, k))
m[np.arange(n), s] = 1
m
=> 
array([[ 0.,  0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  1.]])

m.nonzero()
=> (array([0, 1, 2, 3, 4]), array([4, 3, 1, 0, 5]))
这可以被认为是使用索引(0,4),然后(1,3),然后(2,1),(3,0),(4,5)。

您可以使用-

样本运行-

In [439]: s
Out[439]: [4, 3, 1, 0, 5]

In [440]: num_classes = 9

In [441]: (np.array(s)[:,None]==np.arange(num_classes))+0
Out[441]: 
array([[0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0]])

如果您的一个热编码为多维数组添加了一个额外维度,那么接受的答案将不起作用。使用广播将给您带来意想不到的结果-。这个解决方案很优雅,但效率不高

labels.shape # (80, 256, 10)

def b(labels):
     onehot = np.zeros((a,b,c,num_classes), dtype=float)

     # This is the slow, dumb line:
     (onehot_i, onehot_j, onehot_k) = np.ones(labels.shape).nonzero()

     thehotone = labels[onehot_i, onehot_j, onehot_k]
     onehot[onehot_i, onehot_j, onehot_k, thehotone] = 1
     return onehot

Brocasting仍然有效,只是做而已


$(labels[:,:,:,None]==np.arange(num_classes))+0

我使用了
timeit
,这似乎是最快的解决方案。谢谢@阿尔伯特很酷。如果你能将计时结果添加到问题中,那就太好了。对于后人来说,如果存在多个虚拟维度,你会怎么做?广播会产生意外的结果,而非零会丢弃所有零索引。@user1158559您可能应该发布一个新问题,准确地解释您要做的事情。写了一半就明白了,但不确定我是否喜欢答案。现在将发布一个新的答案。
labels.shape # (80, 256, 10)

def b(labels):
     onehot = np.zeros((a,b,c,num_classes), dtype=float)

     # This is the slow, dumb line:
     (onehot_i, onehot_j, onehot_k) = np.ones(labels.shape).nonzero()

     thehotone = labels[onehot_i, onehot_j, onehot_k]
     onehot[onehot_i, onehot_j, onehot_k, thehotone] = 1
     return onehot