Python scipy中稀疏矩阵上的Log-sum-exp技巧

Python scipy中稀疏矩阵上的Log-sum-exp技巧,python,numpy,scipy,sparse-matrix,logarithm,Python,Numpy,Scipy,Sparse Matrix,Logarithm,将类似于scipy.misc.logsumexp的内容应用于稀疏矩阵(例如scipy.sparse.csr_矩阵)的最佳方法是什么,指定一个轴 关键是要在计算中去掉零 更新 在scipy.sparse中,最好指定我正在寻找执行的东西,简单地执行一系列exp-elem-wise、行求和和和log-elem-wise都是微不足道的。不那么麻烦的是,以干净的方式计算行的最大值,并在稀疏矩阵行中的每个元素减去相应的最大向量元素(最后保留一个稀疏矩阵)时将其减去。CSR矩阵的非零项X通过 X[i].dat

将类似于
scipy.misc.logsumexp
的内容应用于稀疏矩阵(例如
scipy.sparse.csr_矩阵
)的最佳方法是什么,指定一个轴

关键是要在计算中去掉零

更新


scipy.sparse
中,最好指定我正在寻找执行的东西,简单地执行一系列exp-elem-wise、行求和和和log-elem-wise都是微不足道的。不那么麻烦的是,以干净的方式计算行的最大值,并在稀疏矩阵行中的每个元素减去相应的最大向量元素(最后保留一个稀疏矩阵)时将其减去。

CSR矩阵的非零项
X
通过

X[i].data
实际行的值的(排列)将通过在其上附加
X.shape[1]-len(X[i].data)
0来获得

logsumexp(a) = max(a) + log(∑ exp[a - max(a)])
对于向量
a
。让我们设置
b=X[i].data
k=X.shape[1]-len(X[i].data)
,并将先前排列的
X
行表示为

(b, 0ₖ)
使用0ₖ 表示长度
k
的零向量,以及(⋅, ⋅) 用于连接。然后

logsumexp((b, 0ₖ))
 = max((b, 0ₖ)) + log(∑ exp[(b, 0ₖ) - max((b, 0ₖ))])
 = max(max(b), 0) + log(∑ exp[(b, 0ₖ) - max(max(b), 0)])
 = max(max(b), 0) + log(∑ exp[b - max(max(b), 0)] + ∑ exp[0ₖ - max(max(b), 0)])
 = max(max(b), 0) + log(∑ exp[b - max(max(b), 0)] + k × exp[-max(max(b), 0)])
所以我们得到了算法

def logsumexp_csr_row(x):
    data = x.data
    mx = max(np.max(data), 0)
    tmp = data - mx
    r = np.exp(tmp, out=tmp).sum()
    k = X.shape[1] - len(data)
    return mx + np.log(r + k * np.exp(-mx))
对于CSR行向量。将此算法扩展到完整矩阵很容易通过列表理解完成,尽管更有效的形式是使用
indptr

def logsumexp_csr_rows(X):
    result = np.empty(X.shape[0])
    for i in range(X.shape[0]):
        data = X.data[X.indptr[i]:X.indptr[i+1]]
        # fill in from logsumexp_csr_row
        result[i] = mx + np.log(r + k * np.exp(-mx))
    return result
按列的版本要复杂得多;转换矩阵并转换回CSR可能是最容易的


更新好吧,我误解了这个问题:OP根本不想处理零,所以上面的推导是无用的,算法应该是正确的

def logsumexp_row_nonzeros(X):
    result = np.empty(X.shape[0])
    for i in range(X.shape[0]):
        result[i] = logsumexp(X.data[X.indptr[i]:X.indptr[i+1]])
    return result

这只是在CSR矩阵上填写行操作的一般方案。对于列操作,转置,转换回CSR并应用上述内容。

如果尚未在
sparse
中添加等效项,则需要编写自己的。首先,我将使用
np.log(np.sum(np.exp(a),axis=n))
。如果您了解
csr
数据结构,您可以直接对其
数据
属性进行操作。您可以将其与numpy一起使用,因为numpy不支持稀疏矩阵Larsman的答案是我想到的
数据
的使用方式。在某些情况下,它足以对所有非零值进行操作;在这种情况下我认为,在我的特殊情况下,你应该省略关于零的部分,因为我只想对我的非零值进行操作matrix@rano在这种情况下,问题完全是无关紧要的。我将更新答案。是的,它是无关紧要的,因为您正在以python方式按行操作:顺便说一句,让答案保持原样,只需添加一个小案例作为更新,因为它可以方便其他人;)