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))
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
型 案例二:
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
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
5条答案
按热度按时间ubof19bj1#
方法一
这里有一个厚颜无耻的一行字,滥用
broadcasted
比较-字符串
样品运行-
型
对于
0-based
索引,它将是-型
如果one-hot encoding是覆盖从最小值到最大值的值范围,那么用最小值进行偏移,然后将其馈送到
0-based
索引的建议方法。这也适用于本文后面讨论的其他方法。这里有一个样本运行在相同的-
型
如果你对
1's
的True
和0's
的False的布尔数组没有问题,你可以跳过.astype(int)
的转换。方法二
我们也可以初始化一个零数组,并使用
advanced-indexing
索引到输出中。因此,对于0-based
索引,我们将有-型
帮助函数-
型
当处理更大范围的值时,这应该特别具有性能。
对于
1-based
索引,只需将a-1
作为输入。方法三:稀疏矩阵求解
现在,如果你正在寻找稀疏数组作为输出和AFAIK,因为scipy的内置稀疏矩阵只支持
2D
,你可以得到一个稀疏输出,它是前面显示的输出的整形版本,前两个轴合并,第三个轴保持不变。0-based
索引的实现看起来像这样-型
同样,对于
1-based
索引,只需将a-1
作为输入。样品运行-
型
如果您可以接受稀疏输出,这将比前两种方法好得多。
基于0的索引的索引比较
案例1:
型
案例二:
型
挤出最佳性能
为了挤出最佳性能,我们可以修改方法#2,在
2D
形状的输出数组上使用索引,并使用uint8
dtype以提高内存效率,这会导致更快的赋值,就像这样-型
时间-
型
crcmnpdw2#
如果您尝试为机器学习模型创建独热Tensor(您安装了
tensorflow
或keras
),则可以从https://www.tensorflow.org/api_docs/python/tf/keras/backend/one_hot或https://www.tensorflow.org/api_docs/python/tf/one_hot使用one_hot
函数这就是我正在使用的,并且适用于高维数据。
下面是示例用法:
字符串
lsmd5eda3#
作为对公认答案的补充:如果你有非常少的类要编码,并且如果你可以接受
np.bool
数组作为输出,我发现下面的方法甚至稍微快一点:字符串
时间表(10节课):
型
但是,如果班级数量增加(现在为100个班级),情况就会发生变化:
型
因此,根据您的问题,这两种版本都可能是更快的版本。
epfja78i4#
下面是使用np.eye(单位矩阵)和numpy强大索引的最简单和最优雅的解决方案:
字符串
的数据
fivyi3re5#
我想贡献一个简单的高级索引解决方案,这是在一些其他的答案,在一个更容易访问的方式,而不利用“助手函数”和所有这一切。
我们有一个2维数组a,它是分类的。为了简单起见,让我们把它看作是二进制的,例如:
字符串
我们通过将其初始化为零来创建一个热编码数组:
型
我们做高级索引来提取我们想把1放在one-hot编码数组上的位置。
型
重塑是为了使它们可以被广播。
型
将首先广播x,y和a,它们是可广播到shape(5,8)的。然后它将提取该shape的数组,其值取自onehot数组。它将使该数组成为一个数组,并将这些更改拉回到onehot数组。
在最后一个命令中,我们告诉numpy在数组x,y,a给出的特定坐标中进行赋值。它们对应于onehot的3个维度。赋值的数量由广播的数组x,y,a中的元素数量决定。在这种情况下,它是形状(5,8),所以我们进行40次赋值。每个赋值都有自己的二维坐标,让我们用i和j来捐赠它们。赋值(i,j)在onehot中有目标索引,由
(x[i, j], y[i, j], a[i, j])
给出,额外的坐标用广播版本解释。x[i,j]只是i,y[i,j]是j。所以我们实际上是以onehot[i,j,a[i,j]]为目标。我们使用a作为最后一个坐标,这是第i,j '个条目的onehot目标。换句话说,第(i,j)^个命令是翻转onehot数组中对应于第(i,j)^个条目的所需类。