NumPy 1.17.0 发行说明#
此 NumPy 版本包含许多新功能,应能大幅提高其性能和实用性,请参阅下面的 Highlights 部分了解摘要. 支持的 Python 版本为 3.5-3.7,请注意已删除 Python 2.7. Python 3.8b2 应该可以使用已发布的源代码包,但不对未来做任何保证.
下游开发人员应使用 Cython >= 0.29.11 来支持 Python 3.8,并使用 OpenBLAS >= 3.7(目前尚未发布)来避免 Skylake 架构上的问题. PyPI 上的 NumPy wheels 是从 OpenBLAS 开发分支构建的,以避免这些问题.
亮点#
添加了一个新的可扩展
random模块,以及四个可选的 random number generators 和改进的种子,专为在并行进程中使用而设计. 当前可用的位生成器有 MT19937 , PCG64 , Philox 和 SFC64 .请参阅下面的“新功能”.NumPy 的
FFT实现已从 fftpack 更改为 pocketfft,从而实现了更快,更准确的转换,并更好地处理了素数长度的数据集. 请参阅下面的“改进”.新的基数排序和 timsort 排序方法. 目前无法选择将使用哪一个. 它们被硬连线到数据类型,并且当
stable或mergesort作为方法传递时使用. 请参阅下面的“改进”.现在默认可以覆盖 numpy 函数,请参阅下面的
__array_function__.
新函数#
numpy.errstate现在也是一个函数装饰器
弃用#
当传递 float 代替 int 时, numpy.polynomial 函数会发出警告#
以前,此模块中的函数会接受 float 值,前提是它们是积分值 ( 1.0 , 2.0 , 等).为了与 numpy 的其余部分保持一致,现在不建议这样做,将来会引发 TypeError .
类似地,传递像 0.5 这样的浮点数来代替整数现在将引发 TypeError ,而不是之前的 ValueError .
弃用 numpy.distutils.exec_command 和 temp_file_name#
这些功能的内部使用已重构,并且有更好的替代方案. 将 exec_command 替换为 subprocess.Popen ,将 temp_file_name 替换为 tempfile.mkstemp .
C-API 包装数组的可写标志#
当从 C-API 创建数组以包装指向数据的指针时,我们拥有的关于数据读写性质的唯一指示是在创建期间设置的 writeable 标志. 强制将标志设置为可写是危险的. 将来,将无法从 python 将可写标志切换为 True . 此弃用不应影响很多用户,因为以这种方式创建的数组在实践中非常罕见,并且仅通过 NumPy C-API 可用.
不应再在 0d 数组上调用 numpy.nonzero#
numpy.nonzero 在 0 维数组上的行为令人惊讶,导致对其的使用几乎总是错误的. 如果需要保留旧的行为,可以使用 nonzero(atleast_1d(arr)) 而不是 nonzero(arr) ,这样就不会发出警告. 在未来的版本中,很可能会引发 ValueError .
写入 numpy.broadcast_arrays 的结果会发出警告#
通常, numpy.broadcast_arrays 返回一个具有内部重叠的可写数组,这使得对其进行写入是不安全的. 未来版本会将 writeable 标志设置为 False ,并要求用户手动将其设置为 True ,如果他们确定这是他们想要做的. 现在,写入它会发出弃用警告,并提供将 writeable 标志设置为 True 的说明. 请注意,如果在设置标志之前检查它,会发现它已经是 True . 但是,像在未来版本中需要做的那样显式地设置它,会清除一个用于生成弃用警告的内部标志. 为了帮助缓解困惑,在访问 writeable 标志状态时会发出额外的 FutureWarning 以澄清这种矛盾.
请注意,对于 C 端缓冲协议,除非请求可写缓冲,否则此类数组将立即返回只读缓冲.如果请求可写缓冲,将给出警告.当使用 cython 时,应该使用 const 限定符与此类数组一起使用,以避免警告(例如 cdef const double[::1] view ).
未来的变化#
在未来的版本中,dtypes 中形状为 1 的字段不会被折叠为标量#
目前,指定为 [(name, dtype, 1)] 或 "1type" 的字段被解释为标量字段(即,与 [(name, dtype)] 或 [(name, dtype, ()] 相同). 现在会引发 FutureWarning; 在未来的版本中,它将被解释为 shape-(1,) 字段,即与 [(name, dtype, (1,))] 或 "(1,)type" 相同(与 [(name, dtype, n)] / "ntype" 与 n>1 一致,后者已经等同于 [(name, dtype, (n,)] / "(n,)type" ).
兼容性说明#
float16 次正规数舍入#
从不同的浮点精度转换到 float16 在某些极端情况下使用了不正确的舍入.这意味着在极少数情况下,次正规结果现在将被向上舍入而不是向下舍入,从而改变结果的最后一位(ULP).
使用 divmod 时的带符号零#
从 1.12.0 版本开始,当结果为零时,numpy 在使用 divmod 和 floor_divide 函数时错误地返回了一个负号的零. 例如:
>>> np.zeros(10)//1
array([-0., -0., -0., -0., -0., -0., -0., -0., -0., -0.])
在此版本中,结果正确地返回为正号零:
>>> np.zeros(10)//1
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
MaskedArray.mask 现在返回 mask 的视图,而不是 mask 本身#
返回 mask 本身是不安全的,因为它可以在适当的位置重塑,这将违反屏蔽数组代码的预期. mask 的行为现在与 data 一致,后者也返回一个视图.
如果需要,仍然可以使用 ._mask 访问底层 mask.包含 assert x.mask is not y.mask 或类似内容的测试需要更新.
不要在 numpy.frombuffer 中查找 __buffer__ 属性#
在 numpy.frombuffer 中查找 __buffer__ 属性是没有文档记录且不起作用的. 此代码已删除. 如果需要,请改用 frombuffer(memoryview(obj), ...) .
在 take , choose , put 中为内存重叠缓冲 out#
如果提供了这些函数的 out 参数,并且与其他参数有内存重叠,则现在会对其进行缓冲以避免依赖于顺序的行为.
加载时取消序列化需要显式选择加入#
函数 load 和 lib.format.read_array 接受一个 allow_pickle 关键字,现在默认为 False ,以响应 CVE-2019-6446 .
旧的 random 模块中随机数流的潜在变化#
由于将 log 应用于随机浮点数时存在错误,如果底层 MT19937 随机数流中生成了 0 ,则从 beta , binomial , laplace , logistic , logseries 或 multinomial 采样时,流可能会发生变化.发生这种情况的概率为 \(10^{53}\) 分之一,因此对于任何给定的种子,流发生变化的概率都非常小.如果在底层生成器中遇到 0 ,则现在将删除产生的错误值( numpy.inf 或 numpy.nan ).
i0 现在始终返回与输入具有相同形状的结果#
以前,输出被压缩,例如,仅具有单个元素的输入将导致返回数组标量,并且具有诸如 (10, 1) 之类的形状的输入将产生不会与输入进行广播的结果.
请注意,我们通常建议使用 SciPy 实现而不是 numpy 实现:它是一个用 C 编写的适当的 ufunc,并且速度快一个数量级以上.
can_cast 不再假定允许所有不安全的类型转换#
以前,对于几乎所有 casting='unsafe' 的输入,即使在无法进行类型转换的情况下,例如从结构化 dtype 到常规 dtype, can_cast 也返回 True .此问题已得到修复,使其与使用 .astype 方法的实际类型转换更加一致.
ndarray.flags.writeable 可以更频繁地切换为 true#
在极少数情况下,即使基础数组是可写的,也无法将数组从不可写切换为可写. 如果中间 ndarray.base 对象是可写的,则会发生这种情况. 以前,仅考虑最深层的基础对象来做出此决定. 但是,在极少数情况下,此对象没有必要的信息. 在这种情况下,始终不允许切换到可写. 现在已解决此问题.
C API 更改#
维度或步长输入参数现在通过 npy_intp const* 传递#
以前,这些函数参数被声明为更严格的 npy_intp* ,这阻止了调用者传递常量数据. 此更改向后兼容,但现在允许以下代码:
npy_intp const fixed_dims[] = {1, 2, 3};
// no longer complains that the const-qualifier is discarded
npy_intp size = PyArray_MultiplyList(fixed_dims, 3);
新特性#
具有可选择随机数生成器的新型可扩展 numpy.random 模块#
添加了一个新的可扩展 numpy.random 模块以及四个可选择的随机数生成器和改进的播种,专为在并行进程中使用而设计.当前可用的 Bit Generators 有 MT19937 , PCG64 , Philox 和 SFC64 . PCG64 是新的默认值,而 MT19937 则保留以实现向后兼容性.请注意,传统的 random 模块未更改,现在已冻结,您当前的结果不会更改.更多信息可以在 API change description 和 top-level view 文档中找到.
libFLAME#
支持使用 libFLAME 线性代数包作为 LAPACK 构建 NumPy,有关详细信息,请参见 libFLAME .
用户定义的 BLAS 检测顺序#
distutils 现在使用环境变量(逗号分隔且不区分大小写)来确定 BLAS 库的检测顺序. 默认情况下, NPY_BLAS_ORDER=mkl,blis,openblas,atlas,accelerate,blas . 但是,要强制使用 OpenBLAS,只需执行:
NPY_BLAS_ORDER=openblas python setup.py build
这会强制使用 OpenBLAS. 这可能对安装了 MKL 但希望尝试不同实现的用户有所帮助.
用户自定义的LAPACK检测顺序#
numpy.distutils 现在使用一个环境变量(逗号分隔且不区分大小写)来确定 LAPACK 库的检测顺序.默认情况下, NPY_LAPACK_ORDER=mkl,openblas,flame,atlas,accelerate,lapack .但是,要强制使用 OpenBLAS,只需执行以下操作:
NPY_LAPACK_ORDER=openblas python setup.py build
这会强制使用 OpenBLAS. 这可能对安装了 MKL 但希望尝试不同实现的用户有所帮助.
Timsort 和基数排序已经取代归并排序用于稳定排序#
基数排序和 timsort 都已实现,现在用于代替归并排序.由于需要保持向后兼容性,排序 kind 选项 "stable" 和 "mergesort" 已经互为别名,实际的排序实现取决于数组类型.基数排序用于 16 位或更小的整数类型,而 timsort 用于其余类型.Timsort 在包含已排序或接近排序数据的数据上具有改进的性能,并且在随机数据上像归并排序一样执行,并且需要 \(O(n/2)\) 的工作空间.有关 timsort 算法的详细信息,请访问 CPython listsort.txt .
packbits 和 unpackbits 接受一个 order 关键字#
order 关键字默认为 big ,并将相应地对位进行排序.对于 'order=big' ,3 将变为 [0, 0, 0, 0, 0, 0, 1, 1] ,对于 order=little ,则变为 [1, 1, 0, 0, 0, 0, 0, 0] .
unpackbits 现在接受一个 count 参数#
count 允许预先选择要解包的位数,而不是稍后重塑和选择子集,从而使 packbits 操作可逆,并减少解包的浪费.大于可用位数的计数会添加零填充.负计数会从末尾而不是从开头删除位.None 计数实现了解包所有内容的现有行为.
linalg.svd 和 linalg.pinv 在 Hermitian 输入上可以更快#
这些函数现在接受一个 hermitian 参数,与 1.14.0 中添加到 linalg.matrix_rank 的参数匹配.
现在支持两个 timedelta64 操作数的 divmod 运算#
divmod 运算符现在处理两个 timedelta64 操作数,类型签名为 mm->qm .
fromfile 现在接受一个 offset 参数#
此函数现在接受二进制文件的 offset 关键字参数,该参数指定距文件当前位置的偏移量(以字节为单位). 默认为 0 .
pad 的新模式 “empty”#
此模式将数组填充到所需的形状,而不初始化新条目.
浮点标量实现 as_integer_ratio 以匹配内置浮点数#
这返回一个 (分子, 分母) 对,可用于构造 fractions.Fraction .
结构化的 dtype 对象可以使用多个字段名称进行索引#
arr.dtype[['a', 'b']] 现在返回一个等价于 arr[['a', 'b']].dtype 的 dtype,与 arr.dtype['a'] == arr['a'].dtype 保持一致.
与使用字段列表索引的结构化数组的 dtype 一样,此 dtype 具有与原始 dtype 相同的 itemsize ,但仅保留字段的一个子集.
这意味着 arr[['a', 'b']] 和 arr.view(arr.dtype[['a', 'b']]) 是等价的.
.npy 文件支持 Unicode 字段名#
引入了新的 3.0 格式版本,该版本支持具有非 latin1 字段名称的结构化类型.在需要时会自动使用.
改进#
数组比较断言包括最大差异#
数组比较测试(如 testing.assert_allclose )中的错误消息现在除了之前的“不匹配”百分比之外,还包括“最大绝对差”和“最大相对差”.此信息使更新绝对和相对误差容限更容易.
用 pocketfft 库替换基于 fftpack 的 fft 模块#
两种实现都具有相同的祖先(Paul N. Swarztrauber 的 Fortran77 FFTPACK),但 pocketfft 包含额外的修改,可在某些情况下提高准确性和性能.对于包含大素数因子的 FFT 长度,pocketfft 使用 Bluestein 算法,该算法保持 \(O(N log N)\) 运行时间复杂度,而不是对于素数长度恶化为 \(O(N*N)\) .此外,具有近似素数长度的实值 FFT 的准确性得到了提高,并且与复值 FFT 相当.
进一步改进 numpy.ctypeslib 中的 ctypes 支持#
添加了一个新的 numpy.ctypeslib.as_ctypes_type 函数,该函数可用于将 dtype 转换为最佳猜测 ctypes 类型. 感谢这个新函数, numpy.ctypeslib.as_ctypes 现在支持更广泛的数组类型,包括结构,布尔值和非本机字节序的整数.
numpy.errstate 现在也是一个函数装饰器#
目前,如果你有一个像这样的函数:
def foo():
pass
你想把整个东西包装在 errstate 中,你必须像这样重写它:
def foo():
with np.errstate(...):
pass
但通过此更改,你可以这样做:
@np.errstate(...)
def foo():
pass
从而节省了一个缩进级别
numpy.exp 和 numpy.log 针对 float32 实现加速#
exp 和 log 的 float32 实现现在受益于在运行时检测到的 AVX2/AVX512 指令集. exp 的最大 ulp 误差为 2.52, log 的最大 ulp 误差为 3.83.
提高 numpy.pad 的性能#
对于大多数情况,通过使用预先分配的具有所需填充形状的数组而不是使用连接,提高了函数的性能.
numpy.interp 更可靠地处理无穷大#
Pathlib 支持 fromfile , tofile 和 ndarray.dump#
fromfile , ndarray.ndarray.tofile 和 ndarray.dump 现在支持 file / fid 参数的 pathlib.Path 类型.
针对 bool 和 int 类型的专用 isnan , isinf 和 isfinite ufuncs#
isfinite 支持 datetime64 和 timedelta64 类型#
以前, isfinite 曾经在使用这两种类型时引发 TypeError .
添加到 nan_to_num 的新关键字#
nan_to_num 现在接受关键字 nan , posinf 和 neginf ,允许用户定义分别替换 nan ,正和负 np.inf 值的值.
由分配的过大数组引起的 MemoryError 更加具有描述性#
通常,MemoryError 的原因是错误的广播,这会导致非常大且不正确的形状.错误的 message 现在包含此形状,以帮助诊断失败的原因.
floor , ceil 和 trunc 现在支持内建的魔法方法#
这些 ufunc 现在在对象数组上调用 __floor__ , __ceil__ 和 __trunc__ 方法,使其与 decimal.Decimal 和 fractions.Fraction 对象兼容.
quantile 现在可以在 fraction.Fraction 和 decimal.Decimal 对象上工作#
总的来说,这可以更优雅地处理对象数组,并在使用精确算术类型时避免浮点运算.
支持 matmul 中的对象数组#
现在可以将 matmul (或 @ 运算符) 与对象数组一起使用. 例如,现在可以执行以下操作:
from fractions import Fraction
a = np.array([[Fraction(1, 2), Fraction(1, 3)], [Fraction(1, 3), Fraction(1, 2)]])
b = a @ a
变更#
median 和 percentile 系列函数不再警告 nan#
numpy.median , numpy.percentile 和 numpy.quantile 过去在遇到 nan 时会发出 RuntimeWarning . 由于它们返回 nan 值,因此警告是多余的,已被删除.
timedelta64 % 0 行为调整为返回 NaT#
两个 np.timedelta64 操作数进行模运算时,如果被零除,现在返回 NaT ,而不是返回零.
NumPy 函数现在始终支持使用 __array_function__ 进行重载#
如 NEP 18 中所述,NumPy 现在始终检查 __array_function__ 方法,以实现对非 NumPy 数组上的 NumPy 函数的重载. 如果设置了适当的环境变量,则该功能可用于使用 NumPy 1.16 进行测试,但现在始终启用.
lib.recfunctions.structured_to_unstructured 不会压缩单字段视图#
以前, structured_to_unstructured(arr[['a']]) 会产生一个挤压的结果,这与 structured_to_unstructured(arr[['a', b']]) 不一致.这是偶然的.可以使用 structured_to_unstructured(arr[['a']]).squeeze(axis=-1) 更简单地说 arr['a'] 来保持旧的行为.
clip 现在在底层使用 ufunc#
这意味着通过 descr->f->fastclip 在 C 中为自定义 dtype 注册 clip 函数已被弃用 - 它们应该使用 ufunc 注册机制,附加到 np.core.umath.clip ufunc.
这也意味着 clip 接受 where 和 casting 参数,并且可以使用 __array_ufunc__ 重写.
此更改的一个结果是,旧 clip 的某些行为已被弃用:
将
nan传递给表示 “不剪裁” 作为界限之一或两个.这在所有情况下都不起作用,并且可以通过传递适当符号的无穷大来更好地处理.当传递
out参数时,默认使用 “不安全” 转换. 显式使用casting="unsafe"将消除此警告.
此外,还有一些具有行为更改的极端情况:
填充
max < min已更改为在 dtypes 之间更加一致,但不应依赖它.标量
min和max参与提升规则,就像它们在所有其他 ufuncs 中一样.
__array_interface__ 偏移现在可以按文档工作#
该接口可能使用一个被错误忽略的 offset 值.
savez 中的 Pickle 协议设置为 3 用于 force zip64 标志#
savez 没有使用 force_zip64 标志,这限制了存档的大小为 2GB. 但是使用该标志需要我们使用 pickle 协议 3 来写入 object 数组. 使用的协议已提升到 3,这意味着该存档将无法被 Python2 读取.
使用不存在的字段索引结构化数组会引发 KeyError 而不是 ValueError#
结构化类型上的 arr['bad_field'] 引发 KeyError ,以与 dict['bad_field'] 保持一致.