NumPy 1.16.0 发布说明#

此 NumPy 版本是最后一个支持 Python 2.7 的版本,并将作为长期版本维护,直到 2020 年提供错误修复。对 Python 3.4 的支持已停止,受支持的 Python 版本是 2.7 和 3.5-3.7。PyPI 上的 wheels 文件与 OpenBLAS v0.3.4+ 链接,这应该能修复之前 OpenBLAS 版本中已知的线程问题。

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

此版本进行了大量重构,并包含许多错误修复、改进的代码组织和更好的跨平台兼容性。并非所有这些改进对用户都可见,但它们应该有助于使未来的维护工作更轻松。

亮点#

  • 实验性(仅限 opt-in)支持覆盖 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 已废弃。它们存在 bug 且未文档化,将在 1.18 版本中移除。请改用 numpy.sctypeDict

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

  • numpy.set_array_opsnumpy.get_array_ops 函数已废弃。作为 NEP 15 的一部分,它们已与 C-API 函数 PyArray_SetNumericOpsPyArray_GetNumericOps 一同废弃。希望覆盖内置 ufuncs 中内部循环功能的用户应使用 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 运行。在任何 NumPy 版本中,将 f2py 作为模块 python -m numpy.f2py [...] 运行都无需修改路径。

NaT 比较#

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

complex64/128 对齐已更改#

复数类型的内存对齐现在与由两个浮点值组成的 C 结构体相同,而之前它等于类型的大小。对于许多用户(例如在 x64/unix/gcc 上),这意味着 complex64 现在是 4 字节对齐而非 8 字节对齐。一个重要的结果是,对齐的结构化 dtype 现在可能具有不同的大小。例如,np.dtype('c8,u1', align=True) 以前(在 x64/gcc 上)的 itemsize 为 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。关于此更改的额外 FutureWarnings 已在 1.12 中添加。

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

C API 更改#

由于增加了以下内容,NPY_FEATURE_VERSION 已递增到 0x0000D:

新功能#

已向 histogram 添加集成平方误差 (ISE) 估计器#

这种优化 bin 数量的方法(bins='stone')是 Scott's rule 的推广。Scott's rule 假定分布近似正态,而 ISE 是一种基于交叉验证的非参数方法。

np.loadtxt 添加 max_rows 关键字#

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

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

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

改进#

numpy 数组的无拷贝序列化#

直到协议 4,numpy 数组序列化时会创建 2 个多余的数据副本。通过 pickle 协议 5 和 PickleBuffer API,现在可以使用带外缓冲区对各种 numpy 数组进行无拷贝序列化,并使用带内缓冲区减少一次拷贝。这对于大型数组来说,可使峰值内存使用量减少高达 66%。

构建 shell 独立性#

NumPy 构建不应再直接与主机 shell 交互。exec_command 已在适当位置替换为 subprocess.check_output

np.polynomial.Polynomial 类在 Jupyter notebooks 中以 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 已与当前的 upstream 工作同步。

numpy.anglenumpy.expand_dims 现在适用于 ndarray 子类#

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

NPY_NO_DEPRECATED_API 编译器警告抑制#

NPY_NO_DEPRECATED_API 设置为 0 将抑制使用已废弃的 numpy API 时当前的编译器警告。

np.diff 添加了关键字参数 prepend 和 append#

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

ARM 支持已更新#

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

添加到构建标志#

numpy.distutils 在编译 Fortran 扩展时,始终覆盖而非追加 LDFLAGS 和其他类似的环境变量。现在,如果将 NPY_DISTUTILS_APPEND_FLAGS 环境变量设置为 1,则行为将变为追加。这适用于:LDFLAGSF77FLAGSF90FLAGSFREEFLAGSFOPTFDEBUGFFLAGS。更多详情请参阅 gh-11525。

泛化 ufunc 签名现在允许固定大小维度#

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

请注意,对于基本函数而言,这些维度与以字母开头的名称表示的变量维度没有区别;循环仍然传递相应的尺寸,但现在它可以确信该尺寸等于签名中给定的固定尺寸。

泛化 ufunc 签名现在允许灵活维度#

一些函数,特别是 numpy 将 @ 实现为 matmul 的函数,与泛化 ufunc 非常相似,因为它们对核心维度进行操作,但无法将其呈现为泛化 ufunc,因为它们能够处理缺少维度的输入。为了支持这一点,现在允许在维度名称后添加问号,以指示该维度不一定必须存在。

通过此项添加,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.sum'>,而不是 <function 'numpy.core.fromnumeric.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 进行浮点状态错误报告。以前我们有一个损坏的默认设置,有时不会报告下溢、上溢和无效浮点运算。现在,只要非 glibc 发行版(如 Alpine Linux)提供 fenv.h,我们就可以支持它们。

加速大型数组的 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 归约过程中标识行为的改进#

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

自此版本起,逻辑二元 ufuncs,logical_andlogical_orlogical_xor,现在具有 bool 类型的 identity,而以前它们是 int 类型。这恢复了 1.14 版本在使用这些 ufuncs 归约空对象数组时获得 bool 值的行为,同时保留了 1.15 版本在使用 addmultiply 等算术 ufuncs 归约空对象数组时获得 int 值的行为。

此外,logaddexp 现在具有 -inf 的标识,允许在空序列上调用它,而以前则不能。

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

改进了从 ctypes 对象的转换#

Numpy 始终支持从 ctypes 获取值或类型并将其转换为数组或 dtype,但以前只对较简单的类型表现正确。自此版本起,此限制已解除——现在

  • 尊重 ctypes.Structure_pack_ 属性,该属性用于模拟 C 语言的 __attribute__((packed))

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

  • 支持 ctypes.Union

  • 不可表示的结构会引发异常,而不是产生危险的错误结果

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

    • 指针不再替换为它们指向的类型

新增 ndpointer.contents 成员#

这与普通 ctypes 数组的 .contents 成员匹配,可用于围绕指针内容构建 np.array。这取代了在 1.15 中停止工作的 np.array(some_nd_pointer)。作为此更改的副作用,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。