稀疏矩阵应选用CSR或CSC格式而非COO,批量构建避免逐个赋值,警惕隐式零与显式零混淆,合理指定dtype并用npz压缩存储以节省内存和提升性能。
直接用普通二维数组存大量零值矩阵,等于拿金库装几颗螺丝钉——空间浪费严重,计算也拖慢。稀疏矩阵压缩的核心,就是只记“谁不为零、在哪、值多少”,跳过所有零。
选对存储格式,别让格式拖垮性能
不是所有稀疏格式都适合大规模计算:
- COO(坐标格式)适合初始化:用三个数组分别存行号、列号、值,构造直观,但不支持高效运算,也不支持原地修改;
- CSR(按行压缩)更适合大多数场景:行访问快、矩阵乘法和迭代求解器(如共轭梯度法)天然适配;
- CSC(按列压缩)更适配列操作:比如特征提取、sklearn 的 fit/transform 流程,或需要频繁取某一列的场景。
SciPy 中推荐直接用 sparse.csr_matrix() 或 sparse.csc_matrix() 构造,它们内部已做结构优化,索引和算术操作都是向量化实现。
批量构建,拒绝逐个赋值
写 mat[i, j] = x 看似自然,实则每次都会触发结构检查、内存重分配。100 万次赋值可能卡死或爆内存。
- 先用 Python 列表收集所有非零项:
rows, cols, data = [], [], [],循环中追加(i, j, val); - 一次性构造:
sparse.coo_matrix((data, (rows, cols)), shape=(M, N)); - 若需进一步提速,可预分配 CSR 的
indptr数组(尤其当每行非零元数量已知时); - 从文件加载时,优先用
sparse.load_npz()读取已压缩的.npz文件,比现场解析快 5–10 倍。
警惕隐式零与显式零混淆
稀疏矩阵里“没存”不等于“不存在”。mat[0, 0] 返回 0 是逻辑结果,不是内存里真有个 0。
- 调用
mat.toarray()或np.array(mat)会强制转成稠密数组——10⁶×10⁶ 矩阵瞬间 OOM; -
mat == 0会返回稠密布尔矩阵,应改用mat.count_nonzero()或mat.sum()替代; - 用
np.where(mat)提取非零位置前,确保mat已是 CSR/CSC 格式,否则 COO 下效率极低; - 长期运行后调用
mat.eliminate_zeros()清理浮点误差引入的“近零值”和重复索引。
配合 dtype 和压缩策略再减负
默认 float64 占 8 字节,但多数场景 float32 或 int32 完全够用:
- 创建时显式指定
dtype=np.float32,内存直降 50%,科学计算精度通常无损; - 计数类矩阵(如 TF-IDF、共现表)用
dtype=np.int32更省; - 保存时用
sparse.save_npz("mat.npz", mat),比 pickle 小 3–5 倍,且跨平台可读。











