我需要计算一个巨大的相关矩阵,比如 200000x200000 ,它太大而无法存储在内存中。幸运的是,大多数值都是0,除了接近矩阵对角线的值,我需要计算。因此,我很好奇scipy / numpy中的稀疏矩阵是否可以帮助我加快速度。
我构建数据的当前方式如下:
#Input variables are snps, and max_dist
num_snps, num_indivs = snps.shape
corr_table = {}
for i in range(num_snps):
corr_table[i] = {}
for i in range(0, num_snps - 1):
start_i = i + 1
end_i = min(start_i + max_dist, num_snps)
corr_vec = sp.dot(snps[i], sp.transpose(snps[start_i:end_i])) / float(num_indivs)
corr_vec = sp.array(corr_vec).flatten()
for k in range(start_i, end_i):
corr_vec_i = k - start_i
corr_table[i][k] = corr_vec[corr_vec_i]
corr_table[k][i] = corr_vec[corr_vec_i]
return corr_table
此处 snps 是 MxN 矩阵,带有标准化的行向量(均值0和方差1),我想为此计算 MxM 相关矩阵。目前,相关矩阵存储为一个巨大的字典( corr_table )。 max_dist 表示我计算相关性的一对SNP( snps 矩阵中的行)之间的最大距离。对于所有其他相关性(不在 corr_table 中),我认为它们是0。
不幸的是,这在实践中仍然不是很有效,因此,我想知道我是否可以将矩阵乘法与稀疏矩阵一起使用来更有效地计算相关矩阵,而无需使用更多的内存。
任何建议都将不胜感激。
答案 0 :(得分:1)
我还没有尝试理解或运行你的计算,但我可以添加一些关于稀疏矩阵的指针。
包中有六个不同的稀疏formats
,每个都有不同的优点和缺点。并且很容易将一种格式转换为另一种格式;稀疏函数经常这样做。没有一个非常适合增量更新。
dok
格式实际上是一个字典子类。键是坐标元组,例如corr_table[(i,k)] = corr_vec[corr_vec_i]
。我在其他SO问题中发现使用这些密钥构建普通字典会更快,然后update
dok
。 corr_matrix[i,k]=...
索引中有更多的开销。
lol
对于增量更改也相对较好。它将值存储在2个列表列表中,每行矩阵一个子列表。
csr
适用于矩阵计算,但索引分配速度较慢。它最好使用coo
输入样式构建,它使用3个1d数组data
,i
,j
。传统上稀疏矩阵是通过构造这3个数组构建的,如果以增量方式执行,可能作为列表,然后将它们传递给coo_matrix
。
也有块和对角线格式,对于某些稀疏布局可能更好。
我怀疑这一步:
for k in range(start_i, end_i):
corr_vec_i = k - start_i
corr_table[i][k] = corr_vec[corr_vec_i]
corr_table[k][i] = corr_vec[corr_vec_i]
可以执行numpy
向量操作,类似
jj = np.arange(start_i, end_i)
ii = jj - start_i
data_list.append(corr_vec[ii])
row_list.append(ii)
col_list.append(jj)
data_list.append(corr_vec[ii])
row_list.append(jj)
col_list.append(ii)
其中data_list
等是我收集coo
输入的列表。它们可能必须通过np.concatenate
才能生成sparse.coo_matrix
可以使用的1d数组。
我还没有对这段代码进行测试,因此存在错误,但希望它能为您提供一些想法。