稀疏转移矩阵的简单构造 我的方法最后的想法

问题描述

我正在从 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,n3)
arr = np.random.random_sample(dim + (n3,))

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

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

我的方法

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 的最后一个轴可以替换任何原始轴,而不仅仅是最后一个。