稀疏(转换)矩阵的简单构造
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
矩阵。
为了澄清,让我提供我当前的方法来完成我想做的事情。不幸的是,当 N
和 n1, 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
的数据可能会发生变化,但维度将保持不变。所以我可以做的一件事是从文件中保存和加载 row
和 colnew
,跳过 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
的最后一个轴可以替换任何原始轴,而不仅仅是最后一个。
我正在从 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
矩阵。
为了澄清,让我提供我当前的方法来完成我想做的事情。不幸的是,当 N
和 n1, 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
的数据可能会发生变化,但维度将保持不变。所以我可以做的一件事是从文件中保存和加载 row
和 colnew
,跳过 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
的最后一个轴可以替换任何原始轴,而不仅仅是最后一个。