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——以及我们依赖项的各种版本和构建发布质量的轮子。由于要支持大量的配置,并且一些CI作业需要大修,CI的可靠性最近(2023年上半年)并不理想。我们旨在通过删除删除distutils构建系统后剩余的distutils构建作业,并使CI作业中的配置集更加正交来减少构建时间。

二进制文件大小#

SciPy二进制文件相当大(例如,1.7.3的解压缩的manylinux wheel在PyPI上为39 MB,安装后为122 MB),这可能会造成问题——例如,在AWS Lambda中使用时,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 float,对于其他任何内容,请使用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

BLAS和LAPACK

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

  1. 库支持。我们发布的轮子现在附带OpenBLAS,这是目前唯一可行的性能良好的选项(ATLAS太慢,MKL由于许可问题不能作为默认选项,Accelerate支持被取消,因为Apple不再更新Accelerate)。但是,OpenBLAS并不稳定,有时它的版本会导致问题,并且在使用线程时存在问题(目前是使用SciPy与PyPy3的唯一问题)。我们至少需要更好地支持调试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将作为一个公共模块被删除。它的大多数函数已被移至另一个子模块或被弃用。剩下的几个函数

  • derivativecentral_diff_weight:移除,可能用更广泛的数值微分功能来替换。

  • ascentfaceelectrocardiogram:移除或移动到适当的子包(例如,scipy.ndimagescipy.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 对象的默认滤波方法。

小波:现在的小波没有多大意义。目前只有连续小波 - 决定是完全重写还是移除它们。离散小波变换超出了范围(PyWavelets 对它们做了很好的工作)。

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 支持 min-max、索引、算术。

  • 帮助其他库从稀疏矩阵转换为稀疏数组。创建转换指南和有用的脚本以标记需要进一步检查的代码。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 也是如此。

正在对 spatial.distance 度量进行 C++ 重写 - 这将提高性能,使行为(例如,对于各种非 float64 输入数据类型)更加一致,并解决一些度量数学实现的定义中存在的剩余问题。

special#

虽然仍然有很多函数需要提高精度,但可能唯一的问题是超几何函数、抛物柱面函数和球状波函数。处理此问题的三种可能方法

  1. 获得良好的双精度实现。这对抛物柱面函数来说是可以实现的(正在进行中)。我认为超几何函数也是可以实现的,尽管可能来不及了。对于球状波函数,目前没有理论可以做到这一点。

  2. 移植 Boost 的任意精度库,并在幕后使用它来获得双精度精度。这可能需要作为对超几何函数的权宜之计;使用任意精度的想法之前由 @nmayorov 和在 gh-5349 中提出。可能需要用于球状波函数,这可以重复使用:radelman/scattering

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

统计#

scipy.stats 子包旨在提供基础统计方法,这些方法可能在标准统计学教科书中有所涉及,例如 Johnson 的“Miller & Freund 的工程师概率与统计”,Sokal & Rohlf 的“生物测量学”或 Zar 的“生物统计学分析”。它不试图复制下游包(例如 StatsModels、LinearModels、PyMC3)的先进功能;相反,它可以提供一个坚实的基础,这些包可以建立在其之上。(注意,这些只是粗略的指南,不是严格的规则。“高级”是一个定义不明确且主观的术语,SciPy 中也可能包含“高级”方法,尤其是在没有其他广泛使用且支持良好的包涵盖该主题的情况下。另请注意,与下游项目的一些重复是不可避免的,也不一定是件坏事。)

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

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

    • 事后检验(例如 Dunnett 检验)

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

      • 双因素 ANOVA(单次重复、均匀重复次数、可变重复次数)

      • 多因素 ANOVA(即泛化双因素 ANOVA)

      • 嵌套 ANOVA

      • 协方差分析(ANCOVA)

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

  • 添加用于元分析的其他工具

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

  • 加快分布的随机变量采样(方法 rvs),在适当情况下利用 scipy.stats.sampling

  • 扩展 QMC 功能和性能

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

    • 扩展拟合选项以包括

      • 最大乘积间距

      • L 矩 / 概率加权矩方法

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

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

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

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

此外,我们应该

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

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