SciPy 详细路线图#
此路线图的大部分旨在提供一个高层次的视图,说明 SciPy 各个子模块在新功能、错误修复等方面最需要什么。除了重要的“常规业务”变更外,它还包含主要新功能的想法——这些被明确标记出来,预计需要投入大量专门的精力。路线图中未提及的内容并非不重要或超出范围,但我们(SciPy 开发者)希望向我们的用户和贡献者清晰地展示 SciPy 的发展方向以及最需要帮助的领域。
注意
这是详细路线图。仅包含最重要想法的概览请参见SciPy 路线图。
一般#
此路线图将与 SciPy 一同演进。更新可以以拉取请求的形式提交。对于大型或破坏性变更,您可能希望首先在 scipy-dev 论坛上进行讨论。
API 变更#
总的来说,我们希望尽可能地改进 API 以消除已知的不足,但要尽可能不破坏向后兼容性。
测试覆盖率#
过去几年中添加的代码的测试覆盖率相当好,我们旨在为所有新添加的代码实现高覆盖率。然而,仍有大量旧代码的覆盖率很差。将其提升到当前标准可能不现实,但我们应该填补最大的漏洞。
除了覆盖率之外,还有正确性问题——较旧的代码可能有一些测试提供了良好的语句覆盖率,但这并不一定能说明代码是否符合其宣称的功能。因此,对部分代码(特别是stats
、signal
和ndimage
)进行代码审查是必要的。
文档#
文档状况良好。应继续扩展当前的文档字符串——添加示例、引用和更好的解释。大多数模块在参考指南中也有一个很好的入门教程,但有一些缺失或不完整的教程——这应该得到修复。
基准测试#
基于asv
的基准测试系统状况良好。添加新基准测试相当容易,但运行基准测试并不十分直观。使其更易用是一个优先事项。
Cython 的使用#
Cython 使用 NumPy 数组的旧语法应该移除,并替换为 Cython 内存视图。
从 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#
添加此模块时,其范围将被限制。目标是提供黑盒函数的基本微分,而不是复制现有微分工具的所有功能。考虑到这一点,未来的工作包括
改进对接受额外参数的可调用对象的支持(例如,向
*args
和jacobian
添加hessian
)。请注意,由于数组元素在相应计算收敛时被消除的方式,这并非微不足道。改进
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
(以及我们找到它们的任何其他地方),为 1-D、2-D 和 n-d 卷积和相关选择“同类最佳”,将实现放在某个地方,并在整个 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
中支持一维数组,在1.15.0
中支持一维索引。稀疏数组代码库现在支持所有稀疏矩阵功能,并额外支持一维数组和向 N 维数组迈出的第一步。有一个转换指南可以帮助用户和库将其代码转换为稀疏数组。
稀疏数组转换的下一步
- 将稀疏数组 API 扩展到 N 维数组。
支持 COO、CSR 和 DOK 格式。
一些 COO 功能已存在于 1.15 版本中。
在稀疏格式可以有效实现广播操作的地方引入对广播的支持。
帮助其他库从稀疏矩阵转换为稀疏数组。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 中所有接受稀疏数组的函数。pydata/sparse
在scipy.sparse.linalg
和scipy.sparse.csgraph
中的支持大部分已完成。
关于不同的稀疏矩阵格式:它们有很多。这些格式应该保留,但改进/优化应集中在 CSR/CSC,它们是首选格式。LIL 可能是一个例外,它本质上效率低下。如果 DOK 扩展到支持 LIL 当前提供的所有操作,它可以被放弃。
sparse.csgraph#
此模块状况良好。
sparse.linalg#
_arpack
和lobpcg
有大量开放问题。
_isolve
:
回调关键字不一致。
tol 关键字有缺陷,应为相对容差。
Fortran 代码不可重入(但我们不解决,也许可以从 PyKrilov 重用)。
_dsolve
:
添加许可兼容的稀疏 Cholesky 或不完全 Cholesky。
添加许可兼容的稀疏 QR。
改进与 SuiteSparse UMFPACK 的接口。
添加与 SuiteSparse CHOLMOD 和 SPQR 的接口。
spatial#
QHull 封装器状况良好,KDTree
也一样。
spatial.distance
指标的 C++ 重写正在进行中——这应该会提高性能,使行为(例如,对于各种非 float64 输入 dtypes)更加一致,并修复一些剩余的关于某些指标数学定义的缺陷。
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 保留提供标准支持。