稀疏(转换)矩阵的简单构造

simplity construction of sparse (transition) matrix

我正在从 n1 x n2 x ... x nN x nN 数组构造一个转换矩阵。为了具体起见,让N = 3,例如

import numpy as np

# example with N = 3
n1, n2, n3 = 3, 2, 5
dim = (n1, n2, n3)
arr = np.random.random_sample(dim + (n3,))

此处 arr 包含 2 个状态之间的转换概率,其中“from”-state 由前 3 个维度索引,“to”-state 由前 2 个和最后一个维度索引.我想构建一个转换矩阵,将这些概率表示为稀疏 (n1*n2*n3) x (n1*n2*n3 矩阵。

为了澄清,让我提供我当前的方法来完成我想做的事情。不幸的是,当 Nn1, n2, ... 很大时,它很慢并且不起作用。所以我正在寻找一种更有效的方法来做同样的事情,以便更好地解决更大的问题。

我的做法

import numpy as np
from scipy import sparse as sparse

## step 1: get the index correponding to each dimension of the from and to state

# ravel axes 1 to 3 into single axis and make sparse 
spmat = sparse.coo_matrix(arr.reshape(np.prod(dim), -1))
data = spmat.data
row = spmat.row
col = spmat.col

# use unravel to get idx for 
row_unravel = np.array(np.unravel_index(row, dim))
col_unravel = np.array(np.unravel_index(col, n3))

## step 2: combine "to" index with rows 1 and 2 of "from"-index to get "to"-coordinates in full state space

row_unravel[-1, :] = col_unravel # first 2 dimensions of state do not change
colnew = np.ravel_multi_index(row_unravel, dim) # ravel back to 1d

## step 3: assemble transition matrix

out = sparse.coo_matrix((data, (row, colnew)), shape=(np.prod(dim), np.prod(dim)))

最后的想法

我会运行这个代码很多次。在迭代过程中,arr 的数据可能会发生变化,但维度将保持不变。所以我可以做的一件事是从文件中保存和加载 rowcolnew,跳过 data 定义(第 2 行)和代码最后一行之间的所有内容。您认为这是最好的方法吗?

编辑:我看到这个策略的一个问题是,如果 arr 的某些元素为零(这是可能的),那么 data 的大小将在迭代中发生变化。

一种优于 OP 中发布的方法的方法。不确定它是否最有效。

import numpy as np
from scipy import sparse

# get col and row indices
idx = np.arange(np.prod(dim))
row = idx.repeat(dim[-1])
col = idx.reshape(-1, dim[-1]).repeat(dim[-1], axis=0).ravel()

# get the data
data = arr.ravel()

# construct the sparse matrix
out = sparse.coo_matrix((data, (row, col)), shape=(np.prod(dim), np.prod(dim)))

有两点可以改进:

(1) 如果 arr 是稀疏矩阵,输出矩阵 out 会将零编码为非零。

(2) 该方法依赖于新状态作为 dim 的最后一个维度。最好概括一下 arr 的最后一个轴可以替换任何原始轴,而不仅仅是最后一个。