Estoy buscando la forma más rápida de verificar la aparición de NaN ( np.nan
) en una matriz NumPy X
. np.isnan(X)
está fuera de discusión, ya que crea una matriz booleana de formas X.shape
, que es potencialmente gigantesca.
Lo intenté np.nan in X
, pero eso parece no funcionar porque np.nan != np.nan
. ¿Existe alguna forma rápida y eficiente en memoria de hacer esto?
(Para aquellos que preguntan "cuán gigantesco": no puedo decirlo. Esta es la validación de entrada para el código de la biblioteca).
scipy.sparse
matrices NumPy como entrada.Respuestas:
La solución de Ray es buena. Sin embargo, en mi máquina es aproximadamente 2.5 veces más rápido de usar
numpy.sum
en lugar denumpy.min
:A diferencia
min
,sum
no requiere ramificación, que en el hardware moderno tiende a ser bastante caro. Esta es probablemente la razón por la quesum
es más rápido.editar La prueba anterior se realizó con un solo NaN justo en el medio de la matriz.
Es interesante notar que
min
es más lento en presencia de NaN que en su ausencia. También parece volverse más lento a medida que los NaN se acercan al inicio de la matriz. Por otro lado,sum
el rendimiento parece constante independientemente de si hay NaN y dónde se encuentran:fuente
np.min
es más rápido cuando la matriz no contiene NaN, que es mi entrada esperada. Pero he decidido aceptar este de todos modos, porque atrapainf
yneginf
también.inf
o-inf
si la entrada contiene ambos, y tiene problemas si la entrada contiene valores grandes pero finitos que se desbordan cuando se suman.np.sum
sigue siendo un 30% más rápido quenp.min
.np.isnan(x).any(0)
es un poco más rápido quenp.sum
ynp.min
en mi máquina, aunque puede haber algún almacenamiento en caché no deseado.Creo que
np.isnan(np.min(X))
debería hacer lo que quiera.fuente
Incluso si existe una respuesta aceptada, me gustaría demostrar lo siguiente (con Python 2.7.2 y Numpy 1.6.0 en Vista):
Por lo tanto, la forma realmente eficiente podría depender en gran medida del sistema operativo. De todos modos el
dot(.)
basado parece ser el más estable.fuente
x
contiene valores grandes, y también quiero verificar inf.isfinite(.)
. Solo quería señalar la enorme brecha de rendimiento. Graciasmin
- osum
enfoques basados, que se ejecutan confinadas a un solo núcleo. Ergo, esa brecha de desempeño.Aquí hay dos enfoques generales:
nan
y tómeloany
.nan
s (likesum
) y verifique su resultado.Si bien el primer enfoque es ciertamente el más limpio, la gran optimización de algunas de las operaciones acumulativas (particularmente las que se ejecutan en BLAS, como
dot
) puede hacerlas bastante rápidas. Tenga en cuenta quedot
, al igual que algunas otras operaciones BLAS, son multiproceso en determinadas condiciones. Esto explica la diferencia de velocidad entre diferentes máquinas.fuente
usar cualquier()
if numpy.isnan(myarray).any()
numpy.isfinite quizás mejor que isnan para comprobar
if not np.isfinite(prop).all()
fuente
Si te sientes cómodo con numba permite crear un cortocircuito rápido (se detiene tan pronto como se encuentra un NaN) función:
Si no hay,
NaN
la función podría ser más lenta quenp.min
, creo que se debe a quenp.min
usa multiprocesamiento para matrices grandes:Pero en caso de que haya un NaN en la matriz, especialmente si su posición está en índices bajos, entonces es mucho más rápido:
Se pueden lograr resultados similares con Cython o una extensión de C, estos son un poco más complicados (o fácilmente disponibles como
bottleneck.anynan
) pero en última instancia hacen lo mismo que mianynan
función.fuente
Relacionado con esto está la cuestión de cómo encontrar la primera aparición de NaN. Esta es la forma más rápida de manejar eso que conozco:
fuente