如何计算1×10¹³和10¹³×1的Scipy稀疏矩阵点积且避免内存溢出
问题根因
你遇到的内存报错是Scipy稀疏矩阵格式转换的固有逻辑导致的:当两个稀疏矩阵做乘法时,Scipy会自动将第二个矩阵转换为和第一个矩阵一致的压缩格式(如CSR/CSC),而压缩格式的indptr数组长度等于对应维度大小+1。你的矩阵维度高达1e13,int64类型的indptr数组总大小为1e13 * 8B = 72.8TiB,远远超出普通设备的内存上限,直接触发内存分配失败。
可行解决方案
1×N的行稀疏向量和N×1的列稀疏向量的点积,本质上只需要计算非零索引重合位置的数值乘积之和,完全不需要构造完整数组或做稀疏格式转换,直接手动计算即可:
步骤1:提取非零索引和对应数值
你不需要使用CSR/CSC格式存储这类超大规模一维稀疏向量,优先使用COO格式,或者直接维护两个数组:非零位置索引、对应数值。如果已经是Scipy稀疏矩阵,可以直接提取对应字段:
import numpy as np # 假设imputed是1×N的稀疏矩阵,s是N×1的稀疏矩阵 # 提取行向量的非零列索引和对应值 idx_row = imputed.tocoo().col val_row = imputed.tocoo().data # 提取列向量的非零行索引和对应值 idx_col = s.tocoo().row val_col = s.tocoo().data
步骤2:计算点积
找两个索引数组的重合位置,对应数值相乘求和即可:
# 找公共索引,同时返回公共索引在两个原数组中的位置 common_idx, pos_row, pos_col = np.intersect1d(idx_row, idx_col, return_indices=True) # 计算最终点积结果 dot_result = np.sum(val_row[pos_row] * val_col[pos_col])
优化提示
如果两个向量的非零元素总数不超过10万,还可以用字典映射加速计算:
val_map = dict(zip(idx_col, val_col)) dot_result = sum(v * val_map[i] for i, v in zip(idx_row, val_row) if i in val_map)
内容的提问来源于stack exchange,提问作者titorat
相关产品推荐
相关产品推荐

