详细的 SciPy 路线图#

此路线图的大部分内容旨在提供关于每个 SciPy 子模块最需要的新功能、错误修复等的高级视图。除了重要的“日常”更改外,它还包含主要新功能的想法 - 这些功能被标记为如此,并且预计需要大量的专门投入。此路线图中未提及的内容不一定是不重要或超出范围的,但是我们(SciPy 开发人员)希望向我们的用户和贡献者清楚地展示 SciPy 的发展方向以及最需要帮助的地方。

注意

这是详细的路线图。仅包含最重要想法的非常高级的概述请参见 SciPy 路线图

概述#

此路线图将随着 SciPy 的发展而不断发展。更新可以作为拉取请求提交。对于大型或破坏性的更改,您可能希望先在 scipy-dev 论坛上讨论这些更改。

API 更改#

总的来说,我们希望尽可能地改进 API 以消除已知的缺陷,但在尽可能不破坏向后兼容性的情况下

测试覆盖率#

最近几年添加的代码的测试覆盖率相当不错,我们的目标是对所有添加的新代码进行高覆盖率测试。但是,仍然有大量的旧代码的覆盖率很差。将其提升到当前标准可能不现实,但我们应该堵住最大的漏洞。

除了覆盖率之外,还有正确性的问题 - 较旧的代码可能有一些测试提供了不错的语句覆盖率,但这并不一定能说明代码是否按预期运行。因此,有必要对代码的某些部分(尤其是 statssignalndimage)进行代码审查。

文档#

文档状况良好。应继续扩展当前文档字符串 - 添加示例、引用和更好的解释。大多数模块在参考指南中也有一个很好的入门教程,但是有一些教程缺失或不完整 - 应该修复。

基准测试#

基于 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 等)的包装。其中一些库的维护情况良好,而另一些则不然。我们应该根据维护工作量、功能和(可能部分的)替代方案的存在来审核我们对这些库的使用,包括 SciPy 内部的替代方案

持续集成#

持续集成目前涵盖 32/64 位 Windows、x86-64/arm 上的 macOS、x86 上的 32/64 位 Linux 和 aarch64 上的 Linux - 以及一系列依赖项的版本和构建发布质量的 wheels。由于要支持大量的配置,以及某些 CI 作业需要进行大修,CI 的可靠性最近(2023 年上半年)不太好。我们的目标是通过在放弃该构建系统时删除剩余的基于 distutils 的作业,并使 CI 作业中的配置集更加正交来减少构建时间。

二进制文件的大小#

SciPy 二进制文件很大(例如,PyPI 上的 1.7.3 未解压的 manylinux wheel 为 39 MB,安装后为 122 MB),这可能会有问题 - 例如在 AWS Lambda 中使用,其大小限制为 250 MB。我们的目标是尽可能减小二进制文件的大小;在添加新的编译扩展时,需要检查这一点。multibuild 中调试符号的剥离可能可以改进(请参阅此问题)。应尽可能努力减少文件大小,并且不添加新的大型文件。将来,正在(非常初步地)考虑并可能有所帮助的事情是将捆绑的 libopenblas 分离出来,并删除对 long double 的支持。

模块#

cluster#

dendrogram 需要重写,它有许多难以修复的未解决问题和功能请求。

constants#

此模块基本完成,维护量低且没有未解决的问题。

fft#

此模块状况良好。

integrate#

ODE 求解器所需

  • 文档很糟糕,需要修复

  • 在 SciPy 1.0.0 中添加了一个新的 ODE 求解器接口 (solve_ivp)。将来我们可以考虑(软)弃用旧的 API。

数值积分函数状况良好。可以添加对积分复值函数和积分多个区间的支持(请参阅gh-3325)。

interpolate#

样条拟合:我们需要具有更好用户控制的样条拟合例程。这包括

  • 平滑标准的用户可选替代方案(手动、交叉验证等);gh-16653 在这个方向上迈出了第一步;

  • 多种结点放置策略,包括手动和自动(使用 Dierckx、de Boor 的算法,可能还有其他算法)。

一旦我们拥有相当完善的功能集,我们就可以开始长期研究历史悠久的 FITPACK Fortran 库的未来,该库目前是在 SciPy 中构造平滑样条的唯一方法。

可伸缩性和性能:对于基于 FITPACK 的功能,数据大小受到 32 位 Fortran 整数大小的限制(对于非 ILP64 构建)。对于 N 维分散插值器(基于 QHull)和 N 维规则网格插值器,我们需要检查大型数据集的性能并在缺乏时进行改进(gh-16483 在此方向上取得了进展)。

新功能的想法:可以添加 NURBS 支持。

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 中添加类型通用包装器

  • 将许多线性代数例程转换为 gufunc

BLAS 和 LAPACK

scipy.linalg 中 BLAS 和 LAPACK 的 Python 和 Cython 接口是 SciPy 提供的最重要的东西之一。一般来说,scipy.linalg 状况良好,但是我们可以进行一些改进

  1. 库支持。我们发布的 wheels 现在随 OpenBLAS 一起发布,这目前是唯一可行的性能选项(ATLAS 太慢,由于许可问题,MKL 不能作为默认选项,由于 Apple 不再更新 Accelerate,因此已放弃 Accelerate 支持)。但是,OpenBLAS 不是很稳定,有时它的发布会破坏某些东西,并且在线程方面存在问题(目前是使用 PyPy3 的 SciPy 的唯一问题)。我们至少需要更好地支持调试 OpenBLAS 问题,以及更好地说明如何使用它构建 SciPy。一种选择是使用 BLIS 作为 BLAS 接口(请参阅 numpy gh-7372)。

  2. 支持较新的 LAPACK 功能。在 SciPy 1.2.0 中,我们将 LAPACK 的最低支持版本提高到 3.4.0。现在我们放弃了 Python 2.7,我们可以进一步提高该版本(MKL + Python 2.7 以前是 >3.4.0 的障碍),并开始添加对 LAPACK 中新功能的支持。

misc#

scipy.misc 将会被移除作为一个公开模块。其中大多数函数已移动到其他子模块或被弃用。剩下的一些函数:

  • derivative, central_diff_weight : 移除,可能会用更广泛的数值微分功能来替代。

  • ascent, face, electrocardiogram : 移除或移动到适当的子包(例如 scipy.ndimage, scipy.signal)。

ndimage#

底层的 ndimage 是一个强大的插值引擎。用户通常期望以下两种模型之一:像素模型,其中 (1, 1) 元素具有中心 (0.5, 0.5);或者数据点模型,其中值在网格上的点定义。随着时间的推移,我们确信数据点模型定义更好,也更容易实现,但应该在文档中清楚地说明这一点。

更重要的是,SciPy 实现了此数据点模型的一个*变体*,其中轴的任何两个极端的数据点在*周期性包裹*模式下共享空间位置。例如,在 1D 数组中,x[0]x[-1] 将位于同一位置。然而,一个非常常见的用例是信号是周期性的,沿着轴的第一个和最后一个元素之间具有相等的间距(而不是零间距)。此用例的包裹模式已在 gh-8537 中添加,接下来应更新插值例程以使用这些模式。这应解决多个问题,包括 gh-1323、gh-1903、gh-2045 和 gh-2640。

形态学接口需要标准化

  • 二进制膨胀/腐蚀/开运算/闭运算采用“结构”参数,而它们的灰度等效项则采用大小(必须是元组,而不是标量)、足迹或结构。

  • 标量应该可以接受作为大小,相当于为每个轴提供相同的值。

  • 对于二进制膨胀/腐蚀/开运算/闭运算,结构元素是可选的,而对于灰度运算则是强制性的。灰度形态学运算应获得相同的默认值。

  • 其他过滤器也应在可能的情况下采用该默认值。

odr#

此模块状态良好,尽管它可以使用更多的维护。这里没有重大的计划或期望。

optimize#

总的来说,这个模块状态良好。1.2.0 版本中添加了两个很好的全局优化器;大规模优化器仍然是一个可以填补的空白。其他需要的:

  • linprog 中许多关于附加功能的想法(例如整数约束),请参阅 gh-9269

  • 向基准测试套件添加功能,以便更容易地比较结果(例如,使用汇总图)。

  • 在文档中弃用 fmin_* 函数,首选 minimize

  • scipy.optimize 具有用于全局优化器准确性和速度的广泛基准。这使得可以添加新的优化器(shgodual_annealing),其性能明显优于现有的优化器。然而,optimize 基准测试系统本身速度慢且难以使用;我们需要使其更快,并且可以通过绘制性能曲线来更轻松地比较优化器的性能。

signal#

卷积和相关:(相关函数为 convolve、correlate、fftconvolve、convolve2d、correlate2d 和 sepfir2d。)消除与 ndimage(和其他地方)的重叠。从 numpyscipy.signalscipy.ndimage(以及我们发现它们的任何其他地方)中,为 1-D、2-D 和 n-d 卷积和相关选择“最佳”类,将实现放在某个地方,并在整个 SciPy 中一致地使用它。

B 样条:(相关函数为 gauss_spline、cspline1d、qspline1d、cspline2d、qspline2d、cspline1d_eval 和 spline_filter。)将好的东西移到 interpolate(进行适当的 API 更改以匹配 interpolate 中的操作方式),并消除任何重复。

滤波器设计:合并 firwinfirwin2,以便可以移除 firwin2

连续时间线性系统:进一步提高 ltisys 的性能(减少不同表示形式之间的内部转换)。填补 lti 系统转换函数中的空白。

二阶部分:使 SOS 滤波与现有方法一样强大。这包括 ltisys 对象、一个等效于 lfiltic 的对象,以及与其他滤波器表示形式进行数值稳定的转换。考虑到数值稳定性,SOS 滤波器可以被视为 ltisys 对象的默认滤波方法。

sparse#

稀疏矩阵格式主要功能完整,但主要问题是它们的行为类似于 numpy.matrix(它将在 NumPy 中的某个时候被弃用)。

我们想要的是行为类似于 numpy.ndarray 的稀疏数组。SciPy 1.8.0 中添加了对一组新类(csr_array 等)的初始支持,并在添加数组构造函数时在 1.12.0 中稳定下来。预计在 1.13.0 中支持 1-D 数组。

支持稀疏数组的后续步骤

  • 将稀疏数组 API 扩展到 1-D 数组。
    • 支持 COO、CSR 和 DOK 格式。

    • CSR 1D 支持最小值-最大值、索引、算术。

  • 帮助其他库从稀疏矩阵转换为稀疏数组。创建转换指南和有用的脚本,以标记需要进一步检查的代码。NetworkX、scikit-learn 和 scikit-image 正在进行或已完成向稀疏数组的转换。

  • 在稀疏数组代码成熟后(约 1 个发布周期?),为稀疏矩阵添加弃用警告。

  • 与 NumPy 合作弃用/删除 numpy.matrix

  • 弃用然后删除稀疏矩阵,转而使用稀疏数组。

  • 开始构造函数名称的 API 转换(diagsblock 等)。
    • 注意:作为一个整体,构造函数会经历两次名称转换。一次是从矩阵创建转移到新的数组创建函数(即 eye -> eye_array)。然后在删除稀疏矩阵后,第二次转换名称以匹配 array_api 名称(即 eye_arrayeye)。我们将长期保留 *_array 版本作为(可能是隐藏的)别名。

  • 添加与 array_api 名称匹配的构造函数名称。

  • 弃用转换构造函数名称。

pydata/sparse 中正在研究一种替代方案(更雄心勃勃,且不清楚是否会实现)。为了支持这项工作,我们的目标是在所有接受稀疏数组的函数中支持 PyData Sparse。scipy.sparse.linalgscipy.sparse.csgraph 中对 pydata/sparse 的支持已基本完成。

关于不同的稀疏矩阵格式:有很多种。应保留这些格式,但改进/优化应进入 CSR/CSC,这是首选格式。LIL 可能是例外,它本质上效率低下。如果 DOK 扩展到支持 LIL 当前提供的所有操作,则可以删除它。

sparse.csgraph#

此模块状况良好。

sparse.linalg#

对于 _arpacklobpcg,存在大量未解决的问题。_propack 是 1.8.0 版本中的新功能,有待观察它将如何健壮。

_isolve:

  • 回调关键字不一致

  • tol 关键字已损坏,应为相对容差

  • Fortran 代码不可重入(但我们不解决,也许可以从 PyKrilov 重用)

_dsolve:

  • 添加与许可证兼容的稀疏 Cholesky 或不完全 Cholesky

  • 添加与许可证兼容的稀疏 QR

  • 改进 SuiteSparse UMFPACK 的接口

  • 添加 SuiteSparse CHOLMOD 和 SPQR 的接口

spatial#

QHull 包装器状态良好,KDTree 也是如此。

正在进行 C++ 中 spatial.distance 度量的重写 - 这应该会提高性能,使行为(例如,对于各种非 float64 输入 dtype)更加一致,并修复一些与少数度量实现的数学定义相关的剩余问题。

special#

尽管仍有许多函数需要提高精度,但可能唯一的主要障碍是超几何函数、抛物柱面函数和球形波函数。处理此问题的三种可能方法:

  1. 获取良好的双精度实现。抛物柱面函数可以做到这一点(正在进行中)。我认为超几何函数也是可能的,但可能不会及时实现。对于球形波函数,使用当前的理论是不可能的。

  2. 移植 Boost 的任意精度库,并在后台使用它来获得双精度精度。这可能是超几何函数的临时措施;@nmayorov 之前在 gh-5349 中也提出了使用任意精度的想法。对于球形波函数,这可能是必要的,可以重用:radelman/scattering

  3. 在文档中添加关于现有实现的限制的明确警告。

stats#

scipy.stats 子包旨在提供基础的统计方法,这些方法通常涵盖在标准的统计学教材中,例如 Johnson 的《工程师的概率与统计》(Miller & Freund's Probability and Statistics for Engineers)、Sokal 和 Rohlf 的《生物统计学》(Biometry)或 Zar 的《生物统计分析》(Biostatistical Analysis)。它并不寻求复制下游软件包(例如 StatsModels、LinearModels、PyMC3)的高级功能;相反,它可以为它们提供坚实的基础。(请注意,这些只是粗略的指导方针,而不是严格的规则。“高级”是一个定义模糊且主观的术语,“高级”方法也可能包含在 SciPy 中,尤其是在没有其他广泛使用且支持良好的软件包涵盖该主题的情况下。另请注意,与下游项目一些重复是不可避免的,而且不一定是坏事。)

除了 SciPy 路线图 中描述的项目外,以下改进将有助于 SciPy 更好地发挥其作用。

  • 添加基础且广泛使用的假设检验,例如

    • 事后检验(例如邓内特检验)

    • 各种类型的方差分析 (ANOVA)

      • 双向方差分析(单次重复、重复次数一致、重复次数可变)

      • 多向方差分析(即,推广双向方差分析)

      • 嵌套方差分析

      • 协方差分析 (ANCOVA)

    此外,提供一个用于实现假设检验的基础设施。

  • 添加用于荟萃分析的额外工具

  • 添加用于生存分析的工具

  • 加速分布的随机变量抽样(方法 rvs),在适当的地方利用 scipy.stats.sampling

  • 扩展 QMC 功能和性能

  • 增强连续概率分布的 fit 方法

    • 扩展拟合的选项,包括

      • 最大乘积间距

      • L 矩方法 / 概率加权矩

    • 在结果中包含拟合优度的度量

    • 处理删失数据(例如,合并 gh-13699

  • 实现其他广泛使用的连续和离散概率分布,例如混合分布。

  • 改进 SciPy 概率分布提供的核心计算,以便它们可以稳健地处理各种参数值。具体来说,将 scipy.special 中使用的 Fortran 库 CDFLIB 中的许多 PDF 和 CDF 方法替换为 Boost 实现,如 gh-13328 中所示。

此外,我们应该

  • 继续努力使 statsstats.mstats 的函数签名更加一致,并添加测试以确保这种情况保持不变。

  • 改进统计检验:返回检验统计量的置信区间,并实现精确的 p 值计算——考虑出现联系的可能性——在计算上可行的情况下。