NumPy 和 SciPy 中的科学函数

Python 是一种通用计算语言,但在科学计算领域非常受欢迎。得益于 Python 生态系统中的一些库,在许多情况下它可以取代 R 和 Matlab。在机器学习中,我们广泛使用一些数学或统计函数,并且通常会发现 NumPy 和 SciPy 非常有用。下面,我们将简要概述 NumPy 和 SciPy 提供的内容以及一些使用技巧。

完成本教程后,您将了解

  • NumPy 和 SciPy 为您的项目提供什么
  • 如何使用 numba 快速加速 NumPy 代码

通过我的新书 Python for Machine Learning 快速启动您的项目,其中包括分步教程和所有示例的Python 源代码文件。

让我们开始吧!

NumPy 和 SciPy 中的科学函数
照片由 Nothing Ahead 提供。保留部分权利。

概述

本教程分为三个部分

  • NumPy 作为张量库
  • SciPy 中的函数
  • 使用 numba 加速

NumPy 作为张量库

虽然 Python 中的列表和元组是我们原生管理数组的方式,但 NumPy 提供了更接近 C 或 Java 的数组功能,因为我们可以强制要求所有元素具有相同的数据类型,并且在处理高维数组时,在每个维度上都具有规则的形状。此外,在 NumPy 数组上执行相同操作通常比在 Python 中原生执行更快,因为 NumPy 中的代码经过高度优化。

NumPy 提供了成千上万个函数,您应该查阅 NumPy 的文档以获取详细信息。以下备忘单中包含一些常见用法

NumPy 备忘单。版权所有 2022 MachineLearningMastery.com

NumPy 有一些很酷的功能值得一提,因为它们对机器学习项目很有帮助。

例如,如果我们想绘制一个 3D 曲线,我们会计算 $z=f(x,y)$ 对于一系列 $x$ 和 $y$,然后将其结果绘制在 $xyz$ 空间中。我们可以这样生成范围

对于 $z=f(x,y)=\sqrt{1-x^2-(y/2)^2}$,我们可能需要一个嵌套的 for 循环来扫描数组 `x` 和 `y` 中的每个值并进行计算。但在 NumPy 中,我们可以使用 `meshgrid` 将两个一维数组扩展成两个二维数组,通过匹配索引,我们可以获得所有组合,如下所示

在上面,`meshgrid()` 生成的二维数组 `xx` 在同一列上具有相同的值,而 `yy` 在同一行上具有相同的值。因此,对 `xx` 和 `yy` 的逐元素操作本质上是对 $xy$-平面进行的操作。这就是它有效的原因,以及我们为什么可以绘制上面的椭球体。

NumPy 中的另一个好功能是用于扩展维度的函数。神经网络中的卷积层通常期望 3D 图像,即 2D 像素,以及作为第三维的不同颜色通道。它适用于具有 RGB 通道彩色图像,但对于灰度图像我们只有一个通道。例如,scikit-learn 中的 digits 数据集

这表明该数据集有 1797 张图像,每张图像为 8x8 像素。这是一个灰度数据集,显示每个像素是暗度值。我们将第 4 轴添加到此数组(即,将 3D 数组转换为 4D 数组),以便每张图像为 8x8x1 像素

使用 NumPy 数组时的一个便捷功能是布尔索引和花式索引。例如,如果我们有一个二维数组

我们可以检查一列中的所有值是否为正

这表明只有前两列是全正的。请注意,这是一个长度为 5 的一维数组,与数组 `X` 的轴 1 大小相同。如果我们使用此布尔数组作为轴 1 的索引,我们将仅选择索引为正的子数组

如果使用整数列表代替上述布尔数组,我们将根据匹配列表的索引从 `X` 中选择。NumPy 将此称为花式索引。因此,下面我们可以选择前两列两次,形成一个新数组

SciPy 中的函数

SciPy 是 NumPy 的姊妹项目。因此,您将主要看到 SciPy 函数接受 NumPy 数组作为参数或返回 NumPy 数组。SciPy 提供了许多不常用或更高级的函数。

SciPy 函数组织在子模块下。一些常见的子模块是

  • scipy.cluster.hierarchy:层次聚类
  • scipy.fft:快速傅里叶变换
  • scipy.integrate:数值积分
  • scipy.interpolate:插值和样条函数
  • scipy.linalg:线性代数
  • scipy.optimize:数值优化
  • scipy.signal:信号处理
  • scipy.sparse:稀疏矩阵表示
  • scipy.special:一些奇异数学函数
  • scipy.stats:统计,包括概率分布

但永远不要假设 SciPy 能覆盖一切。例如,对于时间序列分析,最好依赖 `statsmodels` 模块。

我们在其他帖子中介绍了许多使用 `scipy.optimize` 的示例。它是一个很好的工具,可以通过例如牛顿法来查找函数的最小值。NumPy 和 SciPy 都有用于线性代数的 `linalg` 子模块,但 SciPy 中的函数更高级,例如用于 QR 分解或矩阵指数的函数。

也许 SciPy 最常用的功能是 `stats` 模块。在 NumPy 和 SciPy 中,我们都可以生成具有非零相关性的多元高斯随机数。

但是,如果我们想引用分布函数本身,最好依赖 SciPy。例如,著名的 68-95-99.7 法则是指标准正态分布,我们可以从 SciPy 的累积分布函数中获得确切的百分比

因此,我们看到在正态分布中,我们期望值落在均值一个标准差以内的概率为 68.269%。反之,我们有百分点函数作为累积分布函数的反函数

这意味着,如果数值服从正态分布,我们预计有 99% 的概率(单尾概率)数值不会超过均值 2.32 个标准差。

这些是 SciPy 如何在 NumPy 提供的功能之上更进一步的示例。

想开始学习机器学习 Python 吗?

立即参加我为期7天的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

使用 numba 加速

NumPy 比原生 Python 更快,因为许多操作是用 C 实现的,并且使用了优化的算法。但有时我们想做一些事情,但 NumPy 仍然太慢。

如果你让 `numba` 通过并行化或将操作移动到 GPU(如果你有 GPU)来进一步优化它,可能会有帮助。你需要先安装 `numba` 模块

如果你需要将 `numba` 编译成 Python 模块,可能需要一些时间。之后,如果你的函数仅包含 NumPy 操作,你可以添加 `numba` 装饰器来加速它

它的作用是使用即时编译器来向量化操作,以便它可以运行得更快。如果你的函数在程序中运行很多次(例如,梯度下降中的更新函数),你可以看到最佳的性能提升,因为运行编译器的开销可以被摊销。

例如,下面是一个 t-SNE 算法的实现,用于将 784 维数据转换为 2 维。我们不打算详细解释 t-SNE 算法,但它需要许多迭代才能收敛。下面的代码展示了如何使用 `numba` 来优化内部循环函数(并且它也展示了一些 NumPy 的用法)。完成需要几分钟。之后你可以尝试删除 `@numba.jit` 装饰器。这将花费更长的时间。

进一步阅读

如果您想深入了解,本节提供了更多关于该主题的资源。

API 文档

总结

在本教程中,您简要了解了 NumPy 和 SciPy 提供的函数。

具体来说,你学到了:

  • 如何使用 NumPy 数组
  • SciPy 提供的一些实用函数
  • 如何通过使用 numba 的 JIT 编译器来加速 NumPy 代码

掌握机器学习 Python!

Python For Machine Learning

更自信地用 Python 编写代码

...从学习实用的 Python 技巧开始

在我的新电子书中探索如何实现
用于机器学习的 Python

它提供自学教程数百个可运行的代码,为您提供包括以下技能:
调试性能分析鸭子类型装饰器部署等等...

向您展示高级 Python 工具箱,用于
您的项目


查看内容

对 *NumPy 和 SciPy 中的科学函数* 的 2 条回复

  1. Pamphile Roy 2022 年 5 月 26 日 9:19 am #

    好文章!请更新 NumPy 关于随机数生成器的部分。Randint、randn 等在新代码中不应使用。np.random.Generator 应在新代码中使用 :)

    • James Carmichael 2022 年 5 月 27 日 9:24 am #

      感谢 Pamphile 的反馈!

留下回复

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。