问题是,给定任意1-d向量y
,将其扩展为d
基础向量n
。
扩展规则是:y
中的每个元素都是n * n单位矩阵中列的索引。
例如:
y = [3, 0, 1]
n = 4
自n = 4
以来,我们有4*4
单位矩阵:
[1, 0, 0, 0]
[0, 1, 0, 0]
[0, 0, 1, 0]
[0, 0, 0, 1]
使用规则展开每个元素y
,我们有:
[0, 1, 0]
[0, 0, 1]
[0, 0, 0]
[1, 0, 0]
我想使用theano来解决这个问题,非常大的n
(> 50k)和非常长的y
(> 10k),因此效率非常重要。
使用numpy的解决方案是微不足道的,但numpy.eye函数可能会花费太多,我们可能会使用其他方法来使其更快。比较以下方法:
import numpy as np
import theano
import theano.tensor as T
n = 25500
y_value = np.asarray([2, 0, 10, 4], dtype='int32')
# method 1
%timeit np.eye(n)[y_value]
# 10 loops, best of 3: 56.9 ms per loop
# method 2
def vec(i):
e = np.zeros(n)
e[i] = 1
return e
%timeit np.vstack([vec(i) for i in y_value])
# 100 loops, best of 3: 16.3 ms per loop
但是,第二种方法可能无法在theano中起作用,因为符号变量中的循环可能并不重要。有没有一种方法可以避免使用T.eye?
y_value
可以是任意的1-d向量。
答案 0 :(得分:1)
您可以尝试其他方法。在我的电脑中:
>>> %timeit np.eye(n)[y_value]
1 loops, best of 3: 544 ms per loop
但是,如果事先知道所需的行,则无需创建整个数组。你可以这样做:
>>> n = 25500
>>> n_rows = y_value.size
>>> r = np.zeros((n_rows, n))
>>> r[range(n_rows), y_value] = 1
您创建了一个更小的数组,只有y x n
,其中y
是索引向量的大小,并在每一行中填充它。我电脑的时间是:
>>> %%timeit
..: r = np.zeros((n_rows, n))
..: r[range(n_rows), y_value] = 1
100 loops, best of 3: 3.8 ms per loop
x151
在我的笔记本电脑中加速。
此外,如果你不想在后面(x轴)有一个满是零的数组,你可以这样做:
>>> %%timeit
..: r = np.zeros((n_rows, y_value.max()+1))
..: r[range(n_rows), y_value] = 1
100000 loops, best of 3: 16 µs per loop
哪个更快,但结果数组为y x ymax
,在这种情况下为99 x 100
,可能不是您想要的。