NumPy 1.16.0 发布说明#

此 NumPy 版本是最后一个支持 Python 2.7 的版本,并将作为长期支持版本进行维护,直至 2020 年提供错误修复。Python 3.4 的支持已被移除,支持的 Python 版本为 2.7 和 3.5-3.7。PyPI 上的 wheel 文件已与 OpenBLAS v0.3.4+ 链接,这应该可以解决先前 OpenBLAS 版本中发现的已知线程问题。

下游开发者在构建此版本时,应使用 Cython >= 0.29,如果使用 OpenBLAS,则应使用 OpenBLAS > v0.3.4。

此版本进行了大量重构,包含许多错误修复、改进的代码组织以及更好的跨平台兼容性。并非所有这些改进用户都能直接看到,但它们应该有助于未来更容易维护。

亮点#

  • 实验性(仅限选择加入)支持覆盖 NumPy 函数,请参阅下面的 __array_function__

  • matmul 函数现已成为 ufunc。这提供了更好的性能,并允许使用 __array_ufunc__ 进行覆盖。

  • 改进了对 ARM 和 POWER 架构的支持。

  • 改进了对 AIX 和 PyPy 的支持。

  • 改进了与 ctypes 的互操作性。

  • 改进了对 PEP 3118 的支持。

新增函数#

  • numpy.lib.recfuntions 模块中添加了新函数,以简化结构化赋值的更改

    • assign_fields_by_name

    • structured_to_unstructured

    • unstructured_to_structured

    • apply_along_fields

    • require_fields

    有关更多信息,请参阅用户指南:<https://docs.scipy.org.cn/doc/numpy/user/basics.rec.html>。

新的弃用项#

  • 类型字典 numpy.core.typeNAnumpy.core.sctypeNA 已弃用。它们存在错误且未被记录,将在 1.18 版本中移除。请改用 numpy.sctypeDict

  • numpy.asscalar 函数已弃用。它是更强大的 numpy.ndarray.item 的别名,未经过测试,并且对于标量会失败。

  • numpy.set_array_opsnumpy.get_array_ops 函数已弃用。作为 NEP 15 的一部分,它们已与 C API 函数 PyArray_SetNumericOpsPyArray_GetNumericOps 一同弃用。希望覆盖内置 ufunc 的内部循环函数的用户应使用 PyUFunc_ReplaceLoopBySignature

  • numpy.unravel_index 的关键字参数 dims 已弃用,请改用 shape

  • numpy.histogramnormed 参数已弃用。之前已弃用,但未发出警告。

  • 应用于非数值数组的 positive 运算符(+)已弃用。详细信息请参阅下文。

  • 将迭代器传递给堆栈函数已弃用

已过期的弃用#

  • NaT 比较现在返回 False 且不发出警告,完成了 NumPy 1.11 开始的弃用周期。

  • np.lib.function_base.unique 已移除,完成了 NumPy 1.4 开始的弃用周期。请改用 numpy.unique

  • 多字段索引现在返回视图而不是副本,完成了 NumPy 1.7 开始的弃用周期。该更改先前在 NumPy 1.14 中尝试过,但一直推迟到现今。

  • np.PackageLoadernp.pkgload 已移除。这些在 1.10 版本中已弃用,没有测试,并且在 1.15 版本中似乎已不再工作。

未来更改#

  • NumPy 1.17 将放弃对 Python 2.7 的支持。

兼容性说明#

Windows 上的 f2py 脚本#

在 Windows 上,用于运行 f2py 的已安装脚本现在是一个 .exe 文件而不是 *.py 文件,并且当 Scripts 目录在路径中时,应从命令行将其作为 f2py 运行。将 f2py 作为模块 python -m numpy.f2py [...] 运行,在任何 NumPy 版本中都可以无需修改路径而工作。

NaT 比较#

与 NaN 的行为一致,除了与 datetime64 或 timedelta64 NaT(“非时间”)值的非相等检查外,所有比较现在都始终返回 False,而与 NaT 的非相等检查现在始终返回 True。这包括 NaT 值之间的比较。为了与旧行为兼容,请使用 np.isnat 显式检查 NaT,或在进行比较之前将 datetime64/timedelta64 数组转换为 .astype(np.int64)

complex64/128 的对齐已更改#

复数类型的内存对齐现在与由两个浮点值组成的 C 结构体相同,而之前则等于类型的大小。对于许多用户(例如在 x64/unix/gcc 上),这意味着 complex64 现在是 4 字节对齐而不是 8 字节对齐。一个重要的后果是,对齐的结构化 dtype 的大小可能会发生变化。例如,np.dtype('c8,u1', align=True)(在 x64/gcc 上)过去的大小为 16,但现在是 12。

更详细地说,complex64 类型现在与 C 结构体 struct {float r, i;} 具有相同的对齐方式,具体取决于编译 NumPy 的编译器,complex128 和 complex256 类型同理。

移除 nd_grid __len__#

len(np.mgrid)len(np.ogrid) 现在被视为无意义,并引发 TypeError

np.unravel_index 现在接受 shape 关键字参数#

以前,只有 dims 关键字参数被接受用于指定用于解构数组的形状。dims 仍然受支持,但现已弃用。

多字段视图返回视图而不是副本#

使用多个字段索引结构化数组,例如 arr[['f1', 'f3']],将返回原始数组的视图而不是副本。返回的视图通常会包含对应于原始数组中间字段的额外填充字节,这与以前不同,可能会影响诸如 arr[['f1', 'f3']].view('float64') 之类的代码。此更改自 numpy 1.7 起已计划。自那时以来,命中此路径的操作已发出 FutureWarnings。在 1.12 中添加了关于此更改的额外 FutureWarnings

为了帮助用户更新其代码以应对这些更改,已向 numpy.lib.recfunctions 模块添加了许多函数,这些函数可以安全地允许此类操作。例如,上面的代码可以替换为 structured_to_unstructured(arr[['f1', 'f3']], dtype='float64')。有关更多信息,请参阅用户指南的“访问多个字段”部分:用户指南

C API 更改#

NPY_FEATURE_VERSION 已递增至 0x0000D,因为添加了

新功能#

直方图添加了平方误差 (ISE) 估计器#

此方法(bins='stone')用于优化 bin 数量,是 Scott 规则的泛化。Scott 规则假设分布近似正态,而 ISE 是一种基于交叉验证的非参数方法。

np.loadtxt 添加了 max_rows 关键字#

numpy.loadtxt 中新增关键字 max_rows,用于在 skiprows 之后设置要读取内容的最多行数,类似于 numpy.genfromtxt

np.timedelta64 操作数添加了模运算符支持#

现在支持两个 np.timedelta64 类型操作数的模(余数)运算符。操作数可以具有不同的单位,返回值将与操作数类型匹配。

改进#

NumPy 数组的无拷贝序列化#

在协议 4 之前,NumPy 数组的序列化会创建 2 个额外的副本。使用 pickle 协议 5 和 PickleBuffer API,现在可以使用带外缓冲区(out-of-band buffers)以无拷贝方式序列化各种 NumPy 数组,使用带内缓冲区(in-band buffers)则少一个副本。对于大型数组,这导致峰值内存使用量最高可降低 66%。

构建 shell 独立性#

NumPy 构建不再需要直接与主机 shell 交互。在适当的情况下,exec_command 已被替换为 subprocess.check_output

Jupyter Notebook 中 np.polynomial.Polynomial 类的 LaTeX 渲染#

当在支持的设备中使用时,Polynomial 实例现在可以通过 LaTeX 渲染。当前格式为实验性质,可能会发生更改。

randintchoice 现在可用于空分布#

即使不需要抽取元素,当参数描述一个空分布时,np.random.randintnp.random.choice 仍会引发错误。此问题已修复,例如 np.random.choice([], 0) == np.array([], dtype=float64)

linalg.lstsqlinalg.qrlinalg.svd 现在可与空数组一起使用#

先前,当传递空矩阵/空矩阵(零行和/或零列)时会引发 LinAlgError。现在会返回适当形状的输出。

链式异常,为无效的 PEP3118 格式字符串提供更好的错误消息#

这应该有助于追踪问题。

Einsum 优化路径更新和效率改进#

Einsum 与当前上游工作同步。

numpy.anglenumpy.expand_dims 现在可与 ndarray 子类一起使用#

特别是,它们现在也适用于掩码数组。

抑制 NPY_NO_DEPRECATED_API 编译器警告#

NPY_NO_DEPRECATED_API 设置为 0 值将抑制在使用已弃用的 NumPy API 时出现的编译器警告。

np.diff 添加了 prependappend 的 kwargs#

新的 prependappend kwargs 允许在差值两侧插入值。类似于 ediff1d 的选项。现在可以通过 prepend=0 轻松获得 cumsum 的逆运算。

ARM 支持更新#

对 ARM CPU 的支持已更新,以适应 32 位和 64 位目标,以及大端和小端字节序。AARCH32 内存对齐问题已得到解决。CI 测试已扩展,通过 shippable.com 的服务包含 AARCH64 目标。

追加构建标志#

numpy.distutils 过去总是覆盖而不是追加 LDFLAGS 和其他类似的编译 Fortran 扩展的环境变量。现在,如果 NPY_DISTUTILS_APPEND_FLAGS 环境变量设置为 1,行为将是追加。这适用于:LDFLAGSF77FLAGSF90FLAGSFREEFLAGSFOPTFDEBUGFFLAGS。有关更多详细信息,请参阅 gh-11525。

广义 ufunc 签名现在允许固定大小的维度#

通过在广义 ufunc 的签名中使用数值,可以指示该函数要求输入或输出具有给定大小的维度。例如,将极坐标角转换为二维笛卡尔单位向量的函数签名将是 ()->(2);将两个球坐标转换为三维单位向量的函数签名将是 (),()->(3);而三维向量叉乘的签名将是 (3),(3)->(3)

请注意,对于基本函数,这些维度与以字母开头的名称指示的可变维度没有区别;循环仍然接收相应的尺寸大小,但现在可以确定该尺寸大小等于签名中给出的固定尺寸。

广义 ufunc 签名现在允许灵活的维度#

一些函数,特别是 NumPy 对 @ 作为 matmul 的实现,与广义 ufuncs 非常相似,因为它们在核心维度上操作,但之前无法将它们呈现为这样,因为它们能够处理维度缺失的输入。为了支持这一点,现在允许在维度名称后加上问号,以指示该维度不一定存在。

有了这个补充,matmul 的签名可以表示为 (m?,n),(n,p?)->(m?,p?)。这表明,例如,如果第二个操作数只有一个维度,对于基本函数来说,它将被视为具有核心形状 (n, 1),输出具有相应的核心形状 (m, 1)。然而,实际的输出数组将移除灵活的维度,即其形状为 (..., m)。类似地,如果两个参数都只有一个维度,输入将作为形状 (1, n)(n, 1) 传递给基本函数,输出为 (1, 1),而实际返回的输出数组的形状为 ()。通过这种方式,签名允许使用单个基本函数处理四个相关的但不同的签名:(m,n),(n,p)->(m,p)(n),(n,p)->(p)(m,n),(n)->(m)(n),(n)->()

np.clipclip 方法检查内存重叠#

这些函数的 out 参数现在始终会检查内存重叠,以避免在发生内存重叠时导致结果损坏。

np.polyfit 中的 cov 选项添加了新值 unscaled#

np.polyfit 函数的 cov 参数添加了另一个可能的值。当 cov='unscaled' 时,协方差矩阵的缩放完全禁用(类似于在 scipy.optimize.curve_fit 中设置 absolute_sigma=True)。这在权重由 1/sigma 给出(其中 sigma 是(已知的)数据点(高斯分布)的标准误差)的情况下很有用,此时未缩放的矩阵已经是协方差矩阵的正确估计。

标量数值类型的详细文档字符串#

现在,当应用于数值类型(如 numpy.intcnumpy.int_numpy.longlong)时,help 函数会列出该类型的所有别名,区分平台相关和平台无关的别名。

__module__ 属性现在指向公共模块#

大多数 NumPy 函数的 __module__ 属性已更新,以指向访问函数的首选公共模块,而不是函数碰巧定义的模块。这会为 IPython 等工具中的函数显示更具信息性的内容,例如,不再是 <function 'numpy.core.fromnumeric.sum'>,而是 <function 'numpy.sum'>

大型分配标记为适用于透明大页#

在支持通过 madvise 系统调用进行透明大页的系统上,NumPy 现在会将大型内存分配标记为可以由大页支持,这可以减少页面故障开销,并在某些页面故障密集的情况下显著提高性能。在 Linux 上,用于大页的设置 /sys/kernel/mm/transparent_hugepage/enabled 必须至少为 madvise。已经将其设置为 always 的系统不会看到太大差异,因为内核会自动在适当的地方使用大页。

使用非常旧的 Linux 内核(约 3.x 及更早版本)的用户应确保 /sys/kernel/mm/transparent_hugepage/defrag 不设置为 always,以避免由于内存碎片整理中的并发问题而导致性能下降。

Alpine Linux(及其他 musl C 库发行版)支持#

我们现在默认使用 fenv.h 进行浮点状态错误报告。以前我们有一个损坏的默认设置,有时不会报告下溢、溢出和无效的浮点运算。现在,只要它们提供 fenv.h,我们就可以支持非 glibc 发行版,如 Alpine Linux。

加速大型数组的 np.block#

大型数组(大于 512 * 512)现在使用基于直接将数据复制到结果数组的相应切片中的阻塞算法。这显著加速了这些大型数组的处理,特别是对于在超过 2 个维度上进行阻塞的数组。

arr.ctypes.data_as(...) 持有对 arr 的引用#

先前,调用者负责在指针的生命周期内保持数组的活动。

加速只读数组的 np.take#

当源数组的 writeable 标志设置为 False 时,np.take 的实现不再进行不必要的源数组副本。

为更多函数支持路径类对象#

除了文件对象外,np.core.records.fromfile 函数现在还支持 pathlib.Path 和其他路径类对象。此外,np.load 函数在内存映射(mmap_mode 关键字参数)时也支持路径类对象。

ufunc 恒等式在归约操作中的行为改进#

通用函数有一个 .identity 属性,当在空轴上调用 .reduce 时使用。

从本次发布开始,逻辑二元 ufunc logical_andlogical_orlogical_xoridentity 类型为 bool,而之前为 int。这恢复了 1.14 版本在对这些 ufunc 进行空对象数组归约时得到 bool 的行为,同时保留了 1.15 版本在对 addmultiply 等算术 ufunc 进行空对象数组归约时得到 int 的行为。

此外,logaddexp 现在具有 -inf 的恒等式,允许它在空序列上调用,而之前则不行。

这得益于新的 PyUFunc_FromFuncAndDataAndSignatureAndIdentity,它允许现在使用任意值作为恒等式。

改进了从 ctypes 对象转换#

NumPy 一直支持从 ctypes 获取值或类型并将其转换为数组或 dtype,但之前仅对更简单的类型有效。从本次发布开始,此限制已解除 - 现在

  • 已遵守 ctypes.Structure_pack_ 属性,该属性用于模拟 C 的 __attribute__((packed))

  • 保留所有 ctypes 对象的字节序

  • 支持 ctypes.Union

  • 无法表示的结构会引发异常,而不是产生危险的不正确结果

    • 位域不再被解释为子数组

    • 指针不再被指向的类型替换

新的 ndpointer.contents 成员#

这与普通 ctypes 数组的 .contents 成员匹配,可用于围绕指针内容构造 np.array。这取代了 np.array(some_nd_pointer)(在 1.15 中已停止工作)。作为此更改的副作用,ndpointer 现在支持具有重叠字段和填充的 dtypes。

matmul 现已成为 ufunc#

numpy.matmul 现已成为 ufunc,这意味着函数和 __matmul__ 运算符都可以被 __array_ufunc__ 覆盖。其实现也已更改。它使用与 numpy.dot 相同的 BLAS 例程,确保其性能与大型矩阵相似。

linspacelogspacegeomspace 的开始和停止数组#

这些函数过去仅限于标量停止和开始值,但现在可以接受数组,这些数组将被正确广播,并生成一个在前面附加了一个轴的输出。例如,这可用于获得点集之间的线性插值点。

CI 已扩展,增加了额外服务#

得益于提供服务的公司,我们现在可以使用额外的免费 CI 服务:

  • 通过 codecov.io 进行代码覆盖率测试

  • 通过 shippable.com 进行 Arm 测试

  • 在 Azure Pipelines 上进行额外的测试运行

这些是继我们持续使用 travis、appveyor(用于 wheels)和 LGTM 之外的服务。

更改#

比较 ufunc 现在会报错而不是返回 NotImplemented#

以前,像 np.equal 这样的比较 ufunc 在其参数具有结构化 dtype 时会返回 NotImplemented,以帮助诸如 __eq__ 之类的比较运算符处理这些情况。现在不再需要这样做,因为相关的逻辑已移至比较运算符本身(因此它们会像往常一样返回 NotImplemented)。因此,与所有其他 ufunc 一样,比较 ufunc 现在在结构化 dtype 上会引发错误。

Positive 现在会针对非数值数组引发弃用警告#

以前,+array 无条件地返回副本。现在,如果数组不是数值型的(即,如果 np.positive(array) 引发 TypeError),它将引发 DeprecationWarning。对于重写了默认 __array_ufunc__ 实现的 ndarray 子类,TypeError 会被传递下去。

NDArrayOperatorsMixin 现在实现了矩阵乘法#

以前,np.lib.mixins.NDArrayOperatorsMixin 没有实现 Python 矩阵乘法运算符(@)的特殊方法。现在 matmul 已经是一个 ufunc,并且可以使用 __array_ufunc__ 进行重写,因此这种情况已经改变。

np.polyfit 中协方差矩阵的缩放方式不同#

到目前为止,np.polyfit 在协方差矩阵的缩放中使用了非标准因子。具体来说,它不是使用标准的 chisq/(M-N),而是使用 chisq/(M-N-2) 进行缩放,其中 M 是数据点的数量,N 是参数的数量。这种缩放方式与 scipy.optimize.curve_fit 等其他拟合程序不一致,已更改为 chisq/(M-N)

maximumminimum 不再发出警告#

作为 1.10 中引入的代码的一部分,当在 numpy.maximumnumpy.minimum 中遇到 Nan 时,float32float64 会设置无效浮点状态,在使用 SSE2 语义时。这有时会导致发出 RuntimeWarning。在 1.15 中,我们修复了导致警告更加明显的那些不一致性。现在将不再发出警告。

Umath 和 multiarray c 扩展模块已合并为一个模块#

根据 NEP 15,这两个模块已被合并。以前 np.core.umathnp.core.multiarray 是独立的 c 扩展模块。现在它们是单个 np.core/_multiarray_math c 扩展模块的 Python 包装器。

getfield 的有效性检查已扩展#

numpy.ndarray.getfield 现在会检查 dtype 和 offset 参数,以防止访问无效内存位置。

NumPy 函数现在支持使用 __array_function__ 进行重写#

NumPy 有一个实验性的新机制,通过定义 __array_function__ 方法来重写几乎所有 NumPy 函数在非 NumPy 数组上的实现,如 NEP 18 所述。

此功能尚未默认启用,但已发布以方便潜在用户的试验。有关设置适当环境变量的详细信息,请参阅 NEP。我们预计 NumPy 1.17 版本将默认启用重写,并且由于使用 C 编写的新实现,其性能也会有所提高。

基于只读缓冲区的数组不能被设置为 writeable#

我们现在不允许将从 fromstring(readonly-buffer) 创建的数组的 writeable 标志设置为 True。