32

走过19年,每年千万下载量,科学计算开源库SciPy的前世今生

 4 years ago
source link: https://www.jiqizhixin.com/articles/2020-02-05-9
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作为科学计算中的中流砥柱,SciPy 从 2001 年到现在已经走过了十九个年头,它为最优化、积分、微分方程等各种数值计算提供了完整的流程,也为科研分析人员提供了最好用与高效的开源库。

前天 2 月 3 日,SciPy 的维护者在 Nature Methods 上发表了一篇论文,其回顾了 SciPy 发展的里程碑与关键技术。并借助 SciPy 1.0 这个成熟的象征,展现了当前科学计算以及未来发展方向都是什么样的。

fauIJfN.jpg!web

  • 论文地址:

    https://www.nature.com/articles/s41592-019-0686-2

  • SciPy 项目地址:

    https://github.com/scipy/scipy

为什么 SciPy 那么重要?

SciPy 是一个面向 Python 的开源科学计算库。自 2001 年首次发布以来,SciPy 已经成为 Python 语言中科学算法的行业标准。该项目拥有超过 800 个独特的代码贡献者,数以千计的相关开发包,和超过 150,000 个依赖存储库以及每年数以百万计的下载量。在下述简介中,会概述 SciPy 1.0 的功能和开发实践,并着重阐述一些最新的技术发展与更新。(注:数据更新来自 Github 最新反馈)

ZFbiInu.jpg!web

SciPy 是一个基于 Python 和 Numeric 的开源代码包,当前模块集包括了上图中的内容。

项目覆盖范围

SciPy 提供了科学计算的基本算法,这些算法涵盖了现有数学软件分类系统中的算法。在迭代相对缓慢的领域(如:线性代数),SciPy 旨在提供完整的算法覆盖。

而在其他领域,它提供基本的构件,并与该领域的其他软件包进行良好的互动于兼容。例如,SciPy 提供了人们期望在统计学教科书中能找到的基本算法(概率分布、假设检验、频率统计、相关函数等),但 Statsmodels 提供了更先进的统计预估及推断方法。虽然 scikit-learn 涵盖了机器学习,但 PyMC、emcee 和 PyStan 涵盖了贝叶斯统计和概率建模等。

SciPy 能干什么

我们知道 SciPy 是一个用于数学、科学、工程领域的常用库,可以处理插值、积分、最优化、常微分方程数值解的求解、信号处理等问题。因此自然科学领域绝大多数涉及计算的工作都能用它来完成,例如我们熟知的统计学习,拟合个分布、做了 K 最近邻算法都是非常便捷的。

当然目前新冠肺炎疫情广受关注,研究者也可以用它模拟各种关键信息。例如之前中国疾病预防控制中心、国内各省市疾控中心等机构在新英格兰医学杂志发表的 《新型冠状病毒肺炎在中国武汉的早期传播》 论文。

在获取数据之后,进行各种统计学分析很多都可以用 Scipy 完成,具体而言:

  • 研究者根据发病日期构建传染曲线;

  • 使用对数高斯分布拟合暴露历史和发病日期数据,估计潜伏期分布;

  • 使用韦伯分布拟合发病日期、首次就诊日期和住院日期,并估计发病离就诊的时间间隔分布、发病离住院的时间间隔分布;

  • 使用伽玛分布拟合病例集群数据,从而估计人际传播的时间间隔(serial interval)分布。

这些分析任务主要在于利用统计分布拟合对应的数据,该肺炎论文的研究者采用 MATLAB 做的拟合。但实际上,scipy.status 包含了 100 多个概率分布,这些统计分析也能通过 SciPy 完成。

面对汹涌的疫情,不论我们是有第一手数据,还是从各网站爬取疫情信息,利用 SciPy 建模与分析都是非常好的选择。

SciPy 发展里程碑

20 世纪 90 年代末期,美国梅奥医学中心的博士生 Travis Oliphant 发布了一系列构建于数值数组之上的包,并提供了用于信号处理、特殊函数、稀疏矩阵、正交、最优化和快速傅里叶变换等的算法。

这些包中的 Multipack 是一组包装了 Fortran 和 C 语言的扩展模块,用于解决非线性方程和最小二乘问题、求微分方程的积分以及拟合曲线。

随后,编程环境愈加丰富,也具备了适当的数值数组对象,开发全栈科学软件的时机成熟了。2001 年,Eric Jones 和 Travis Vaught 创建了 Enthought 科学计算解决方案。

之后,为了简化工具堆栈,他们创建了以 SciPy 库为中心的 SciPy 项目。该项目的发展势头很猛,2001 年 2 月推出网站和代码库,6 月宣布邮件列表,8 月推出了 SciPy 0.1 版。

SciPy 早期版本的文档较少,但随着 2006 年发布 Numpy 指南(Guide to Numpy),这种情况开始改变。2007 年,Sphinx 文档生成器使得 SciPy 能够从包含 Python 代码的纯文本中自动呈现超文本和 PDF 文档。2008 年,Pydocweb 工具使得 SciPy 又能够以维基百科的方式进行协作文档开发。

在早期的 SciPy workshop 中,反复出现的一些主题反映了 SciPy 的开发状态,它将重心放在了底层数组包、绘图、并行处理、加速/包装和用户界面上。 到了 2004 年,关于 SciPy 应用于科学计算问题上的内容开始出现。

EfQVFzr.jpg!web

图 1: 自 2001 年发布 0.1 版到 2017 年推出 1.0 版本,SciPy 发展过程中的一些里程碑式事件。

SciPy 近三年的关键技术

从 2001 年发布的 0.1,到近几年发布成熟版的 SciPy 1.0,最近三年 SciPy 在科学计算上有了更多的技术累积。我们可以用更少的算力运行更大的矩阵计算,用更精简的方式拟合更复杂与多样的概率分布,也可以跑一跑最新的最优化方法。 研究者在这篇论文中着重介绍了 SciPy 一路走来的关键技术。

数据结构:稀疏矩阵

scipy.sparse 提供了 7 种稀疏矩阵数据结构,或者称之为稀疏格式。其中最重要的一种是压缩行/压缩列的稀疏格式,它们分别为 CSR 与 CSC。这两种方法都提供了快速的主轴索引与快速的矩阵-向量乘法,这两种稀疏格式在 SciPy 及依赖的库中得到了广泛的应用。

从新特性的角度来看,scipy.sparse 矩阵与线性运算子现在都已经支持 Python 矩阵乘法(@)。

cKDTree

scipy.spatial.ckdtree 模块实现了空间分割的数据结构,该结构会在 K 维空间中组织数据点。整个 cKDTree 模块通过模板化类用 C++重写了,并新增对周期性边界条件的支持,它经常用于物理过程的模拟。

2013 年,基于 cKDTree.query 的 K 最近邻算法时间复杂度逼近了对数线性。2015 年,cKDTree 二元树计数算法通过加强以支持加权,这对于很多科学应用来说都是非常重要的,例如计算星系的相关性函数。

统一捆绑到已编译代码:LowLevelCallable

到了 SciPy 0.19,用户就可以直接使用 scipy.LowLevelCallable 对象包装底层函数,从而减少直接从 Python 调用已编译 C 函数的开销,这种编译的 C 函数可能是由 Numba 或 Cython 生成的。

数学优化

scipy.optimize 子包提供了数学解决方案,用于解决多种类型的「root finding」和优化问题。

研究者在表 1 中详细比较了所有最小化方法的特征,这些特征说明了 SciPy 如果要达到比较完整的水平,它需要涵盖的数值方法或主题。

MFbEJzM.jpg!web

统计分布

scipy.status 包含了 100 多个概率分布:96 个连续分布和 13 个离散单变量分布,以及 10 个多变量分布。该实现依赖于一个一致的框架,该框架提供了抽样随机变量的方法,用以评估累积分布函数指数(CDF)和概率密度函数指数(PDF),并适合每一个分布的参数。

测试套件

在更改代码时,测试驱动的开发被认为是一种管理不确定性的方法。对于 SciPy 的每个组件,研究者都编写了多种能够验证它们预期行为的可执行小测试。这些可执行小测试的集合被称为『测试套件』,增强了对正确性和准确度的置信度,并允许用户在修改已有代码时不会改变预期行为。

fAzUvaq.png!web

图 2: 不同版本 SciPy 中的 Python 和编译代码量。

除了保证单元测试通过之外,重要的是确保 SciPy 代码库的性能能够随时间推移而提升。比如,下图 3 展示了在大约 9 年的项目发展历程中,scipy.spatial. cKDTree.query 的性能提升情况。

qmqQbuJ.jpg!web

图 3: 从 cKDTree 的提出到 SciPy 1.0 的发布,scipy.spatial.cKDTree.query 的基准测试的结果。 图中的每个标记表示 SciPy 主分支中提交的基准测试的执行时间。

SciPy 仍在路上

SciPy 项目每 6 个月进行一次更新。任何感兴趣、有技术能力的开发者都可以参与贡献代码。虽然 SciPy 的研发成本已经超过了 1 千万美元,但是项目依然是没有资金支持的。 这些代码都是由大学研究生、学术界和工业界的人们在闲暇时间完成的。

SciPy 有着一个很大的开发社区,用户基数也很庞大。在 2017 年,通过 PyPI 下载的次数是 13,096,468 次,而通过 conda 下载的次数则有 5,776,017 次。

尽管如此,SciPy 依然在继续进步。下图的表格是一个持续更新的文档,描述了团队正在项目中进行改进和提升的工作。这份文档也提到了一些需要改进的地方。

rUvQJbu.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK