SciPy 详细路线图#
本路线图的大部分旨在就每个 SciPy 子模块在新功能、错误修复等方面最需要什么提供高层视图。除了重要的“照常营业”变更外,它还包含主要新功能的想法——这些功能已特别标记,预计需要投入大量的专门工作。本路线图中未提及的事项不一定不重要或超出范围,但我们(SciPy 开发人员)希望向我们的用户和贡献者清晰地展示 SciPy 的发展方向以及最需要帮助的地方。
注意
这是详细的路线图。一个仅包含最重要想法的非常高层的概述是SciPy 路线图。
通用#
本路线图将与 SciPy 一同发展。更新可以通过拉取请求提交。对于大型或破坏性的更改,您可能希望首先在 scipy-dev 论坛上讨论。
API 变更#
总的来说,我们希望尽可能地发展 API,以消除已知的缺陷,但也要尽可能地保持向后兼容性。
测试覆盖率#
过去几年添加的代码的测试覆盖率相当好,我们致力于为所有新添加的代码实现高覆盖率。然而,仍有大量旧代码的覆盖率很差。将其提升到当前标准可能不现实,但我们应该堵住最大的漏洞。
除了覆盖率,还有一个正确性问题——旧代码可能有一些提供良好语句覆盖率的测试,但这不一定能说明代码是否名副其实。因此,需要对代码的某些部分(特别是stats、signal 和 ndimage)进行代码审查。
文档#
文档状况良好。应继续扩展当前的 docstrings——添加示例、参考文献和更好的解释。大多数模块在参考指南中也有一个很好的入门教程,但有几个教程缺失或不完整——这应该得到修复。
基准测试#
基于 asv 的基准测试系统状况良好。添加新的基准测试相当容易,但运行基准测试却不是很直观。使其更容易是优先事项。
Cython 的使用#
Cython 旧的 NumPy 数组使用语法应该被移除并替换为 Cython memoryviews。
由 Cython 代码构建的扩展模块的二进制文件大小很大,编译时间很长。我们应该尽可能地合并扩展模块(例如,stats._boost 现在包含许多扩展模块),并将 Cython 的使用限制在它是最佳选择的地方。请注意,scipy.special 中正在进行 Cython 到 C++ 的转换。
Pythran 的使用#
Pythran 仍然是一个可选的构建依赖项,可以使用 -Duse-pythran=false 禁用。目标是使其成为硬依赖项——为此,必须明确维护负担足够低。
Fortran 库的使用#
SciPy 的成功很大程度上归功于对成熟 Fortran 库(QUADPACK、FITPACK、ODRPACK、ODEPACK 等)的封装。这些库所用的 Fortran 77 语言难以维护,且 Fortran 的使用存在许多问题;例如,它使我们的 wheel 构建更难维护,反复给支持 macOS arm64 和 Windows on Arm 等新平台带来问题,并对 Pyodide 的 SciPy 支持造成了极大的困扰。我们的目标是通过用其他语言编写的代码替换其功能,从而从 SciPy 中移除所有 Fortran 代码。此目标的进展在 gh-18566 中跟踪。
持续集成#
持续集成目前涵盖 32/64 位 Windows、x86-64/arm 上的 macOS、x86 上的 32/64 位 Linux 和 aarch64 上的 Linux,以及一系列版本的依赖项和构建发布质量的 wheel。最近(2023 年上半年)CI 的可靠性不佳,原因是要支持的配置数量庞大以及一些 CI 作业需要进行大修。我们计划在放弃 distutils 构建系统时,通过移除剩余的基于 distutils 的作业来缩短构建时间,并使 CI 作业中的配置集更加正交。
二进制文件大小#
SciPy 二进制文件相当大(例如,1.7.3 版本的未解压 manylinux wheel 在 PyPI 上为 39 MB,安装后为 122 MB),这可能会带来问题——例如在 AWS Lambda 中使用,它有 250 MB 的大小限制。我们的目标是尽可能保持二进制文件大小最小;在添加新的编译扩展时,需要检查这一点。multibuild 中调试符号的剥离或许可以改进(参见此问题)。应努力在可能的情况下进行精简,并且不添加新的大文件。将来,正在考虑(非常初步地)且可能有所帮助的是分离捆绑的 libopenblas 并移除对 long double 的支持。
模块#
cluster#
dendrogram 需要重写,它有许多难以修复的开放问题和功能请求。
constants#
此模块仅需定期更新数值。
differentiate#
添加此模块时,其范围将被限定。目标是提供黑盒函数的基本微分,而不是复制现有微分工具的所有功能。考虑到这一点,未来的工作包括:
改进对接受额外参数的调用体的支持(例如,向
jacobian和hessian添加*args)。请注意,由于当数组元素对应的计算收敛时,这些元素会被消除,因此这不是微不足道的。改进
scipy.differentiate.hessian的实现:不使用一阶微分的链式调用,而是使用二阶微分模板。考虑添加一个使用相对步长的选项。
考虑推广这种方法以使用“多项式外推”;即,不从最少数量的函数评估中估计给定阶数的导数,而是使用最小二乘法来提高对数值噪声的鲁棒性。
fft#
此模块状况良好。
integrate#
完成新的
cubature函数的功能集,并添加专为一维积分设计的接口。从 special 迁移用于生成求积规则点和权重的函数,提高其可靠性,并添加对其他重要规则的支持。
完成
solve_ivp的功能集,包括odeint接口的所有功能。优雅地淘汰被取代的函数和类。
interpolate#
FITPACK 替换
我们需要完成提供 FITPACK Fortran 库的功能等价物。目标是以模块化的方式重新实现 FITPACK 巨石的算法内容,以允许更好的用户控制和可扩展性。为此,我们需要
一维样条:将周期样条拟合添加到 make_splrep 函数中。
二维样条:为散点和网格数据提供 BivariateSpline 类家族的功能替换。
一旦我们拥有了功能完整的替换集,我们就可以优雅地淘汰对 FITPACK 的使用。
新功能的想法
在 make_smoothing_spline 中添加构造具有可变节点数的平滑样条的能力。目前,make_smoothing_spline 总是使用所有数据点作为节点向量。
尝试用户可选择的平滑标准:添加 P 样条惩罚形式,以补充 make_smoothing_spline 的二阶导数惩罚和 make_splrep 的三阶导数跳跃。
研究独立变量批次样条构造的矢量化方法。这种类型的功能已由
scipy.stats开发人员请求。允许为样条拟合指定边界条件。
研究 FITPACK 库在 Fortran 中提供但从未暴露给 Python 接口的受约束样条拟合问题。
如果用户有足够兴趣,可以添加 NURBS 支持。
可扩展性和性能
我们需要检查大型数据集上的性能,并在不足之处进行改进。这对于常规网格 N 维插值器和基于 QHull 的散点 N 维插值器都很重要。对于后者,我们还需要研究是否可以改进 QHull 库的 32 位整数限制。
io#
wavfile
将支持 PCM 浮点数,其他任何格式请使用
audiolab或其他专业库。如果数据无法理解,则抛出错误而不是警告。
其他子模块(matlab、netcdf、idl、harwell-boeing、arff、matrix market)状况良好。
linalg#
scipy.linalg 状况良好。
所需
减少与
numpy.linalg的函数重复,使 API 保持一致。get_lapack_funcs应该始终使用flapack封装更多 LAPACK 函数
LU 分解函数太多,移除一个
新功能的想法
在 Cython BLAS 和 LAPACK 中添加类型通用包装器
将许多线性代数例程转换为 gufuncs
完成对批量操作的支持(参见 gh-21466)
BLAS 和 LAPACK
scipy.linalg 中到 BLAS 和 LAPACK 的 Python 和 Cython 接口是 SciPy 提供的最重要的功能之一。总的来说,scipy.linalg 状况良好,但我们可以进行一些改进。
misc#
所有功能已从 scipy.misc 中移除,该命名空间本身最终也将被移除。
ndimage#
底层的 ndimage 是一个强大的插值引擎。用户通常预期以下两种模型之一:一种是像素模型,其中 (1, 1) 元素中心位于 (0.5, 0.5);另一种是数据点模型,其中值定义在网格上的点。随着时间的推移,我们越来越确信数据点模型定义更清晰,实现更容易,但这一点应在文档中明确说明。
更重要的是,SciPy 仍然实现的是这种数据点模型的一种变体,其中轴的两个极端的数据点在周期性包裹模式下共享一个空间位置。例如,在一维数组中,x[0] 和 x[-1] 将共置。然而,一个非常常见的用例是信号是周期的,沿轴的第一个和最后一个元素之间具有相等的间距(而不是零间距)。针对此用例的包裹模式已在 gh-8537 中添加,接下来插值例程应更新以使用这些模式。这将解决包括 gh-1323、gh-1903、gh-2045 和 gh-2640 在内的几个问题。
形态学接口需要标准化
二值膨胀/腐蚀/开运算/闭运算接受“结构”参数,而其灰度等效操作接受大小(必须是元组,而不是标量)、足迹或结构。
标量应该可以接受作为大小,等同于为每个轴提供相同的值。
对于二值膨胀/腐蚀/开运算/闭运算,结构元素是可选的,而对于灰度操作,它是强制的。灰度形态学操作应获得相同的默认值。
其他过滤器也应尽可能采用该默认值。
odr#
此模块状况良好,尽管可能需要更多的维护。此处没有重大计划或愿望。
optimize#
我们致力于持续改进本模块提供的优化器集合。对于大规模问题,最先进的技术不断发展,我们旨在通过利用 HiGHS 和 PRIMA 等领域特定库的实现来跟进。未来工作的其他领域包括:
改进现有优化器的接口(例如
shgo)。改进基准测试系统的可用性,并添加更易于比较结果的功能(例如摘要图)。
signal#
卷积和相关:(相关函数包括 convolve, correlate, fftconvolve, convolve2d, correlate2d 和 sepfir2d。)消除与 ndimage(及其他地方)的重叠。从 numpy, scipy.signal 和 scipy.ndimage(以及我们找到它们的任何其他地方),为 1D、2D 和 nD 卷积和相关选择“一流”的实现,将实现放在某个地方,并在整个 SciPy 中一致使用。
B 样条:(相关函数包括 gauss_spline, cspline1d, qspline1d, cspline2d, qspline2d, cspline1d_eval 和 spline_filter。)将优秀部分移至 interpolate(并进行适当的 API 更改以匹配 interpolate 中的处理方式),并消除任何重复。
滤波器设计:合并 firwin 和 firwin2,以便可以移除 firwin2。
连续时间线性系统:进一步提高 ltisys 的性能(减少不同表示之间内部转换)。填补 lti 系统转换函数的空白。
二阶节:使 SOS 滤波与现有方法具有同等能力。这包括 ltisys 对象、等效的 lfiltic,以及与其他滤波器表示之间数值稳定的转换。SOS 滤波器可被视为 ltisys 对象的默认滤波方法,因为它们具有数值稳定性。
sparse#
稀疏矩阵格式的功能大部分已经完善,但主要问题是它们行为类似于 numpy.matrix(该功能在 NumPy 中最终会被废弃)。
我们想要的是行为类似于 numpy.ndarray 的稀疏数组。SciPy 1.8.0 中添加了新类集(csr_array 等)的初步支持,并在 1.12.0 中通过数组构造函数、1.14.0 中的 1D 数组支持和 1.15.0 中的 1D 索引得到了稳定。稀疏数组代码库现在支持所有稀疏矩阵功能,此外还支持 1D 数组以及 nD 数组的第一步。有一个转换指南可以帮助用户和库将其代码转换为稀疏数组。
稀疏数组转换的下一步
- 将稀疏数组 API 扩展到 nD 数组。
支持 COO、CSR 和 DOK 格式。
1.15 版本中存在一些 COO 功能。
在稀疏格式可以有效实现广播的操作中引入对广播的支持。
帮助其他库从稀疏矩阵转换为稀疏数组。NetworkX、dipy、scikit-image、pyamg、cvxpy 和 scikit-learn 正在进行或已完成转换为稀疏数组。
为稀疏矩阵添加弃用警告。
与 NumPy 合作,废弃/移除
numpy.matrix。弃用并随后移除稀疏矩阵,转而使用稀疏数组。
- 开始构造函数名称的 API 变更(
diags、block等) 注:总的来说,构造函数将经历两次名称变更。第一次是从矩阵创建移动到新的数组创建函数(即
eye->eye_array)。然后第二次是稀疏矩阵移除后,将名称更改为与array_api名称匹配(即eye_array到eye)。我们将长期保留*_array版本作为(可能隐藏的)别名。
- 开始构造函数名称的 API 变更(
添加与
array_api名称匹配的构造函数名称。废弃过渡构造函数名称。
在 pydata/sparse 中正在制定一个替代(更雄心勃勃,但尚不清楚是否会实现)计划。为了支持这项工作,我们的目标是在所有接受稀疏数组的函数中支持 PyData Sparse。scipy.sparse.linalg 和 scipy.sparse.csgraph 对 pydata/sparse 的支持已基本完成。
关于不同的稀疏矩阵格式:它们有很多。这些应该保留,但改进/优化应该投入到 CSR/CSC 中,它们是首选格式。LIL 可能是一个例外,它本身效率低下。如果 DOK 扩展到支持 LIL 当前提供的所有操作,则可以放弃它。
sparse.csgraph#
此模块状况良好。
sparse.linalg#
_arpack 和 lobpcg 有大量的开放问题。
_isolve:
callback 关键词不一致
tol 关键词已损坏,应该是相对容差
Fortran 代码不可重入(但我们不解决,或许可以从 PyKrilov 重用)
_dsolve:
添加兼容许可的稀疏 Cholesky 或不完全 Cholesky
添加兼容许可的稀疏 QR
改进与 SuiteSparse UMFPACK 的接口
添加与 SuiteSparse CHOLMOD 和 SPQR 的接口
spatial#
QHull 封装器状况良好,KDTree 亦是如此。
spatial.distance 指标的 C++ 重写正在进行中——这应该会提高性能,使行为(例如,对于各种非 float64 输入 dtype)更加一致,并修复一些关于某些指标实现的数学定义的剩余问题。
special#
尽管仍有许多函数在精度上需要改进,但可能唯一的拦路虎是超几何函数、抛物线柱函数和扁球波函数。有三种可能的处理方法:
获取良好的双精度实现。这对于抛物线柱函数是可行的(正在进行中)。我认为对于超几何函数也是可能的,尽管可能无法及时完成。对于扁球波函数,以目前的理论来说这是不可能的。
移植 Boost 的任意精度库并在后台使用它来获得双精度准确性。这可能作为超几何函数的一个权宜之计;之前 @nmayorov 和在 gh-5349 中都曾建议过使用任意精度的想法。对于扁球波函数可能很有必要,这可以重用:radelman/scattering。
在文档中添加关于现有实现限制的明确警告。
stats#
scipy.stats 子包旨在提供基本统计方法,这些方法可能涵盖在标准统计教材中,例如 Johnson 的《Miller & Freund's Probability and Statistics for Engineers》、Sokal & Rohlf 的《Biometry》或 Zar 的《Biostatistical Analysis》。它不寻求复制下游包(例如 StatsModels、LinearModels、PyMC3)的高级功能;相反,它可以提供一个坚实的基础,供它们在其上构建。(请注意,这些是粗略的指导方针,而非严格的规则。“高级”是一个定义模糊且主观的术语,SciPy 中也可能包含“高级”方法,特别是如果没有其他广泛使用且受支持的包涵盖该主题。另请注意,与下游项目的一些重复是不可避免的,并且不一定是坏事。)
以下改进将帮助 SciPy 更好地履行这一职责。
改进统计检验:包括生成置信区间的方法,并在计算可行的情况下实现精确和随机的 p 值计算——考虑平局的可能性。
扩展新的单变量分布基础设施,增加对离散分布和圆形连续分布的支持。在新基础设施下添加一系列最广泛使用的统计分布,进行严格的准确性测试并记录结果。使用户能够创建利用新基础设施的自定义分布。
改进多变量分布基础设施,以确保一致的 API、彻底的测试和完整的文档。
继续使函数的 API 更加一致,对批量计算、NaN 策略和 dtype 保留提供标准支持。