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 模組,以及四個可選的 隨機數字產生器 和改良的種子設定,專為平行處理程序設計。目前可用的位元產生器為 MT19937PCG64PhiloxSFC64。請參閱下方的「新功能」章節。

  • NumPy 的 FFT 實作已從 fftpack 變更為 pocketfft,從而實現更快速、更準確的轉換,並能更好地處理質數長度的資料集。請參閱下方的「改進」章節。

  • 新的基數排序和 timsort 排序方法。目前無法選擇要使用哪一種。它們硬編碼到資料類型中,並在將 stablemergesort 作為方法傳遞時使用。請參閱下方的「改進」章節。

  • 現在預設可以覆寫 numpy 函數,請參閱下方的 __array_function__

新函數#

棄用#

當傳遞 float 取代 int 時,numpy.polynomial 函數會發出警告#

先前,此模組中的函數會接受 float 值,前提是它們是整數(1.02.0 等)。為了與 numpy 的其餘部分保持一致,現在已棄用這樣做,未來將引發 TypeError

同樣地,傳遞像 0.5 這樣的 float 取代整數現在將引發 TypeError,而不是先前的 ValueError

棄用 numpy.distutils.exec_commandtemp_file_name#

這些函數的內部使用方式已重構,並且有更好的替代方案。請將 exec_command 替換為 subprocess.Popen,並將 temp_file_name 替換為 tempfile.mkstemp

C-API 包裝陣列的可寫入標誌#

當從 C-API 建立陣列以包裝指向資料的指標時,我們擁有的關於資料讀寫性質的唯一指示是在建立期間設定的 writeable 標誌。強制將標誌設為可寫入是很危險的。未來將無法從 python 將可寫入標誌切換為 True。此棄用不應影響許多使用者,因為以這種方式建立的陣列在實務上非常罕見,並且僅透過 NumPy C-API 提供。

numpy.nonzero 不應再於 0 維陣列上呼叫#

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;在未來的版本中,它將被解釋為形狀為 (1,) 的欄位,即與 [(name, dtype, (1,))]'(1,)type' 相同(與 n>1[(name, dtype, n)] / 'ntype' 一致,後者已經等同於 [(name, dtype, (n,)] / '(n,)type')。

相容性注意事項#

float16 次常態捨入#

在某些邊緣情況下,從不同的浮點精度轉換為 float16 會使用不正確的捨入。這表示在極少數情況下,次常態結果現在將向上捨入而不是向下捨入,從而更改結果的最後一位 (ULP)。

使用 divmod 時的帶號零#

1.12.0 版本開始,當結果為零時,使用 divmodfloor_divide 函數時,numpy 錯誤地傳回了帶負號的零。例如

>>> 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), ...)

takechooseput 中,out 會針對記憶體重疊進行緩衝處理#

如果為這些函數提供了 out 引數,並且它與其他引數有記憶體重疊,則現在會對其進行緩衝處理,以避免與順序相關的行為。

載入時還原序列化需要明確選擇加入#

函數 loadlib.format.read_array 採用 allow_pickle 關鍵字,現在預設值為 False,以回應 CVE-2019-6446

舊 random 模組中隨機串流的潛在變更#

由於將 log 應用於隨機浮點數時存在錯誤,因此如果底層 MT19937 隨機串流中產生 0,則從 betabinomiallaplacelogisticlogseriesmultinomial 採樣時,串流可能會變更。發生這種情況的機率為 \(10^{53}\) 分之 1,因此對於任何給定的種子,串流變更的機率都極小。如果在底層產生器中遇到 0,則現在會捨棄產生的不正確值(numpy.infnumpy.nan)。

i0 現在始終傳回與輸入形狀相同的結果#

先前,輸出被壓縮,因此,例如,只有單一元素的輸入會導致傳回陣列純量,而形狀如 (10, 1) 的輸入會產生不會與輸入廣播的結果。

請注意,我們通常建議使用 SciPy 實作而不是 numpy 實作:它是一個以 C 語言編寫的正確 ufunc,速度快了一個數量級以上。

can_cast 不再假設允許所有不安全的轉換#

先前,對於 casting='unsafe'can_cast 幾乎對所有輸入都傳回 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 模組,以及四個可選的隨機數字產生器和改良的種子設定,專為平行處理程序設計。目前可用的 位元產生器MT19937PCG64PhiloxSFC64PCG64 是新的預設值,而 MT19937 則保留以實現向後相容性。請注意,舊版 random 模組保持不變,現在已凍結,您目前的結果不會變更。更多資訊請參閱 API 變更說明頂層 檢視 文件。

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 和基數排序已取代 mergesort 以進行穩定排序#

基數排序和 timsort 都已實作,現在取代 mergesort 使用。由於需要保持向後相容性,排序 kind 選項 'stable''mergesort' 已成為彼此的別名,實際的排序實作取決於陣列類型。基數排序用於 16 位元或更小的整數類型,而 timsort 用於其餘類型。Timsort 在包含已排序或近乎排序資料的資料上具有改進的效能,並且在隨機資料上的效能與 mergesort 類似,並且需要 \(O(n/2)\) 工作空間。timsort 演算法的詳細資訊可在 CPython listsort.txt 中找到。

packbitsunpackbits 接受 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.svdlinalg.pinv 在 hermitian 輸入上可以更快#

這些函數現在接受 hermitian 引數,與 1.14.0 版本中新增至 linalg.matrix_rank 的引數相符。

現在支援兩個 timedelta64 運算元的 divmod 運算#

divmod 運算子現在處理兩個 timedelta64 運算元,類型簽名為 mm->qm

fromfile 現在接受 offset 引數#

此函數現在採用二進位檔案的 offset 關鍵字引數,該引數指定從檔案目前位置的偏移量(以位元組為單位)。預設值為 0

pad 的新模式「empty」#

此模式將陣列填充到所需的形狀,而無需初始化新條目。

浮點純量實作 as_integer_ratio 以符合內建 float#

這會傳回 (分子, 分母) 對,可用於建構 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.expnumpy.log 加速 float32 實作#

explog 的 float32 實作現在受益於在運行時偵測到的 AVX2/AVX512 指令集。exp 的最大 ulp 誤差為 2.52,而 log 的最大 ulp 誤差為 3.83。

改善 numpy.pad 的效能#

對於大多數情況,此函數的效能已透過填入具有所需填充形狀的預先分配陣列,而不是使用串聯來改善。

numpy.interp 更穩健地處理無限值#

在某些情況下,interp 先前會回傳 nan,現在它會回傳適當的無限值。

Pathlib 支援 fromfiletofilendarray.dump#

fromfilendarray.ndarray.tofilendarray.dump 現在支援 pathlib.Path 類型作為 file/fid 參數。

針對布林值和整數類型的特殊化 isnanisinfisfinite ufuncs#

布林值和整數類型無法儲存 naninf 值,這讓我們能夠提供特殊化的 ufuncs,其速度比先前的方法快達 250 倍。

isfinite 支援 datetime64timedelta64 類型#

先前,isfinite 用於在這兩種類型上使用時會引發 TypeError

新增至 nan_to_num 的新關鍵字#

nan_to_num 現在接受關鍵字 nanposinfneginf,允許使用者定義要分別取代 nan、正和負 np.inf 值的值。

由分配過大的陣列引起的 MemoryError 更具描述性#

MemoryError 的原因通常是不正確的廣播,這會導致非常大且不正確的形狀。錯誤訊息現在包含此形狀,以幫助診斷失敗原因。

floorceiltrunc 現在尊重內建魔術方法#

這些 ufuncs 現在在物件陣列上呼叫時會呼叫 __floor____ceil____trunc__ 方法,使其與 decimal.Decimalfractions.Fraction 物件相容。

quantile 現在適用於 fraction.Fractiondecimal.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

變更#

medianpercentile 系列函數不再警告 nan#

numpy.mediannumpy.percentilenumpy.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#

這表示在 C 中為自訂 dtype 註冊 clip 函數(透過 descr->f->fastclip)已被棄用 - 它們應該改為使用 ufunc 註冊機制,附加到 np.core.umath.clip ufunc。

這也表示 clip 接受 wherecasting 引數,並且可以使用 __array_ufunc__ 覆寫。

此變更的一個後果是舊 clip 的某些行為已被棄用

  • nan 作為一個或兩個邊界傳遞以表示「不剪裁」。無論如何,這在所有情況下都不起作用,並且可以透過傳遞適當符號的無限值來更好地處理。

  • 當傳遞 out 引數時,預設使用「不安全」的轉換。明確使用 casting="unsafe" 將會消除此警告。

此外,還有一些邊角案例的行為變更

  • 填充 max < min 已變更為在 dtype 之間更一致,但不應依賴它。

  • 純量 minmax 參與促銷規則,就像它們在所有其他 ufunc 中一樣。

__array_interface__ 偏移量現在如文件所述運作#

介面可能會使用錯誤地被忽略的 offset 值。

savez 中的 Pickle 協定針對 force zip64 旗標設定為 3#

savez 未使用 force_zip64 旗標,這將封存檔案的大小限制為 2GB。但是使用該旗標需要我們使用 pickle 協定 3 來寫入 object 陣列。使用的協定已升級到 3,這表示 Python 2 將無法讀取該封存檔案。

使用不存在的欄位索引的結構化陣列引發 KeyError 而不是 ValueError#

結構化類型上的 arr['bad_field'] 引發 KeyError,為了與 dict['bad_field'] 保持一致性。