NumPy 1.17.0 发行说明#
此 NumPy 版本包含许多新功能,这些功能应大大提高其性能和实用性,请参阅下面的"亮点"部分以获取摘要.支持的 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 将 writeable 标志切换为 True . 此弃用不应影响很多用户,因为以这种方式创建的数组在实践中非常罕见,并且只能通过 NumPy C-API 获得.
numpy.nonzero 不应再在 0d 数组上调用#
numpy.nonzero 在 0d 数组上的行为令人惊讶,使其使用几乎总是错误的. 如果打算使用旧的行为,则可以通过使用 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 中的 Shape-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 的行为现在与 data 一致,后者也返回一个视图.
如果需要,仍然可以使用 ._mask 访问底层掩码.包含 assert x.mask is not y.mask 或类似内容的测试需要更新.
不要在 numpy.frombuffer 中查找 __buffer__ 属性#
在 numpy.frombuffer 中查找 __buffer__ 属性是未记录且无效的.此代码已删除.如果需要,请改用 frombuffer(memoryview(obj), ...) .
out 在 take , choose , put 中针对内存重叠进行缓冲#
如果提供了这些函数的 out 参数并且与其他参数存在内存重叠,则现在对其进行缓冲以避免依赖于顺序的行为.
加载时 Unpickling 需要显式选择加入#
函数 load 和 lib.format.read_array 采用一个 allow_pickle 关键字,该关键字现在默认为 False ,以响应 CVE-2019-6446 .
旧随机模块中随机流的潜在变化#
由于在将 log 应用于随机浮点数时存在错误,因此如果基础 MT19937 随机流中生成 0 ,则从 beta , binomial , laplace , logistic , logseries 或 multinomial 采样时,流可能会发生变化. 有 \(10^{53}\) 分之 1 的可能性会发生这种情况,因此对于任何给定的种子,流发生变化的概率极小.如果在底层生成器中遇到 0 ,则现在将丢弃生成的不正确的值( numpy.inf 或 numpy.nan ).
i0 现在总是返回与输入形状相同的结果#
以前,输出被压缩了,例如,仅具有单个元素的输入将导致返回数组标量,并且具有诸如 (10, 1) 之类的形状的输入将产生不会针对输入进行广播的结果.
请注意,我们通常建议使用 SciPy 实现而不是 numpy 实现:它是一个用 C 编写的合适的 ufunc,并且速度快了一个数量级以上.
can_cast 不再假定允许所有不安全的强制转换#
以前, can_cast 对于几乎所有 casting='unsafe' 的输入都返回 True ,即使对于无法进行强制转换的情况,例如从结构化 dtype 到常规 dtype.这已得到修复,使其与实际使用(例如, .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 参数,与 1.14.0 中添加到 linalg.matrix_rank 的参数匹配.
现在支持对两个 timedelta64 操作数执行 divmod 运算#
divmod 运算符现在处理两个 timedelta64 操作数,类型签名为 mm->qm .
fromfile 现在接受一个 offset 参数#
此函数现在接受一个 offset 关键字参数,用于二进制文件,它指定从文件当前位置的偏移量(以字节为单位).默认为 0 .
pad 的新模式 “empty”]#
此模式将数组填充到所需的形状,而不初始化新条目.
浮点标量实现 as_integer_ratio 以匹配内置 float#
这返回一个 (numerator, denominator) 对,可用于构造 fractions.Fraction .
结构化的 dtype 对象可以用多个字段名进行索引#
arr.dtype[['a', 'b']] 现在返回一个等效于 arr[['a', 'b']].dtype 的 dtype,以便与 arr.dtype['a'] == arr['a'].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 值的 value.
由分配的过大数组引起的 MemoryError 更加具有描述性#
通常,MemoryError 的原因是错误的广播,这会导致非常大且不正确的形状. 错误消息现在包含此形状,以帮助诊断失败的原因.
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__ 进行覆盖#
NumPy 现在始终检查 __array_function__ 方法,以实现对非 NumPy 数组上的 NumPy 函数的覆盖,如 NEP 18 中所述. 如果设置了适当的环境变量,则该功能已可在 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已更改为在不同的 dtype 之间更加一致,但不应依赖.标量
min和max参与提升规则,就像它们在所有其他 ufunc 中一样.
__array_interface__ offset 现在按照文档工作#
该接口可能使用了一个被错误忽略的 offset 值.
savez 中的 Pickle 协议设置为 3 以用于 force zip64 标志#
savez 没有使用 force_zip64 标志,这会将归档文件的大小限制为 2GB. 但是使用该标志需要我们使用 pickle 协议 3 来写入 object 数组. 使用的协议已提升到 3,这意味着该归档文件将无法被 Python2 读取.
使用不存在的字段索引的结构化数组会引发 KeyError 而不是 ValueError#
结构化类型的 arr['bad_field'] 会引发 KeyError ,以与 dict['bad_field'] 保持一致.