在theano中比T.eye更好的方式

时间:2015-01-07 09:59:39

标签: python numpy theano

问题是,给定任意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向量。

1 个答案:

答案 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,可能不是您想要的。