Estou procurando a maneira mais rápida de verificar a ocorrência de NaN ( np.nan
) em uma matriz NumPy X
. np.isnan(X)
está fora de questão, uma vez que cria uma matriz booleana de forma X.shape
, que é potencialmente gigantesca.
Eu tentei np.nan in X
, mas isso parece não funcionar porque np.nan != np.nan
. Existe uma maneira rápida e eficiente de memória de fazer isso?
(Para aqueles que perguntariam "quão gigantesco": não sei dizer. Esta é a validação de entrada para o código da biblioteca.)
scipy.sparse
matrizes NumPy como entrada.Respostas:
A solução de Ray é boa. No entanto, na minha máquina, é cerca de 2,5 vezes mais rápido de usar
numpy.sum
no lugar denumpy.min
:Ao contrário
min
,sum
não requer ramificação, o que em hardware moderno tende a ser muito caro. Este é provavelmente o motivo pelo qualsum
é mais rápido.editar O teste acima foi executado com um único NaN bem no meio do array.
É interessante notar que
min
é mais lento na presença de NaNs do que em sua ausência. Ele também parece ficar mais lento conforme os NaNs se aproximam do início do array. Por outro lado,sum
a taxa de transferência de parece constante, independentemente de haver NaNs e de onde eles estão localizados:fonte
np.min
é mais rápido quando a matriz não contém NaNs, que é minha entrada esperada. Mas decidi aceitar este de qualquer maneira, porque pegainf
eneginf
também.inf
ou-inf
se a entrada contiver ambos, e terá problemas se a entrada contiver valores grandes, mas finitos, que transbordam quando somados.np.sum
ainda é cerca de 30% mais rápido do que onp.min
.np.isnan(x).any(0)
é um pouco mais rápido do quenp.sum
enp.min
na minha máquina, embora possa haver algum cache indesejado.Eu acho que
np.isnan(np.min(X))
deveria fazer o que você quiser.fonte
Mesmo que haja uma resposta aceita, gostaria de demonstrar o seguinte (com Python 2.7.2 e Numpy 1.6.0 no Vista):
Portanto, a maneira realmente eficiente pode depender muito do sistema operacional. De qualquer forma,
dot(.)
parece ser o mais estável.fonte
x
contém grandes valores, e também quero verificar se há inf.isfinite(.)
. Eu só queria apontar a enorme lacuna de desempenho. Obrigadomin
- ou -sum
, que funcionam confinadas a um único núcleo. Portanto, essa lacuna de desempenho.Existem duas abordagens gerais aqui:
nan
e pegueany
.nan
s (comosum
) e verifique seu resultado.Embora a primeira abordagem seja certamente a mais limpa, a otimização pesada de algumas das operações cumulativas (particularmente as que são executadas no BLAS, como
dot
) pode torná-las bastante rápidas. Observe quedot
, como algumas outras operações BLAS, são multithread sob certas condições. Isso explica a diferença de velocidade entre diferentes máquinas.fonte
use .any ()
if numpy.isnan(myarray).any()
numpy.isfinite talvez seja melhor do que isnan para verificar
if not np.isfinite(prop).all()
fonte
Se você está confortável com numba permite criar uma função de curto-circuito rápido (para assim que um NaN for encontrado):
Se não houver nenhuma,
NaN
a função pode realmente ser mais lenta do quenp.min
, acho que é porquenp.min
usa multiprocessamento para grandes matrizes:Mas, caso haja um NaN na matriz, especialmente se sua posição estiver em índices baixos, é muito mais rápido:
Resultados semelhantes podem ser alcançados com Cython ou uma extensão C, eles são um pouco mais complicados (ou facilmente disponíveis como
bottleneck.anynan
), mas no final das contas fazem o mesmo que minhaanynan
função.fonte
Relacionado a isso está a questão de como encontrar a primeira ocorrência de NaN. Esta é a maneira mais rápida de lidar com isso que eu conheço:
fonte