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
模組,以及四個可選的 隨機數字產生器 和改良的種子設定,專為平行處理程序設計。目前可用的位元產生器為 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
這樣的 float 取代整數現在將引發 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 提供。
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 版本開始,當結果為零時,使用 divmod
和 floor_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), ...)
。
在 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}\) 分之 1,因此對於任何給定的種子,串流變更的機率都極小。如果在底層產生器中遇到 0
,則現在會捨棄產生的不正確值(numpy.inf
或 numpy.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
模組,以及四個可選的隨機數字產生器和改良的種子設定,專為平行處理程序設計。目前可用的 位元產生器 為 MT19937、PCG64、Philox 和 SFC64。PCG64
是新的預設值,而 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 中找到。
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
以符合內建 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.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
現在支援 pathlib.Path
類型作為 file
/fid
參數。
針對布林值和整數類型的特殊化 isnan
、isinf
和 isfinite
ufuncs#
布林值和整數類型無法儲存 nan
和 inf
值,這讓我們能夠提供特殊化的 ufuncs,其速度比先前的方法快達 250 倍。
isfinite
支援 datetime64
和 timedelta64
類型#
先前,isfinite
用於在這兩種類型上使用時會引發 TypeError。
新增至 nan_to_num
的新關鍵字#
nan_to_num
現在接受關鍵字 nan
、posinf
和 neginf
,允許使用者定義要分別取代 nan
、正和負 np.inf
值的值。
由分配過大的陣列引起的 MemoryError 更具描述性#
MemoryError 的原因通常是不正確的廣播,這會導致非常大且不正確的形狀。錯誤訊息現在包含此形狀,以幫助診斷失敗原因。
floor
、ceil
和 trunc
現在尊重內建魔術方法#
這些 ufuncs 現在在物件陣列上呼叫時會呼叫 __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#
這表示在 C 中為自訂 dtype 註冊 clip 函數(透過 descr->f->fastclip
)已被棄用 - 它們應該改為使用 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
值。
savez
中的 Pickle 協定針對 force zip64
旗標設定為 3#
savez
未使用 force_zip64
旗標,這將封存檔案的大小限制為 2GB。但是使用該旗標需要我們使用 pickle 協定 3 來寫入 object
陣列。使用的協定已升級到 3,這表示 Python 2 將無法讀取該封存檔案。
使用不存在的欄位索引的結構化陣列引發 KeyError
而不是 ValueError
#
結構化類型上的 arr['bad_field']
引發 KeyError
,為了與 dict['bad_field']
保持一致性。