NumPy 1.15.0 发布说明#

NumPy 1.15.0 是一个进行了异常数量的清理、许多旧函数被弃用以及对许多现有函数进行改进的版本。请阅读下面的详细描述以了解您是否受到影响。

为了测试,我们已改用 pytest 作为不再维护的 nose 框架的替代品。旧的基于 nose 的接口仍保留给可能仍在使用的下游项目。

此版本支持的 Python 版本为 2.7、3.4-3.7。 коле子(wheels)与 OpenBLAS v0.3.0 链接,这应该能解决 NumPy 1.14 报告的一些 linalg 问题。

亮点#

  • NumPy 已改用 pytest 进行测试。

  • 一个新的 numpy.printoptions 上下文管理器。

  • 直方图函数的多项改进。

  • 在 Python 2.7 中支持 Unicode 字段名。

  • 改进了对 PyPy 的支持。

  • 修复和改进了 numpy.einsum

新函数#

  • numpy.gcdnumpy.lcm,用于计算最大公约数和最小公倍数。

  • numpy.ma.stack,是 numpy.stack 数组连接函数对掩码数组的泛化。

  • numpy.quantile 函数,一个不带 100 倍数因子的 percentile 接口。

  • numpy.nanquantile 函数,一个不带 100 倍数因子的 nanpercentile 接口。

  • numpy.printoptions,一个上下文管理器,它可以在 with 块的作用域内临时设置打印选项。

    >>> with np.printoptions(precision=2):
    ...     print(np.array([2.0]) / 3)
    [0.67]
    
  • numpy.histogram_bin_edges,一个用于获取直方图所用 bin 边缘的函数,无需计算直方图。

  • C 函数 npy_get_floatstatus_barriernpy_clear_floatstatus_barrier 已被添加,用于处理编译器优化改变操作顺序的问题。详情见下文。

弃用#

  • 内置 pickle 函数的别名已弃用,建议使用其非别名 pickle.<func> 名称。

    • numpy.loads

    • numpy.core.numeric.load

    • numpy.core.numeric.loads

    • numpy.ma.loads, numpy.ma.dumps

    • numpy.ma.load, numpy.ma.dump - 这些函数在 Python 3 中以字符串作为参数调用时已经失败。

  • 除了元组以外的多维索引已被弃用。这意味着 ind = [slice(None), 0]; arr[ind] 中的索引列表应更改为元组,例如 ind = [slice(None), 0]; arr[tuple(ind)]arr[(slice(None), 0)]。此更改是必要的,以避免在诸如 arr[[[0, 1], [0, 1]]] 等表达式中产生歧义,该表达式目前被解释为 arr[array([0, 1]), array([0, 1])],未来将被解释为 arr[array([[0, 1], [0, 1]])]

  • 从以下子模块导入已被弃用,它们将在未来某个日期被移除。

    • numpy.testing.utils

    • numpy.testing.decorators

    • numpy.testing.nosetester

    • numpy.testing.noseclasses

    • numpy.core.umath_tests

  • numpy.sum 传递生成器现在已弃用。这是一个未文档化的行为,但它有效。以前,它会计算生成器表达式的和。将来,它可能会返回不同的结果。请改用 np.sum(np.from_iter(generator)) 或内置 Python sum

  • C-API 的用户在释放数组之前,应在任何设置了 WRITEBACKIFCOPY 标志的数组上调用 PyArrayResolveWriteBackIfCopyPyArray_DiscardWritebackIfCopy。如果需要时未调用这些函数,将发出弃用警告。

  • nditer 的用户应在迭代器操作数可写时将 nditer 对象用作上下文管理器,以便 numpy 可以管理写回语义,或者应调用 it.close()。否则在这些情况下可能会发出 RuntimeWarning

  • np.histogramnormed 参数,早在 1.6.0 中已弃用,现在会发出 DeprecationWarning

未来变化#

  • NumPy 1.16 将取消对 Python 3.4 的支持。

  • NumPy 1.17 将取消对 Python 2.7 的支持。

兼容性说明#

已编译的测试模块已重命名并设置为私有#

以下已编译的模块已重命名并设置为私有:

  • umath_tests -> _umath_tests

  • test_rational -> _rational_tests

  • multiarray_tests -> _multiarray_tests

  • struct_ufunc_test -> _struct_ufunc_tests

  • operand_flag_tests -> _operand_flag_tests

umath_tests 模块仍可用于向后兼容,但将在未来移除。

np.savez 返回的 NpzFile 现在是 collections.abc.Mapping#

这意味着它表现得像一个只读字典,并且有一个新的 .values() 方法和 len() 实现。

对于 Python 3,这意味着 .iteritems().iterkeys() 已被弃用,而 .keys().items() 现在返回视图而不是列表。这与 Python 2 和 Python 3 之间内置 dict 类型的变化一致。

在某些条件下,nditer 必须在上下文管理器中使用#

当使用带有 "writeonly""readwrite" 标志的 numpy.nditer 时,在某些情况下,nditer 实际上不会给您可写数组的视图。相反,它会给您一个副本,如果您对副本进行更改,nditer 稍后会将这些更改写回您的实际数组。目前,这种写回发生在数组对象被垃圾回收时,这使得这个 API 在 CPython 上容易出错,在 PyPy 上完全失效。因此,每当与可写数组一起使用时,nditer 现在应该用作上下文管理器,例如 with np.nditer(...) as it: ...。对于上下文管理器无法使用的情况(例如在生成器表达式中),您也可以显式调用 it.close()

Numpy 已改用 pytest 进行测试,取代 nose#

nose 的最后一个版本是 2015 年 6 月的 1.3.7,并且该工具的开发已结束,因此 NumPy 现在已改用 pytest。以前被一些下游项目使用的旧装饰器和 nose 工具仍然可用,但将不再维护。标准的测试工具,如 assert_almost_equal 等,不受此更改的影响,除了 nose 特定的函数 import_noseraises。这些函数未在 numpy 中使用,但为下游兼容性而保留。

Numpy 不再使用 __array_interface__ctypes 进行猴子补丁#

以前 numpy 会将 __array_interface__ 属性添加到 ctypes 中的所有整数类型。

np.ma.notmasked_contiguousnp.ma.flatnotmasked_contiguous 始终返回列表#

这是文档中描述的行为,但以前的结果可以是切片、None 或列表。

所有下游用户似乎都会检查 flatnotmasked_contiguousNone 结果并将其替换为 []。这些调用者将继续像以前一样工作。

np.squeeze 恢复了无法处理 axis 参数的对象的旧行为#

在版本 1.7.0 之前,numpy.squeeze 没有 axis 参数,并且默认情况下会删除所有空轴。引入 axis 参数使得可以有选择地压缩单个或多个空轴,但旧的 API 预期并未得到遵守,因为轴仍然可以有选择地(静默成功)从期望删除所有空轴的对象中删除。这种对期望旧行为的对象的空轴的静默、选择性删除已被修复,并恢复了旧行为。

非结构化 void 数组的 .item 方法现在返回字节对象#

.item 现在返回一个 bytes 对象,而不是缓冲区或字节数组。这可能会影响那些假设返回值是可变的(现在不再是)的代码。

copy.copycopy.deepcopy 不再将 masked 转换为数组#

由于 np.ma.masked 是一个只读标量,复制应该是一个无操作。这些函数现在与 np.copy() 的行为一致。

结构化数组的多字段索引仍将返回副本#

结构化数组的多字段索引返回视图而非副本的更改已推迟到 1.16。已引入新方法 numpy.lib.recfunctions.repack_fields 以帮助减轻此更改的影响,可用于编写与 numpy 1.15 和 1.16 兼容的代码。有关如何更新代码以适应此未来更改的更多信息,请参阅用户指南的“访问多个字段”部分。

C API 更改#

新增函数 npy_get_floatstatus_barriernpy_clear_floatstatus_barrier#

函数 npy_get_floatstatus_barriernpy_clear_floatstatus_barrier 已被添加,应取代 npy_get_floatstatus``和 ``npy_clear_status 函数。像 GCC 8.1 和 Clang 这样的优化编译器在使用之前的函数在 ufunc SIMD 函数中时会重新排列操作顺序,导致在检查浮点状态标志的操作运行之前就进行了检查。参见 #10339

PyArray_GetDTypeTransferFunction 的更改#

PyArray_GetDTypeTransferFunction 现在默认使用用户定义的 copyswapn / copyswap 进行用户定义的 dtype。如果这导致显著的性能损失,请考虑实现 copyswapn 以反映 PyArray_GetStridedCopyFn 的实现。参见 #10898

新特性#

为整数和对象类型添加了 np.gcdnp.lcm ufuncs#

它们分别计算最大公约数和最小公倍数。这些函数适用于所有 numpy 整数类型,以及内置的任意精度 Decimallong 类型。

支持 iOS 跨平台构建#

构建系统已修改,以支持 _PYTHON_HOST_PLATFORM 环境变量,该变量在 distutils 在一个平台上为另一个平台编译时使用。这使得为 iOS 目标编译 NumPy 成为可能。

这仅允许您一次为特定平台编译 NumPy。创建完整的 iOS 兼容 NumPy 包需要为 iOS 支持的 5 种架构(i386、x86_64、armv7、armv7s 和 arm64)进行构建,并将这 5 个编译好的构建产品组合成一个“胖”二进制文件。

np.intersect1d 添加了 return_indices 关键字#

新的关键字 return_indices 返回对应于共同元素的两个输入数组的索引。

np.quantilenp.nanquantile#

np.percentilenp.nanpercentile 类似,但接受 [0, 1] 范围内的分位数,而不是 [0, 100] 范围内的百分位数。np.percentile 现在是 np.quantile 的一个薄封装,多了一个除以 100 的步骤。

构建系统#

增加了对 64 位 RISC-V 架构的实验性支持。

改进#

np.einsum 更新#

同步 numpyopt_einsum 之间的 einsum 路径优化技术。特别是,由 @jcmgray 对 greedy 路径进行了许多增强。修复的问题完整列表如下:

  • 任意内存可以传递到 greedy 路径中。修复了 gh-11210。

  • 贪心路径已更新,包含更多动态规划思想,防止了大量重复(且昂贵)的调用,这些调用用于确定实际发生的对收缩。现在在数百个输入张量上只需几秒钟。对于矩阵乘积状态理论很有用。

  • 重新设计了 gh-11218 gh-10352 中发现的广播点错误捕获,使其在流程中更早一些。

  • 增强了 can_dot 功能,该功能以前遗漏了一个边界情况(gh-11308 的一部分)。

np.flip 可以在多个轴上操作#

np.flip 现在在其 axis 参数中接受 None 或整数元组。如果 axis 为 None,它将在所有轴上翻转。

histogramhistogramdd 函数已移至 np.lib.histograms#

这些最初位于 np.lib.function_base 中。它们仍然可以通过其无作用域的 np.histogram(dd) 名称访问,并且为了保持兼容性,它们在 np.lib.function_base.histogram(dd) 处被别名。

执行 from np.lib.function_base import * 的代码需要使用新位置进行更新,并且将来应考虑不使用 import *

当给定显式 bin 时,histogram 将接受 NaN 值#

以前,当尝试计算数据的有限范围时,它会失败。由于当显式给定 bin 时范围无论如何都会被忽略,因此此错误是不必要的。

请注意,在 NaN 值上调用 histogram 仍会引发处理 NaN 值时常见的 RuntimeWarning,这可以通过 errstate 照常抑制。

当给定明确的 bin 边缘时,histogram 适用于 datetime 类型#

日期、时间和时间差现在可以进行直方图处理。bin 边缘必须显式传递,并且尚未自动计算。

histogram 的“自动”估计器能更好地处理有限方差#

现在,IQR 为 0 不再导致 n_bins=1,而是选择的 bin 数量与此情况下的数据大小相关。

histogram`histogramdd 返回的边缘现在与数据浮点类型匹配#

当传入 np.float16np.float32np.longdouble 数据时,返回的边缘现在具有相同的 dtype。以前,histogram 仅在给定显式 bin 时才返回相同的类型,并且 histogram 无论输入如何都会生成 float64 bin。

histogramdd 允许在轴的子集中给定显式范围#

numpy.histogramddrange 参数现在可以包含 None 值,以指示对应轴的范围应从数据中计算。以前,这不能按轴指定。

histogramddhistogram2d 的 normed 参数已重命名#

这些参数现在被称为 density,这与 histogram 一致。旧的参数继续有效,但应优先使用新名称。

np.r_ 适用于 0 维数组,np.ma.mr_ 适用于 np.ma.masked#

传递给 r_mr_ 拼接辅助函数的 0 维数组现在被视为长度为 1 的数组。以前,传递这些数组会引发错误。因此,numpy.ma.mr_ 现在可以正确地作用于 masked 常量。

np.ptp 接受 keepdims 参数,并扩展了轴元组#

np.ptp (peak-to-peak) 现在可以在多个轴上工作,就像 np.maxnp.min 一样。

MaskedArray.astype 现在与 ndarray.astype 相同#

这意味着它接受所有相同的参数,使得为 ndarray 编写的更多代码也适用于掩码数组。

编译时启用 AVX2/AVX512#

更改 simd.inc.src 以允许在编译时使用 AVX2 或 AVX512。以前,即使代码的其余部分获得 AVX2,使用 -march=native 为 avx2(或 512)编译仍会使用 SSE 代码进行 simd 函数。

当接收到标量或 0 维输入时,nan_to_num 始终返回标量#

以前,对于整数标量输入会返回一个数组,这与浮点输入的行为以及 ufuncs 的一般行为不一致。对于所有类型的标量或 0 维输入,结果现在都是一个标量。

np.flatnonzero 适用于 NumPy 可转换类型#

np.flatnonzero 现在使用 np.ravel(a) 而不是 a.ravel(),因此它适用于列表、元组等。

np.interp 返回 numpy 标量而不是内置标量#

以前 np.interp(0.5, [0, 1], [10, 20]) 会返回一个 float,但现在它返回一个 np.float64 对象,这更接近其他函数的行为。

此外,不再支持 np.interp(object_array_0d, ...) 的特殊情况,因为 np.interp(object_array_nd) 从未受支持。

由于此更改,period 参数现在可以用于 0 维数组。

在 Python 2 中允许 dtype 字段名使用 Unicode#

以前,在 Python 2 中,np.dtype([(u'name', float)]) 会引发 TypeError,因为字段名只允许字节串。现在,任何 Unicode 字符串字段名都将使用 ascii 编码器进行编码,失败时会引发 UnicodeEncodeError

此更改使得使用 from __future__ import unicode_literals 编写 Python 2/3 兼容代码更容易,以前这会导致 Python 2 中的字符串字面量字段名引发 TypeError。

比较 ufuncs 接受 dtype=object,覆盖默认的 bool#

这允许符号类型的对象数组(它们重写 == 和其他运算符以返回表达式)通过 np.equal(a, b, dtype=object) 进行逐元素比较。

sort 函数接受 kind='stable'#

到目前为止,要对数据执行稳定排序,用户必须执行

>>> np.sort([5, 2, 6, 2, 1], kind='mergesort')
[1, 2, 2, 5, 6]

因为归并排序是 NumPy 中唯一可用的稳定排序算法。然而,使用 kind='mergesort' 并不能明确表示用户想要执行稳定排序,从而损害了可读性。

此更改允许用户指定 kind='stable',从而澄清意图。

不要为原地累加创建临时副本#

当 ufuncs 执行累加时,它们不再因为输入和输出之间的重叠而创建临时副本,也就是说,在累加结果存储到其位置之前,下一个累加的元素被添加,因此重叠是安全的。避免复制可以加快执行速度。

linalg.matrix_power 现在可以处理矩阵堆栈#

linalg 中的其他函数一样,matrix_power 现在可以处理维度大于 2 的数组,这些数组被视为矩阵堆栈。作为此更改的一部分,为了进一步提高一致性,第一个参数的名称已更改为 a(从 M ),并且非方阵的异常已更改为 LinAlgError(从 ValueError)。

多维数组的 random.permutation 性能提升#

permutation 对于所有输入数组维度都使用 random.shuffle 中的快速路径。以前快速路径仅用于一维数组。

广义 ufuncs 现在接受 axesaxiskeepdims 参数#

可以通过传入 axes 参数(一个包含特定轴索引的元组列表)来控制广义 ufunc 在哪些轴上操作。例如,对于适合矩阵乘法的签名 (i,j),(j,k)->(i,k),基本元素是二维矩阵,并且这些矩阵被视为存储在每个参数的最后两个轴中。对应的轴关键字将是 [(-2, -1), (-2, -1), (-2, -1)]。如果想使用前导维度,则会传入 [(0, 1), (0, 1), (0, 1)]

为简单起见,对于作用于一维数组(向量)的广义 ufunc,接受单个整数而不是单元素元组;对于所有输出均为标量的广义 ufunc,可以省略(空)输出元组。因此,对于适合内积的签名 (i),(i)->(),可以传入 axes=[0, 0] 以指示向量存储在两个输入参数的第一个维度中。

作为与归约类似的广义 ufunc(即作用于单个共享核心维度的广义 ufunc,如上面的内积示例)的快捷方式,可以传入 axis 参数。这等同于传入 axes,其中所有具有该核心维度的参数都具有相同的条目(例如,对于上面的示例,axes=[(axis,), (axis,)])。

此外,与归约类似,对于所有输入都具有相同数量的核心维度且输出没有核心维度的广义 ufunc,可以传入 keepdims 以在输出中保留一个大小为 1 的维度,从而允许与原始输入进行正确的广播。额外维度的位置可以通过 axes 控制。例如,对于内积示例,keepdims=True, axes=[-2, -2, -2] 将作用于内积示例,keepdims=True, axis=-2 将作用于输入参数的倒数第二个维度,并在输出中在该位置保留一个大小为 1 的维度。

float128 值现在在 ppc 系统上正确打印#

以前,在 ppc 上打印 float128 值存在错误,因为没有考虑这些系统上的特殊双精度浮点格式。现在 float128s 打印时具有正确的四舍五入和唯一性。

ppc 用户警告:如果 glibc 版本 <=2.23,您应该升级它,尤其是在使用 float128 时。在 ppc 上,这些版本中的 glibc 的 malloc 经常会使分配的内存未对齐,这在使用 float128 值时可能会使 numpy 崩溃。

新增 np.take_along_axisnp.put_along_axis 函数#

当在多维数组上使用时,argsortargminargmaxargpartition 返回的数组很难用作索引。take_along_axis 提供了一种使用这些索引在数组中查找值的简单方法,因此

np.take_along_axis(a, np.argsort(a, axis=axis), axis=axis)

np.sort(a, axis=axis)

np.put_along_axis 作为将值写入数组中这些索引的对偶操作。