una que multiplicar multiplicacion matriz matrices libreria inversa determinant como calcular numpy

que - numpy: evite eficientemente los 0s al tomar log(matriz)



multiplicacion de matrices python numpy (6)

from numpy import * m = array([[1,0], [2,3]])

Me gustaría calcular el elemento log2(m) , pero solo en los lugares donde m no es 0. En esos lugares, me gustaría tener 0 como resultado.

Ahora estoy luchando contra

RuntimeWarning: divide by zero encountered in log2

Prueba 1: usando where

res = where(m != 0, log2(m), 0)

que me calcula el resultado correcto, pero todavía me registra un RuntimeWarning: divide by zero encountered in log2 . Parece que (y sintácticamente es bastante obvio) Numpy aún calcula log2(m) en la matriz completa y solo después, where selecciona los valores para mantener.

Me gustaría evitar esta advertencia.

Prueba 2: usando mascarillas

from numpy import ma res = ma.filled(log2(ma.masked_equal(m, 0)), 0)

Claro que si ocultas los ceros log2 que log2 se aplique a ellos, ¿no es así? Desafortunadamente no: aún tenemos RuntimeWarning: divide by zero encountered in log2 .

Aunque la matriz está enmascarada, log2 todavía parece aplicarse a todos los elementos.

¿Cómo puedo calcular de manera eficiente el registro de elementos de una matriz numpy sin recibir advertencias de división por cero?

  • Por supuesto, podría desactivar temporalmente el registro de estas advertencias utilizando seterr , pero eso no parece una solución limpia.
  • Y seguro, un doble para el bucle ayudaría a tratar los 0 en especial, pero anula la eficiencia de numpy.

¿Algunas ideas?


¿Qué pasa con lo siguiente?

from numpy import * m=array((-1.0,0.0,2.0)) p=m > 0.0 print ''positive='',p print m[p] res=zeros_like(m) res[p]=log(m[p]) print res


La solución de matriz enmascarada y la solución que desactiva la advertencia están bien. Por variedad, aquí hay otro que usa scipy.special.xlogy . np.sign(m) se proporciona como el argumento x , por lo que xlogy devuelve 0 donde np.sign(m) es 0. El resultado se divide por np.log(2) para obtener el logaritmo base-2.

In [4]: from scipy.special import xlogy In [5]: m = np.array([[1, 0], [2, 3]]) In [6]: xlogy(np.sign(m), m) / np.log(2) Out[6]: array([[ 0. , 0. ], [ 1. , 1.5849625]])


Otra opción es usar el parámetro where de los ufuncs de numpy :

m = np.array([[1., 0], [2, 3]]) res = np.log2(m, out=np.zeros_like(m), where=(m!=0))

No se RuntimeWarning y se introducen ceros donde no se calcula el registro.


Podemos usar matrices enmascaradas para esto:

>>> from numpy import * >>> m = array([[1,0], [2,3]]) >>> x = ma.log(m) >>> print x.filled(0) [[ 0. 0. ] [ 0.69314718 1.09861229]]


Puede usar algo como - m = np.clip(m, 1e-12, None) para evitar el error log (0). Esto establecerá el límite inferior a 1e-12 .


Simplemente deshabilite la advertencia para ese cálculo:

from numpy import errstate,isneginf,array m = array([[1,0],[2,3]]) with errstate(divide=''ignore''): res = log2(m)

Y luego puedes postprocesar el -inf si quieres:

res[isneginf(res)]=0

EDITAR: Puse aquí algunos comentarios sobre la otra opción, que está usando arreglos enmascarados, publicados en la otra respuesta. Debes optar por deshabilitar el error por dos razones:

1) El uso de matrices enmascaradas es mucho menos eficiente que deshabilitar momentáneamente el error, y usted pidió eficiencia.

2) Deshabilitar la advertencia específica de ''dividir por cero'' NO deshabilita el otro problema con el cálculo del registro de un número, que es una entrada negativa. La entrada negativa se captura como una advertencia de ''valor no válido'', y tendrá que lidiar con ella.

Por otro lado, el uso de matrices enmascaradas captura los dos errores de la misma manera y lo llevará a no notar un número negativo en la entrada. En otras palabras, un número negativo en la entrada se trata como un cero, y dará como resultado cero. Esto no es lo que pediste.

3) Como último punto y como opinión personal, deshabilitar la advertencia es muy legible, es obvio lo que está haciendo el código y lo hace más mantenible. En ese sentido, encuentro esta solución más limpia que luego usando arreglos enmascarados.