最有效的单热编码器
Most efficient one-hot-encoder
说,我有一个 Numpy 数组 target
,如下所示:
target = np.array([1, 2, 3, 2, 3, 2, 3, 1, 1, 3])
我知道目标值的范围:即1-3。
现在,我想创建一个与目标长度相同的目标编码。
为此,我使用了以下代码:
target_one_hot = np.zeros([len(target], 4)
for i in range(0, len(target)):
target_one_hot[i, target[i]] = 1
target_one_hot = = np.delete(target_one_hot , 0, 1)
这行得通。但是,我怀疑通过省略 for 循环可以更有效地编写此操作。我该怎么做?
方法 #1
创建一个掩码(用于内存 + 性能。效率),在目标给定的索引处分配 1s
/True
(以 1
开头时偏移一个),最后使用视图转换为 int
数组 -
mask = np.zeros((len(target), 3), dtype=bool)
mask[np.arange(len(target)),target-1] = 1
out = mask.view('i1')
如果最终输出需要作为浮点数,请在开始时使用 float
dtype 初始化 mask
并跳过最终的 int
转换。
方法 #2
另一个通过在 identity-matrix
上建立索引并偏移 target
-
进行散列
np.eye(3, dtype=bool)[target-1].view('i1')
方法 #3
直接用target
散列-
np.eye(4, k=-1, dtype=bool)[target,:-1].view('i1')
大型数据集上的计时 -
In [46]: target = np.random.randint(1,4,1000000)
In [47]: %%timeit
...: mask = np.zeros((len(target), 3), dtype=bool)
...: mask[np.arange(len(target)),target-1] = 1
10.3 ms ± 48.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [48]: %timeit np.eye(3, dtype=bool)[target-1]
14.3 ms ± 241 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [49]: %timeit np.eye(4, k=-1, dtype=bool)[target]
13.1 ms ± 80.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
有一个OneHotEncoder
:
from sklearn.preprocessing import OneHotEncoder
a = OneHotEncoder().fit_transform(target.reshape(-1,1))
您的 One-hot 矩阵将是一个稀疏矩阵,您可以通过以下方式获取 numpy 数组:
a.toarray()
另一方面,如果您已经知道范围:
np.array(np.arange(1,4)[:,None]==target, dtype=np.int)
# 4.23 ms ± 66.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
说,我有一个 Numpy 数组 target
,如下所示:
target = np.array([1, 2, 3, 2, 3, 2, 3, 1, 1, 3])
我知道目标值的范围:即1-3。
现在,我想创建一个与目标长度相同的目标编码。
为此,我使用了以下代码:
target_one_hot = np.zeros([len(target], 4)
for i in range(0, len(target)):
target_one_hot[i, target[i]] = 1
target_one_hot = = np.delete(target_one_hot , 0, 1)
这行得通。但是,我怀疑通过省略 for 循环可以更有效地编写此操作。我该怎么做?
方法 #1
创建一个掩码(用于内存 + 性能。效率),在目标给定的索引处分配 1s
/True
(以 1
开头时偏移一个),最后使用视图转换为 int
数组 -
mask = np.zeros((len(target), 3), dtype=bool)
mask[np.arange(len(target)),target-1] = 1
out = mask.view('i1')
如果最终输出需要作为浮点数,请在开始时使用 float
dtype 初始化 mask
并跳过最终的 int
转换。
方法 #2
另一个通过在 identity-matrix
上建立索引并偏移 target
-
np.eye(3, dtype=bool)[target-1].view('i1')
方法 #3
直接用target
散列-
np.eye(4, k=-1, dtype=bool)[target,:-1].view('i1')
大型数据集上的计时 -
In [46]: target = np.random.randint(1,4,1000000)
In [47]: %%timeit
...: mask = np.zeros((len(target), 3), dtype=bool)
...: mask[np.arange(len(target)),target-1] = 1
10.3 ms ± 48.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [48]: %timeit np.eye(3, dtype=bool)[target-1]
14.3 ms ± 241 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [49]: %timeit np.eye(4, k=-1, dtype=bool)[target]
13.1 ms ± 80.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
有一个OneHotEncoder
:
from sklearn.preprocessing import OneHotEncoder
a = OneHotEncoder().fit_transform(target.reshape(-1,1))
您的 One-hot 矩阵将是一个稀疏矩阵,您可以通过以下方式获取 numpy 数组:
a.toarray()
另一方面,如果您已经知道范围:
np.array(np.arange(1,4)[:,None]==target, dtype=np.int)
# 4.23 ms ± 66.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)