SciPY 科学家特刊
在我的上一篇文章中,我介绍了 NumPY 及其在数值模拟中的一些应用。虽然 NumPY 确实提供了一些非常强大的构建模块,但在更复杂的工具方面略有不足。 SciPY 是众多基于 NumPY 构建的 Python 模块之一。事实上,SciPY 已经成为 Python 编程中事实上的科学软件包。如果您有一个科学问题想要解决,那么从 SciPY 入手绝对不会错。它不仅提供了更高级的函数和对象来执行线性代数,还提供了处理微积分、插值、信号处理和快速傅里叶变换等功能的函数和对象。有如此多的函数可用,它们实际上被分组到子包中。在本文中,我将快速了解一下有哪些类型的函数可用,以及如何使用它们来完成一些重要的工作。
首先,您需要导入主 scipy 模块。您可以使用通常的
import scipy
这会导入 SciPY 中使用的常用函数和对象集。它还导入了 NumPY 中最常用的部分,因为它们对于 SciPY 所用的工作至关重要。如果您需要 NumPY 中的任何其他内容,您需要显式导入 NumPY 模块。在许多情况下,无论如何您都会想要这样做。各个子包中的所有额外函数都需要显式导入。因此,如果您想进行一些信号处理,您需要使用这个
from scipy import signal
SciPY 中最简单的包可能是 constants 子包。此包提供了一组最常用的基本物理常数,例如 pi 或阿伏伽德罗常数。它还包括来自 2010 CODATA 数据库的更大一组常数。这些物理常数存储为值、单位和不确定性的元组,它们包括从 α 粒子质量到维恩波长位移定律常数等各种项目。 scipy.misc 子包包含所有那些真正不适合任何其他地方的零碎内容。在这里,您可以找到像 factorial(计算数字的阶乘)和 imread(将图像文件读入 Python)这样的函数。
线性代数是计算代码的重要用途之一。 SciPY 包括一个名为 linalg 的子包,它是 NumPY 中 linalg 包的包装器。来自 NumPY 的所有功能都包含在 scipy.linalg 中,以及其他几个函数。在 NumPY 模块中,这些线性代数函数可能由外部库处理,也可能不处理,具体取决于 NumPY 的编译方式。使用 SciPY,这不再是一种选择。它需要使用 ATLAS LAPACK 和 BLAS 库进行编译,以便以优化的方式处理实际的数值工作。有一些函数可以处理诸如查找矩阵的逆矩阵、行列式或转置之类的事情。如果您需要求解方程组,您可以通过单个函数调用来完成。如果您从系数矩阵 A 和右手边向量 b 开始,您可以使用以下方法找到系统的解向量
from scipy import linalg
linalg.solve(A,b)
在许多物理和工程问题中,您需要找到特征值和特征向量。 linalg 子包也提供了非常快速的函数来执行此操作。
大多数人默认使用 R 来进行统计,但您不必这样做。 SciPY 包括一个 stats 子包,它提供了您在大多数情况下需要的大部分函数。 describe 函数将为您提供样本向量的基本统计描述。这包括均值、方差、偏度和峰度。一旦您掌握了一些基本的统计数据,您可能想要运行 t 检验,以查看您的数据与您的模型匹配程度如何。您可以使用类似这样的方法来做到这一点
stats.ttest_1samp(x, m)
其中 x 是您的数据,m 是您的模型。这将为您提供一个 t 统计量和一个 p 值。就像在 R 中一样,您可以使用更多更复杂的统计函数。
我个人非常感兴趣的一个主题是求解微分方程。 SciPY 也可以帮助完成这项任务。您需要的子包名为 integrate。有两组函数,一组将函数对象作为输入,另一组采用一组固定样本。您可以使用函数 quad、dblquad 和 tplquad 对函数对象执行单重、双重和三重积分。如果您有来自某些实验的数据,您可以使用梯形法则、辛普森法则或龙贝格积分对其进行积分。如果您正在处理常微分方程,则可以使用一些特殊函数。函数 odeint 将使用给定的一组初始条件求解一组常微分方程。
最后,但同样重要的是,让我们看一下 weave 子包。即使 SciPY 已经功能齐全,它也无法涵盖每一种可能性。虽然您始终可以使用纯 Python 编写代码来处理任何缺失的部分,但有时您需要从硬件中挤出每一丝性能。在这些情况下,您可能需要编写一些优化的 C 代码来完成繁重的工作。虽然您可以编写并将其编译为外部目标文件,但这对于任何有自尊的程序员来说都太麻烦了。进入 weave 子包。
使用 weave,您可以通过多种方式从 Python 程序中添加 C 代码。最直接的是 inline 函数。使用此函数,您可以编写 C 或 C++ 代码,对其进行编译,并在 Python 程序中直接运行它。您的所有 Python 对象都可以在内联代码的范围内使用。任何可变对象的内容都可以从您的 C/C++ 代码中更改。如果您想将结果返回到您的 Python 程序,这些结果可以在一个名为“return_val”的特殊变量中使用。 SciPY 文档中的一个简单示例使用 printf 来展示内联函数的工作原理
import weave
a = 1
weave.inline('printf("%d\\n",a);',['a'])
inline 函数的一般形式是一个包含要编译和运行的代码的字符串,以及一个 Python 变量列表,这些变量可供 C/C++ 代码使用。如果您有更大的代码片段想要内联,您可以使用三引号来定义代码块并首先将其保存到变量中。例如,您可能有类似这样的内容
code = """
for (int i=0; i<a; i++) {
printf("%d\\n", i);
}"""
weave.inline(code, ['a'])
另一种加速代码的方法是让 Python 使用 blitz 函数为您完成。在这种情况下,blitz 接受一些 NumPY 表达式,并创建 C++ 代码并将其编译为外部模块。您第一次执行此操作时,可能需要几分钟才能生成代码并对其进行编译。完成后,编译后的目标文件将被存储起来,以便下次调用时重用。现在,您可以看到比直接使用 Python 代码快 2-10 倍的速度提升。它也会在 Python 关闭后保存,因此您可以在下次运行 Python 代码时重复使用它。
现在您已经拥有了一些可用于进行实际科学计算的工具。在我的下一篇文章中,我将介绍 matplotlib,这是可视化您一直在进行的所有计算工作的方法之一。在那之前,去做一些科学研究吧。