>我正在尝试在稀疏的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
格式在data
、indices
、indptr
的主要属性。 如果您在创建后摆弄它们,data
可能会有一些 0 个值,但新创建的矩阵不应该。
矩阵还具有基于numpy
方法建模的nonzero
方法。 在实践中,它将矩阵转换为coo
格式,过滤掉任何零值,并返回row
和col
属性:
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 恩瓦里的回答似乎更快。所以我会接受他的回答。