我是Python的新手,这似乎很天真。我正在使用coo_matrix(scipy稀疏矩阵) M 并希望返回M的三元组:
row_index,column_index,random_index
具备以下条件:
我可以提出以下功能:
def get_triplets(M):
return M.row, M.col, np.random.randint(M.shape[1], size=len(M.row))
上述函数中的一切正常,但三元组的最后一个条目 - random_index 不是理想的方式。不保证随机索引不会位于该行的非零索引集合中。换句话说,不满足条件数(5)
是否有一种有效的方法可以返回满足上述所有5个条件的三元组。希望我能说清楚,并感谢任何帮助解决我的问题
由于
答案 0 :(得分:1)
对于库矩阵M
,M.row
,M.col
和M.data
是定义矩阵的3个数组,并一起标识所有非零条目。它们可能是无序的,它们可能包含重复项。
In [1]: from scipy import sparse
In [2]: row=[0,0,1,1,1,2,2]
In [3]: col=[0,2,0,1,0,1,2]
In [4]: data=[1,2,3,4,5,6,7]
In [5]: M=sparse.coo_matrix((data,(row,col)))
In [6]: M
Out[6]:
<3x3 sparse matrix of type '<class 'numpy.int32'>'
with 7 stored elements in COOrdinate format>
In [7]: print(M)
(0, 0) 1
(0, 2) 2
(1, 0) 3
(1, 1) 4
(1, 0) 5
(2, 1) 6
(2, 2) 7
In [8]: M.A
Out[8]:
array([[1, 0, 2],
[8, 4, 0],
[0, 6, 7]])
我们可以将其设为规范 - 无需重复排序:
In [9]: M.sum_duplicates()
In [10]: print(M)
(0, 0) 1
(1, 0) 8
(1, 1) 4
(2, 1) 6
(0, 2) 2
(2, 2) 7
顺便说一句,这是转换为csr
格式的一步。
(Opps - 首先按列排序的lex)
如果我正确地对随机位进行了图像处理,则对于每个非零条目,您需要从同一行的零时隙中随机选择。我假设我们不关心是否有重复。
所以我们需要一起收集所有行。
使用lil
格式
In [13]: Ml = M.tolil()
In [14]: Ml.data
Out[14]: array([[1, 2], [8, 4], [6, 7]], dtype=object)
In [16]: Ml.rows
Out[16]: array([[0, 2], [0, 1], [1, 2]], dtype=object)
只需迭代Ml.rows
中的每个列表并生成随机选择。
这是一个开始:
def foo(cols, N):
c = set(range(N))
c = c.difference(cols)
return np.random.choice(list(c))
In [29]: [foo(c,3) for c in Ml.rows]
Out[29]: [1, 2, 0]
不完全是我们想要的;它为每一行选择一个零列。在这个例子中,每行只有一个。
更改choice
以便每次调用返回多个值:
def foo(cols, N):
c = set(range(N))
c = c.difference(cols)
return np.random.choice(list(c),size=len(cols), replace=True)
In [32]: [foo(c,3) for c in Ml.rows]
Out[32]: [array([1, 1]), array([2, 2]), array([0, 0])]
我们可以将这些随机值写回Ml
作为data
In [37]: randval = [foo(c,3) for c in Ml.rows]
In [38]: randval
Out[38]: [array([1, 1]), array([2, 2]), array([0, 0])]
In [39]: Ml.data
Out[39]: array([[1, 2], [8, 4], [6, 7]], dtype=object)
In [40]: Ml.data[:] = randval
In [41]: Ml.data
Out[41]: array([array([1, 1]), array([2, 2]), array([0, 0])], dtype=object)
In [42]: Ml.A
Out[42]:
array([[1, 0, 1],
[2, 2, 0],
[0, 0, 0]], dtype=int32)
In [45]: print(Ml)
(0, 0) 1
(0, 2) 1
(1, 0) 2
(1, 1) 2
(2, 1) 0
(2, 2) 0
In [48]: Mo=Ml.tocoo()
In [51]: np.column_stack((Mo.row, Mo.col, Mo.data))
Out[51]:
array([[0, 0, 1],
[0, 2, 1],
[1, 0, 2],
[1, 1, 2],
[2, 1, 0],
[2, 2, 0]], dtype=int32)
如果数组较大且每行有多个零列,则此显示更有意义。如果任何行密集(没有零),我的代码也会中断。
所以一起
In [56]: M=sparse.rand(10,10,.2,'coo')
In [58]: Ml=M.tolil()
In [59]: randval = [foo(c,Ml.shape[1]) for c in Ml.rows]
In [61]: Ml.data[:] = randval
In [62]: Mo=Ml.tocoo()
In [63]: np.column_stack((Mo.row, Mo.col, Mo.data))
从评论中复制,以便于格式化
最初,我有这个功能:
def get_triplets(M):
return M.row, M.col, np.random.randint(M.shape[1], size=len(M.row))
它及时运作但不一致。但现在:
def get_triplets(mat):
M1 = mat.tolil()
randval = [foo(c, M1.shape[1]) for c in M1.rows]
M1.data[:] = randval
Mo = M1.tocoo()
return_mat = np.column_stack((Mo.row, Mo.col, Mo.data))
return return_mat[:, 0], return_mat[:, 1], return_mat[:, 2]