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)似乎也不起作用。

我怎样才能做到这一点?

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

比较

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

例如,人们会写T.neq(A, 0),而不是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 没有单独的布尔类型(掩码是零和一),因此必须首先调用 nonzero() 来获取非零元素的索引。此外,这不适用于稀疏矩阵。

对非零稀疏元素进行操作

Theano 提供了稀疏操作,这些操作据说是结构化的,并且只对非零元素进行操作。看:http://deeplearning.net/software/theano/tutorial/sparse.html#structured-operation

更准确地说,它们对稀疏矩阵的data属性进行操作,与元素的索引无关。此类操作易于实现。请注意,结构化操作将对 data 数组中的所有值进行操作,包括那些显式设置为零的值。

这是使用 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 个值,但新创建的矩阵不应该。

矩阵还具有基于numpy方法建模的nonzero方法。 在实践中,它将矩阵转换为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 ]])

T.where有效。

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

@Seppo 恩瓦里的回答似乎更快。所以我会接受他的回答。

最新更新