scipy csr_matrix 来自表示为集合列表的几个向量
scipy csr_matrix from several vectors represented as list of sets
我有几个表示为元组列表的稀疏向量,例如。
[[(22357, 0.6265631775164965),
(31265, 0.3900572375543419),
(44744, 0.4075397480094991),
(47751, 0.5377595092643747)],
[(22354, 0.6265631775164965),
(31261, 0.3900572375543419),
(42344, 0.4075397480094991),
(47751, 0.5377595092643747)],
...
]
我的目标是 scipy.sparse.csr_matrix
由数百万个这样的向量组成。
我想问问是否有一些简单优雅的解决方案来进行这种转换,而不是试图将所有内容都卡在内存中。
编辑:
澄清一下:我的目标是构建二维矩阵,其中我的每个稀疏向量代表矩阵中的一行。
考虑以下几点:
import numpy as np
from scipy.sparse import csr_matrix
vectors = [[(22357, 0.6265631775164965),
(31265, 0.3900572375543419),
(44744, 0.4075397480094991),
(47751, 0.5377595092643747)],
[(22354, 0.6265631775164965),
(31261, 0.3900572375543419),
(42344, 0.4075397480094991),
(47751, 0.5377595092643747)]]
indptr = np.cumsum([0] + map(len, vectors))
indices, data = np.vstack(vectors).T
A = csr_matrix((data, indices.astype(int), indptr))
不幸的是,通过这种方式,列索引从整数转换为双精度并返回。 This works correctly 适用于非常大的矩阵,但并不理想。
将 indices,data
收集到结构化数组中可避免整数-双精度转换问题。它也比 vstack
方法快一点(在有限测试中)(使用这样的列表数据 np.array
比 np.vstack
快。)
indptr = np.cumsum([0]+[len(i) for i in vectors])
aa = np.array(vectors,dtype='i,f').flatten()
A = sparse.csr_matrix((aa['f1'], aa['f0'], indptr))
我用 map
替换了列表理解,因为我使用的是 Python3。
coo
格式的索引 (data, (i,j))
可能更直观
ii = [[i]*len(v) for i,v in enumerate(vectors)])
ii = np.array(ii).flatten()
aa = np.array(vectors,dtype='i,f').flatten()
A2 = sparse.coo_matrix((aa['f1'],(np.array(ii), aa['f0'])))
# A2.tocsr()
这里,第一步的ii
是每个子列表的行号。
[[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3],
...]]
这种构造方法比csr
直接indptr
慢。
对于每行条目数量不同的情况,此方法有效(使用 intertools.chain
来展平列表):
示例列表(暂时没有空行):
In [779]: vectors=[[(1, .12),(3, .234),(6,1.23)],
[(2,.222)],
[(2,.23),(1,.34)]]
行索引:
In [780]: ii=[[i]*len(v) for i,v in enumerate(vectors)]
In [781]: ii=list(chain(*ii))
从元组中提取并展平的列和数据值
In [782]: jj=[j for j,_ in chain(*vectors)]
In [783]: data=[d for _,d in chain(*vectors)]
In [784]: ii
Out[784]: [0, 0, 0, 1, 2, 2]
In [785]: jj
Out[785]: [1, 3, 6, 2, 2, 1]
In [786]: data
Out[786]: [0.12, 0.234, 1.23, 0.222, 0.23, 0.34]
In [787]: A=sparse.csr_matrix((data,(ii,jj))) # coo style input
In [788]: A.A
Out[788]:
array([[ 0. , 0.12 , 0. , 0.234, 0. , 0. , 1.23 ],
[ 0. , 0. , 0.222, 0. , 0. , 0. , 0. ],
[ 0. , 0.34 , 0.23 , 0. , 0. , 0. , 0. ]])
我有几个表示为元组列表的稀疏向量,例如。
[[(22357, 0.6265631775164965),
(31265, 0.3900572375543419),
(44744, 0.4075397480094991),
(47751, 0.5377595092643747)],
[(22354, 0.6265631775164965),
(31261, 0.3900572375543419),
(42344, 0.4075397480094991),
(47751, 0.5377595092643747)],
...
]
我的目标是 scipy.sparse.csr_matrix
由数百万个这样的向量组成。
我想问问是否有一些简单优雅的解决方案来进行这种转换,而不是试图将所有内容都卡在内存中。
编辑: 澄清一下:我的目标是构建二维矩阵,其中我的每个稀疏向量代表矩阵中的一行。
考虑以下几点:
import numpy as np
from scipy.sparse import csr_matrix
vectors = [[(22357, 0.6265631775164965),
(31265, 0.3900572375543419),
(44744, 0.4075397480094991),
(47751, 0.5377595092643747)],
[(22354, 0.6265631775164965),
(31261, 0.3900572375543419),
(42344, 0.4075397480094991),
(47751, 0.5377595092643747)]]
indptr = np.cumsum([0] + map(len, vectors))
indices, data = np.vstack(vectors).T
A = csr_matrix((data, indices.astype(int), indptr))
不幸的是,通过这种方式,列索引从整数转换为双精度并返回。 This works correctly 适用于非常大的矩阵,但并不理想。
将 indices,data
收集到结构化数组中可避免整数-双精度转换问题。它也比 vstack
方法快一点(在有限测试中)(使用这样的列表数据 np.array
比 np.vstack
快。)
indptr = np.cumsum([0]+[len(i) for i in vectors])
aa = np.array(vectors,dtype='i,f').flatten()
A = sparse.csr_matrix((aa['f1'], aa['f0'], indptr))
我用 map
替换了列表理解,因为我使用的是 Python3。
coo
格式的索引 (data, (i,j))
可能更直观
ii = [[i]*len(v) for i,v in enumerate(vectors)])
ii = np.array(ii).flatten()
aa = np.array(vectors,dtype='i,f').flatten()
A2 = sparse.coo_matrix((aa['f1'],(np.array(ii), aa['f0'])))
# A2.tocsr()
这里,第一步的ii
是每个子列表的行号。
[[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3],
...]]
这种构造方法比csr
直接indptr
慢。
对于每行条目数量不同的情况,此方法有效(使用 intertools.chain
来展平列表):
示例列表(暂时没有空行):
In [779]: vectors=[[(1, .12),(3, .234),(6,1.23)],
[(2,.222)],
[(2,.23),(1,.34)]]
行索引:
In [780]: ii=[[i]*len(v) for i,v in enumerate(vectors)]
In [781]: ii=list(chain(*ii))
从元组中提取并展平的列和数据值
In [782]: jj=[j for j,_ in chain(*vectors)]
In [783]: data=[d for _,d in chain(*vectors)]
In [784]: ii
Out[784]: [0, 0, 0, 1, 2, 2]
In [785]: jj
Out[785]: [1, 3, 6, 2, 2, 1]
In [786]: data
Out[786]: [0.12, 0.234, 1.23, 0.222, 0.23, 0.34]
In [787]: A=sparse.csr_matrix((data,(ii,jj))) # coo style input
In [788]: A.A
Out[788]:
array([[ 0. , 0.12 , 0. , 0.234, 0. , 0. , 1.23 ],
[ 0. , 0. , 0.222, 0. , 0. , 0. , 0. ],
[ 0. , 0.34 , 0.23 , 0. , 0. , 0. , 0. ]])