Theano:在稀疏矩阵的非零元素上运算

时间:2016-03-16 18:11:42

标签: python numpy theano

我试图在稀疏的theano变量中取exp个非零元素。我有当前的代码:

A = T.matrix("Some matrix with many zeros")
A_sparse = theano.sparse.csc_from_dense(A)

我试图做一些与以下numpy语法等效的事情:

mask = (A_sparse != 0)
A_sparse[mask] = np.exp(A_sparse[mask])

但Theano还没有支持!=面具。 (并且(A_sparse > 0) | (A_sparse < 0)似乎也无效。)

我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:1)

对Theano中稀疏矩阵的支持是不完整的,所以有些事情很难实现。您可以在该特定情况下使用theano.sparse.structured_exp(A_sparse),但我会在下面更详细地回答您的问题。

<强>比较

在Theano中,通常会使用此处描述的比较运算符:http://deeplearning.net/software/theano/library/tensor/basic.html

例如,代替A != 0,可以写T.neq(A, 0)。对于稀疏矩阵,必须使用theano.sparse中的比较运算符。两个运算符都必须是稀疏矩阵,结果也是稀疏矩阵:

mask = theano.sparse.neq(A_sparse, theano.sparse.sp_zeros_like(A_sparse))

修改子订单

为了修改矩阵的一部分,可以使用theano.tensor.set_subtensor。使用密集矩阵,这将起作用:

indices = mask.nonzero()
A = T.set_subtensor(A[indices], T.exp(A[indices]))

请注意,Theano没有分离的布尔类型 - 掩码为零和1 - 因此必须先调用nonzero()来获取非零元素的索引。此外,这不适用于稀疏矩阵。

在非零稀疏元素上运行

Theano提供稀疏操作,据说这些操作是结构化的,仅在非零元素上运行。看到: http://deeplearning.net/software/theano/tutorial/sparse.html#structured-operation

更确切地说,它们在稀疏矩阵的data属性上运行,与元素的索引无关。这些操作很容易实现。请注意,结构化操作将对data数组中的所有值进行操作,也将显式设置为零。

答案 1 :(得分:0)

以下是使用scipy.sparse模块执行此操作的方法。我不知道theano如何实现稀疏。它可能基于类似的想法(因为它使用类似csc的名称)

In [224]: A=sparse.csc_matrix([[1.,0,0,2,0],[0,0,3,0,0],[0,1,1,2,0]])

In [225]: A.A
Out[225]: 
array([[ 1.,  0.,  0.,  2.,  0.],
       [ 0.,  0.,  3.,  0.,  0.],
       [ 0.,  1.,  1.,  2.,  0.]])

In [226]: A.data
Out[226]: array([ 1.,  1.,  3.,  1.,  2.,  2.])

In [227]: A.data[:]=np.exp(A.data)

In [228]: A.A
Out[228]: 
array([[  2.71828183,   0.        ,   0.        ,   7.3890561 ,   0.        ],
       [  0.        ,   0.        ,  20.08553692,   0.        ,   0.        ],
       [  0.        ,   2.71828183,   2.71828183,   7.3890561 ,   0.        ]])

csc格式的主要属性dataindicesindptr。如果你在创建后摆弄它们,data可能有0个值,但是新创建的矩阵不应该。

矩阵还有一个nonzero方法,模仿numpy个方法。实际上,它会将矩阵转换为coo格式,过滤掉任何零值,并返回rowcol属性:

In [229]: A.nonzero()
Out[229]: (array([0, 0, 1, 2, 2, 2]), array([0, 3, 2, 1, 2, 3]))

csc格式允许将索引编译为密集的numpy数组:

In [230]: A[A.nonzero()]
Out[230]: 
matrix([[  2.71828183,   7.3890561 ,  20.08553692,   2.71828183,
           2.71828183,   7.3890561 ]])

答案 2 :(得分:0)

T.where有效。

A_sparse = T.where(A_sparse == 0, 0, T.exp(A_sparse))

@Seppo Envari的回答似乎更快了。所以我会接受他的回答。