NumPy에서 NaN에 대한 빠른 확인
NaN 발생 여부를 가장 빠르게 확인할 수 있는 방법을 찾고 있습니다(np.nan
에서 ) NumPy 배열표 니다됩시로▁)다.X
.np.isnan(X)
합니다.X.shape
잠재적으로 거대할 수도 있습니다.
나는 노력했다.np.nan in X
하지만 그것은 작동하지 않는 것처럼 보입니다 왜냐하면np.nan != np.nan
빠르고 메모리 효율적인 방법이 있습니까?
("얼마나 거대한가"라고 묻는 사람들에게:나는 건지 모르겠네.라이브러리 코드에 대한 입력 유효성 검사입니다.)
레이의 해결책은 좋습니다.하지만, 내 기계에서는 대신 사용하는 것이 약 2.5배 더 빠릅니다.numpy.min
:
In [13]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 244 us per loop
In [14]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 97.3 us per loop
와는과 다르게 .min
,sum
분기가 필요하지 않습니다. 현대 하드웨어에서는 상당히 비싼 경향이 있습니다.이것이 아마도 이유일 것입니다.sum
더 빠릅니다.
edit 위의 테스트는 단일 NaN을 배열 중앙에 배치하여 수행되었습니다.
흥미로운 것은.min
NaN이 있을 때는 없을 때보다 느립니다.또한 NaN이 배열의 시작에 가까워질수록 속도가 느려지는 것으로 보입니다. 에반면은,sum
한 것으로 .:NaNaN의 경우 NaN을 지원합니다.
In [40]: x = np.random.rand(100000)
In [41]: %timeit np.isnan(np.min(x))
10000 loops, best of 3: 153 us per loop
In [42]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.9 us per loop
In [43]: x[50000] = np.nan
In [44]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 239 us per loop
In [45]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.8 us per loop
In [46]: x[0] = np.nan
In [47]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 326 us per loop
In [48]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.9 us per loop
생각합니다np.isnan(np.min(X))
당신이 원하는 것을 해야 합니다.
여기에는 두 가지 일반적인 접근 방식이 있습니다.
- 에서 다에대각어항확인목이레음한▁check▁each 확인합니다.
nan
그리고 테이크any
. - 보하는일누작적용업을 보존하는 합니다.
nan
요)sum
및합니다. 및 결과를 확인합니다.
첫 번째 접근 방식이 확실히 가장 깨끗하지만, 일부 누적 작업(특히 BLAS에서 실행되는 작업)의 강력한 최적화는 다음과 같습니다.dot
를 사용하면 수 는 그것들을 꽤 빠르게 만들 수 있습니다.:dot
다른 일부 BLAS 작업과 마찬가지로, 특정 조건에서 멀티 스레드화됩니다.이것은 서로 다른 기계 간의 속도 차이를 설명합니다.
import numpy as np
import perfplot
def min(a):
return np.isnan(np.min(a))
def sum(a):
return np.isnan(np.sum(a))
def dot(a):
return np.isnan(np.dot(a, a))
def any(a):
return np.any(np.isnan(a))
def einsum(a):
return np.isnan(np.einsum("i->", a))
b = perfplot.bench(
setup=np.random.rand,
kernels=[min, sum, dot, any, einsum],
n_range=[2 ** k for k in range(25)],
xlabel="len(a)",
)
b.save("out.png")
b.show()
승인된 답변이 있더라도 다음을 시연해 보겠습니다(Vista의 Python 2.7.2 및 Numpy 1.6.0 사용).
In []: x= rand(1e5)
In []: %timeit isnan(x.min())
10000 loops, best of 3: 200 us per loop
In []: %timeit isnan(x.sum())
10000 loops, best of 3: 169 us per loop
In []: %timeit isnan(dot(x, x))
10000 loops, best of 3: 134 us per loop
In []: x[5e4]= NaN
In []: %timeit isnan(x.min())
100 loops, best of 3: 4.47 ms per loop
In []: %timeit isnan(x.sum())
100 loops, best of 3: 6.44 ms per loop
In []: %timeit isnan(dot(x, x))
10000 loops, best of 3: 138 us per loop
따라서 정말 효율적인 방법은 운영 체제에 크게 의존할 수 있습니다. ㅠㅠㅠdot(.)
기반이 가장 안정적인 것 같습니다.
Numba에 익숙하다면 빠른 단락(NaN이 발견되는 즉시 중지) 기능을 만들 수 있습니다.
import numba as nb
import math
@nb.njit
def anynan(array):
array = array.ravel()
for i in range(array.size):
if math.isnan(array[i]):
return True
return False
없는 NaN
는 기이실더느수있습다니릴로제보다 수 .np.min
제생에각 때문인 것 같습니다.np.min
대규모 어레이에 멀티프로세싱을 사용합니다.
import numpy as np
array = np.random.random(2000000)
%timeit anynan(array) # 100 loops, best of 3: 2.21 ms per loop
%timeit np.isnan(array.sum()) # 100 loops, best of 3: 4.45 ms per loop
%timeit np.isnan(array.min()) # 1000 loops, best of 3: 1.64 ms per loop
그러나 배열에 NaN이 있는 경우, 특히 위치가 낮은 인덱스일 경우 훨씬 더 빠릅니다.
array = np.random.random(2000000)
array[100] = np.nan
%timeit anynan(array) # 1000000 loops, best of 3: 1.93 µs per loop
%timeit np.isnan(array.sum()) # 100 loops, best of 3: 4.57 ms per loop
%timeit np.isnan(array.min()) # 1000 loops, best of 3: 1.65 ms per loop
Cython 또는 C 확장으로 유사한 결과를 얻을 수 있습니다. 이것들은 조금 더 복잡합니다(또는 쉽게 사용할 수 있습니다). 하지만 궁극적으로 제 것과 동일하게 합니다.anynan
기능.
.any를 사용합니다.
if numpy.isnan(myarray).any()
numpy.isfinite는 확인을 위해 nan보다 더 나을 수 있습니다.
if not np.isfinite(prop).all()
이와 관련하여 NaN의 첫 발생을 어떻게 찾을 것인가에 대한 문제가 있습니다.이것이 제가 알고 있는 가장 빠른 처리 방법입니다.
index = next((i for (i,n) in enumerate(iterable) if n!=n), None)
@nico-schlömer와 @mseifert의 답변을 추가하여 numba-test의 성능을 계산했습니다.has_nan
전체 배열을 구문 분석하는 일부 함수와 비교하여 초기 중지를 사용합니다.
내 시스템에서 nan이 없는 어레이의 경우 ~10^4 요소에 대해 손익분기점이 발생합니다.
import perfplot
import numpy as np
import numba
import math
def min(a):
return np.isnan(np.min(a))
def dot(a):
return np.isnan(np.dot(a, a))
def einsum(a):
return np.isnan(np.einsum("i->", a))
@numba.njit
def has_nan(a):
for i in range(a.size - 1):
if math.isnan(a[i]):
return True
return False
def array_with_missing_values(n, p):
""" Return array of size n, p : nans ( % of array length )
Ex : n=1e6, p=1 : 1e4 nan assigned at random positions """
a = np.random.rand(n)
p = np.random.randint(0, len(a), int(p*len(a)/100))
a[p] = np.nan
return a
#%%
perfplot.show(
setup=lambda n: array_with_missing_values(n, 0),
kernels=[min, dot, has_nan],
n_range=[2 ** k for k in range(20)],
logx=True,
logy=True,
xlabel="len(a)",
)
배열에 nans가 있으면 어떻게 됩니까?저는 어레이의 나노 커버리지의 영향을 조사했습니다.
길이가 1,000,000인 배열의 경우,has_nan
배열에 ~10^-3%의 nans(따라서 ~10nans)가 있는 경우 더 나은 옵션이 됩니다.
#%%
N = 1000000 # 100000
perfplot.show(
setup=lambda p: array_with_missing_values(N, p),
kernels=[min, dot, has_nan],
n_range=np.array([2 ** k for k in range(20)]) / 2**20 * 0.01,
logy=True,
xlabel=f"% of nan in array (N = {N})",
)
의 어레이에 애리케에대어의가가 있는 nan
그 다음에 고당없는것을찾있고습다니그신럼은그, 리럼▁and▁without.has_nan
최선의 방법입니다. 기타;dot
최선의 선택인 것 같습니다.
언급URL : https://stackoverflow.com/questions/6736590/fast-check-for-nan-in-numpy
'programing' 카테고리의 다른 글
pip 요구 사항 파일을 사용하여 패키지를 제거하고 설치하려면 어떻게 해야 합니까? (0) | 2023.07.18 |
---|---|
Android API 버전을 프로그래밍 방식으로 검색하는 중 (0) | 2023.07.18 |
Python(또는 불변 데이터 유형)에서 튜플이 필요한 이유는 무엇입니까? (0) | 2023.07.18 |
Matlab의 tic 및 toc 함수에 해당하는 파이썬은 무엇입니까? (0) | 2023.07.18 |
하위 항목에 값이 포함되어 있는지 여부를 Firebase 쿼리 (0) | 2023.07.18 |