拼接大型稀疏矩阵触发内存错误,求更优解决方案
解决大型稀疏矩阵垂直拼接的内存问题
最优方案:直接操作CSR矩阵的内部结构
对于Scipy的CSR格式稀疏矩阵,垂直拼接不需要调用sparse.vstack——直接拼接其核心的三个数组即可,完全避免临时大矩阵的内存开销:
- 确保两个矩阵都转为CSR格式(CSR天生适合行方向操作)
- 直接拼接
data和indices数组 - 调整
indptr数组:将第二个矩阵的indptr(去掉第一个0元素)每个值加上第一个矩阵的非零元素总数,再拼接到第一个矩阵的indptr后
代码示例:
import scipy.sparse as sparse import numpy as np # 统一转为CSR格式 train_data_pt_a = train_data_pt_a.tocsr() train_data_pt_b = train_data_pt_b.tocsr() # 拼接核心数组 new_data = np.concatenate([train_data_pt_a.data, train_data_pt_b.data]) new_indices = np.concatenate([train_data_pt_a.indices, train_data_pt_b.indices]) # 处理indptr:b的indptr偏移a的非零数,去掉开头的0 new_indptr = np.concatenate([train_data_pt_a.indptr, train_data_pt_b.indptr[1:] + train_data_pt_a.nnz]) # 生成最终拼接后的CSR矩阵 all_data = sparse.csr_matrix((new_data, new_indices, new_indptr), shape=(train_data_pt_a.shape[0] + train_data_pt_b.shape[0], train_data_pt_a.shape[1]))
备选方案:分块迭代拼接
如果因为矩阵格式限制无法用上面的方法,可以分块处理train_data_pt_b,每次拼接一小块后及时释放内存:
import scipy.sparse as sparse import gc train_data_pt_a = train_data_pt_a.tocsr() chunk_size = 50000 # 根据你的内存容量调整块大小 all_data = train_data_pt_a.copy() for start_idx in range(0, train_data_pt_b.shape[0], chunk_size): end_idx = min(start_idx + chunk_size, train_data_pt_b.shape[0]) chunk = train_data_pt_b[start_idx:end_idx].tocsr() all_data = sparse.vstack([all_data, chunk]) # 清理临时变量,触发垃圾回收 del chunk gc.collect()
注意事项
- 优先使用CSR格式进行行拼接,CSC格式更适合列拼接(
hstack),用错格式会大幅增加内存开销 - 避免在Jupyter Notebook中保留过多中间变量,及时清理无用的矩阵对象
内容的提问来源于stack exchange,提问作者RUser4512
相关产品推荐
相关产品推荐

