像 NumPy 一样运算:sparse 稀疏数组算术运算与 ufunc 完整指南

发布时间:2026/8/19 20:37:41
像 NumPy 一样运算:sparse 稀疏数组算术运算与 ufunc 完整指南 像 NumPy 一样运算sparse 稀疏数组算术运算与 ufunc 完整指南【免费下载链接】sparseSparse multi-dimensional arrays for the PyData ecosystem项目地址: https://gitcode.com/gh_mirrors/sp/sparse在数据科学与科学计算领域当数据规模巨大而有效信息却只占极少比例时sparse 稀疏数组就是 PyData 生态中最趁手的工具之一。这个开源项目为 Python 提供了真正的多维稀疏数组而不仅是 SciPy 那样的二维矩阵并做到了与 NumPy 接口的高度一致加法、减法、乘法、除法等算术运算可以直接书写np.add、np.sin、np.sqrt等 ufunc 通用函数也能一键套用。本文面向新手用最少的代码带你掌握 sparse 稀疏数组算术运算、逐元素运算ufunc与广播归约的完整用法。为什么需要 sparse 稀疏数组普通的 NumPy 数组把每一个元素都实实在在存下来哪怕 99% 都是 0。当数据是推荐系统的评分矩阵、知识图谱的邻接矩阵或张量分解中的高维张量时这种方式既浪费内存又拖慢计算。sparse 稀疏数组只存储非零元素及其坐标同时尽可能复刻 NumPy 的写法让你在低内存开销下获得像 NumPy 一样的运算体验。项目核心的格式包括COO、GCXS、DOK等全部运算逻辑的实现可参考源码目录 sparse/numba_backend/官方运算说明见 docs/operations.md。快速上手30 秒创建稀疏数组安装后只需几行代码就能把 NumPy 数组转成稀疏数组或用随机方式生成一个import numpy as np import sparse # 从稠密数组转换 x sparse.COO.from_numpy(np.eye(4)) # 或直接用 asarray 转换 y sparse.asarray(np.arange(12).reshape(3, 4))COO是最常用的格式全称 Coordinate format用坐标列表记录非零元素直观且易于运算。想了解 COO 的底层实现可以看看 sparse/numba_backend/_coo/core.py。支持哪些算术运算符一表看懂sparse 稀疏数组支持几乎所有 Python 标准算术运算符与 NumPy 惯例包括运算符含义示例/-加 / 减x y、x - y*//乘 / 除x * y、x / 7.3///%整除 / 取余x // 2、x % 3**幂x ** 2矩阵乘法x y/!相等比较x 5、x ! 0/大小比较x y、x y例如sparse.elemwise(np.add, x, y)与x y等价几乎所有算术运算最终都经由通用的elemwise逐元素机制完成核心实现在 sparse/numba_backend/_umath.py。与标量混合运算的填充值魔法sparse 稀疏数组支持与标量直接运算这是最常用的场景之一x 1 # 每个非零元素 1 5 * x # 每个元素 ×5 x / 7.3 # 除以标量 x 0 # 判断哪些位置为 0这里藏着一个重要的概念fill_value填充值。稀疏数组默认填充值为 0运算时它表示所有未存储位置的取值。当运算会把 0 映射成非零值时例如x 1结果数组的填充值会自动变为 1同理~x的填充值会变成True。这套机制保证了结果依旧是稀疏的不必展开成稠密数组。相关定义见 sparse/numba_backend/_sparse_array.py。ufunc 逐元素运算像 NumPy 一样调用数学函数这是 sparse 最惊艳的特性它实现了 NumPy 的__array_ufunc__协议见 sparse/numba_backend/_sparse_array.py因此绝大多数 ufunc 都能直接作用于稀疏数组np.abs(x) # 绝对值 np.sin(x) # 正弦 np.sqrt(x) # 平方根 np.exp(x) # 指数 np.log(x) # 对数 np.conj(x) # 共轭与标量运算同理np.exp(x)、np.cos(x)、np.log(x)这类把 0 映射为非零值的函数会产生带非零填充值的新稀疏数组而np.abs(x)、np.sqrt(x)等保持 0→0 的函数则维持原填充值。只要结果不稠密几乎所有一元、二元 ufunc 都能直接使用。用 sparse.elemwise 组合任意自定义函数如果内置运算符不够用sparse.elemwise允许你把任意支持广播的函数应用到任意多个参数上参数可以是稀疏数组或 SciPy 稀疏矩阵sparse.elemwise(np.add, x, y) # 等价于 x y sparse.elemwise(np.maximum, x, 0) # 截断负数 sparse.elemwise(lambda a, b: a * b 1, x, y)逐元素运算性能的基准测试可以运行官方示例 examples/elemwise_example.py它同时对比了 Numba 后端与 Finch 后端在multiply、add、greater_equal三种运算上的表现。广播机制不同形状也能直接算与 NumPy 完全一致sparse 稀疏数组的二元运算支持广播Broadcasting。只要两个数组满足维度对齐规则维度缺失或某维度为 1就能直接运算a sparse.random((4, 1), density0.5) # 形状 (4, 1) b sparse.random((5, 4), density0.5) # 形状 (5, 4) c a b # 结果形状 (5, 4)形状(4,)与(5, 1)运算得到(5, 4)但(4, 1)与(5, 1)这类无法对齐的会抛出ValueError与 NumPy 行为一致。归约运算sum、max、min、prod 一网打尽对整张稀疏数组或沿指定轴做归约是统计分析的刚需。sparse 原生支持x.sum() # 全部求和 x.sum(axis1) # 沿第 1 轴求和 np.max(x) # 最大值 np.min(x, axis(0, 2)) x.prod() # 连乘更通用的是reduce方法它可以接收任意二元 ufunc 作为归约函数x.reduce(np.add, axis1) # 自定义归约求和 x.reduce(np.maximum) # 归约取最大归约逻辑的完整实现见 sparse/numba_backend/_sparse_array.py。需要注意的是若归约会把填充值变成非零值导致结果稠密sparse 会主动抛出ValueError提醒你。与 SciPy 稀疏矩阵的协同运算sparse 还支持与scipy.sparse的稀疏矩阵直接运算例如x y、x - y、x * y、x y都允许y是 SciPy 稀疏矩阵。不过官方建议为了保证结果正确最好先把 SciPy 矩阵显式转换为sparse.COO或sparse.GCXS再参与运算。新手避坑3 个常见注意事项避免意外稠密化当运算会得到稠密结果时例如与普通 NumPy 数组直接相加sparse 会抛出ValueError而不是偷偷展开。确需稠密结果时请显式调用x.todense()。有些运算要求零填充值例如nonzero等操作要求填充值为 0concatenate要求所有输入填充值一致使用前建议查阅 API 文档。注意 ufunc 的 reduce 精度库按坐标分组做归约若归约结果会因反复叠加多个 0 而改变结果可能不精确大多数场景下没有影响。结语让稀疏计算变得简单sparse 稀疏数组库把 NumPy 的算术运算、ufunc 通用函数、广播与归约体验完整带入了稀疏世界。对于推荐系统、图计算、张量分解等典型稀疏场景你几乎不需要改变原有 NumPy 的书写习惯只需把数据类型换成COO或GCXS就能获得显著的内存与性能收益。如果你想亲自上手克隆仓库后运行examples/elemwise_example.py即可看到稀疏与稠密运算的直观对比官方文档 docs/operations.md 也列出了所有支持与暂不支持的运算清单值得收藏。【免费下载链接】sparseSparse multi-dimensional arrays for the PyData ecosystem项目地址: https://gitcode.com/gh_mirrors/sp/sparse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考