gpt4 book ai didi

python - 将 2d 矩阵转换为 3d 单热矩阵 numpy

转载 作者:太空狗 更新时间:2023-10-29 17:24:07 25 4
gpt4 key购买 nike

我有 np 矩阵,我想将其转换为 3d 数组,并将元素的一种热编码作为第三维。有没有办法不用遍历每一行例如

a=[[1,3],
[2,4]]

应该做成

b=[[1,0,0,0], [0,0,1,0],
[0,1,0,0], [0,0,0,1]]

最佳答案

方法#1

这是一个滥用 broadcasted 的厚颜无耻的单行本比较 -

(np.arange(a.max()) == a[...,None]-1).astype(int)

sample 运行-

In [120]: a
Out[120]:
array([[1, 7, 5, 3],
[2, 4, 1, 4]])

In [121]: (np.arange(a.max()) == a[...,None]-1).astype(int)
Out[121]:
array([[[1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0]],

[[0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0]]])

对于 0-based 索引,它将是 -

In [122]: (np.arange(a.max()+1) == a[...,None]).astype(int)
Out[122]:
array([[[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0]],

[[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0]]])

如果 one-hot enconding 要覆盖从最小值到最大值的值范围,则用最小值偏移,然后将其提供给建议的0-based 方法> 索引。这也适用于本文稍后讨论的其他方法。

这是在同一台机器上运行的示例 -

In [223]: a
Out[223]:
array([[ 6, 12, 10, 8],
[ 7, 9, 6, 9]])

In [224]: a_off = a - a.min() # feed a_off to proposed approaches

In [225]: (np.arange(a_off.max()+1) == a_off[...,None]).astype(int)
Out[225]:
array([[[1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0]],

[[0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0]]])

如果您对 True1 和 False 为 0 的 bool 数组没问题,您可以跳过 .astype (int) 转换。

方法#2

我们还可以初始化一个 zeros 数组并使用 advanced-indexing 索引到输出中.因此,对于 0-based 索引,我们将有 -

def onehot_initialization(a):
ncols = a.max()+1
out = np.zeros(a.shape + (ncols,), dtype=int)
out[all_idx(a, axis=2)] = 1
return out

辅助函数 -

# https://stackoverflow.com/a/46103129/ @Divakar
def all_idx(idx, axis):
grid = np.ogrid[tuple(map(slice, idx.shape))]
grid.insert(axis, idx)
return tuple(grid)

在处理更大范围的值时,这应该特别高效。

对于 1-based 索引,只需将 a-1 作为输入。

方法 #3:稀疏矩阵解决方案

现在,如果您正在寻找稀疏数组作为输出和 AFAIK,因为 scipy 的内置稀疏矩阵仅支持 2D 格式,您可以获得一个稀疏输出,它是前面显示的输出的 reshape 版本前两个轴合并,第三个轴保持不变。 0-based 索引的实现看起来像这样 -

from scipy.sparse import coo_matrix
def onehot_sparse(a):
N = a.size
L = a.max()+1
data = np.ones(N,dtype=int)
return coo_matrix((data,(np.arange(N),a.ravel())), shape=(N,L))

同样,对于 1-based 索引,只需将 a-1 作为输入。

sample 运行-

In [157]: a
Out[157]:
array([[1, 7, 5, 3],
[2, 4, 1, 4]])

In [158]: onehot_sparse(a).toarray()
Out[158]:
array([[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0]])

In [159]: onehot_sparse(a-1).toarray()
Out[159]:
array([[1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0]])

如果您可以接受稀疏输出,这将比前两种方法好得多。

基于 0 的索引的运行时比较

案例#1:

In [160]: a = np.random.randint(0,100,(100,100))

In [161]: %timeit (np.arange(a.max()+1) == a[...,None]).astype(int)
1000 loops, best of 3: 1.51 ms per loop

In [162]: %timeit onehot_initialization(a)
1000 loops, best of 3: 478 µs per loop

In [163]: %timeit onehot_sparse(a)
10000 loops, best of 3: 87.5 µs per loop

In [164]: %timeit onehot_sparse(a).toarray()
1000 loops, best of 3: 530 µs per loop

案例#2:

In [166]: a = np.random.randint(0,500,(100,100))

In [167]: %timeit (np.arange(a.max()+1) == a[...,None]).astype(int)
100 loops, best of 3: 8.51 ms per loop

In [168]: %timeit onehot_initialization(a)
100 loops, best of 3: 2.52 ms per loop

In [169]: %timeit onehot_sparse(a)
10000 loops, best of 3: 87.1 µs per loop

In [170]: %timeit onehot_sparse(a).toarray()
100 loops, best of 3: 2.67 ms per loop

挤出最佳性能

为了获得最佳性能,我们可以修改方法 #2 以在 2D 形状的输出数组上使用索引,并使用 uint8 dtype 来提高内存效率和领先的到更快的分配,就像这样 -

def onehot_initialization_v2(a):
ncols = a.max()+1
out = np.zeros( (a.size,ncols), dtype=np.uint8)
out[np.arange(a.size),a.ravel()] = 1
out.shape = a.shape + (ncols,)
return out

时间 -

In [178]: a = np.random.randint(0,100,(100,100))

In [179]: %timeit onehot_initialization(a)
...: %timeit onehot_initialization_v2(a)
...:
1000 loops, best of 3: 474 µs per loop
10000 loops, best of 3: 128 µs per loop

In [180]: a = np.random.randint(0,500,(100,100))

In [181]: %timeit onehot_initialization(a)
...: %timeit onehot_initialization_v2(a)
...:
100 loops, best of 3: 2.38 ms per loop
1000 loops, best of 3: 213 µs per loop

关于python - 将 2d 矩阵转换为 3d 单热矩阵 numpy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36960320/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com