numpy.reciprocal devuelve valores diferentes cuando se llama repetidamente

Tengo una matriz ssh_sum :

 >>> ssh_sum array([[ 0., 2., 1., 0., 0., 0.], [ 0., 0., 1., 2., 0., 0.], [ 0., 0., 0., 1., 0., 2.]]) 

Quería calcular los valores recíprocos de los elementos en esta matriz. Numpy devuelve valores diferentes cuando llamo np.reciprocal repetidamente:

 >>> ssh_sum array([[ 0., 2., 1., 0., 0., 0.], [ 0., 0., 1., 2., 0., 0.], [ 0., 0., 0., 1., 0., 2.]]) >>> np.reciprocal(ssh_sum, where=(ssh_sum > 0.)) array([[ 6.90326535e-310, 5.00000000e-001, 1.00000000e+000, 0.00000000e+000, 1.07034283e-296, 1.33666925e+241], [ 4.74783847e-309, 1.45260789e-296, 1.00000000e+000, 5.00000000e-001, 2.13436228e-287, -3.13188338e-294], [ 4.85105226e-309, 1.08690709e+171, 4.09521901e+149, 1.00000000e+000, 2.82730247e-311, 5.00000000e-001]]) >>> np.reciprocal(ssh_sum, where=(ssh_sum > 0.)) array([[ inf, 0.5, 1. , inf, inf, inf], [ inf, inf, 1. , 0.5, inf, inf], [ inf, inf, inf, 1. , inf, 0.5]]) >>> np.reciprocal(ssh_sum, where=(ssh_sum > 0.)) array([[ 6.90326535e-310, 5.00000000e-001, 1.00000000e+000, 0.00000000e+000, 1.07034283e-296, 1.33666925e+241], [ 4.74783847e-309, 1.45260789e-296, 1.00000000e+000, 5.00000000e-001, 2.13436228e-287, -3.13188338e-294], [ 4.85105226e-309, 1.08690709e+171, 4.09521901e+149, 1.00000000e+000, 2.82730247e-311, 5.00000000e-001]]) >>> np.reciprocal(ssh_sum, where=(ssh_sum > 0.)) array([[ inf, 0.5, 1. , inf, inf, inf], [ inf, inf, 1. , 0.5, inf, inf], [ inf, inf, inf, 1. , inf, 0.5]]) 

¿Alguna idea de lo que está pasando aquí? Estoy usando Python 3.4.5 y numpy 1.13.3.

No es solo reciprocal ; el problema ocurre con cualquier uso del argumento where . He podido reproducir el problema con la twig maestra de numpy ( np.__version__ is '1.15.0.dev0+c093997' ), con funciones como abs , sign , add , subtract , etc.

Si lees atentamente las cadenas de documentación de los “ufuncs” numpy y las interpretas correctamente, verás que el comportamiento no es un error. Aquí están las descripciones relevantes de la numpy.reciprocal numpy.reciprocal:

 out : ndarray, None, or tuple of ndarray and None, optional A location into which the result is stored. If provided, it must have a shape that the inputs broadcast to. If not provided or `None`, a freshly-allocated array is returned. A tuple (possible only as a keyword argument) must have length equal to the number of outputs. where : array_like, optional Values of True indicate to calculate the ufunc at that position, values of False indicate to leave the value in the output alone. 

Tenga en cuenta, en particular:

  • where dice “los valores de Falso indican dejar el valor solo en la salida”.
  • out dice “Si no se proporciona o None , se devuelve una matriz recién asignada”.

No proporcionó un argumento de out , por lo que su llamada se asigna a reciprocal . Los contenidos de esta matriz no están inicializados; la matriz contiene lo que sea que esté en la memoria asignada. Cuando usa el argumento where , solo las posiciones en la salida where es verdadera son valores asignados. Las posiciones donde where está Falso no se tocan, por lo que contienen cualquier cosa aleatoria que estuviera allí cuando se asignó la matriz. Para la salida de punto flotante, el material aleatorio en la salida podría ser 0.0 , 4.85105226e-309 , o cualquier otro valor aleatorio.

Para usar el argumento where lo desea, también debe proporcionar su propio argumento de out , inicializado con los valores que desea en la salida where es Falso. En tu caso, deberías pasar una serie de ceros:

 In [84]: ssh_sum Out[84]: array([[0., 2., 1., 0., 0., 0.], [0., 0., 1., 2., 0., 0.], [0., 0., 0., 1., 0., 2.]]) In [85]: out = np.zeros_like(ssh_sum) In [86]: np.reciprocal(ssh_sum, where=ssh_sum > 0.0, out=out) Out[86]: array([[0. , 0.5, 1. , 0. , 0. , 0. ], [0. , 0. , 1. , 0.5, 0. , 0. ], [0. , 0. , 0. , 1. , 0. , 0.5]]) In [87]: out Out[87]: array([[0. , 0.5, 1. , 0. , 0. , 0. ], [0. , 0. , 1. , 0.5, 0. , 0. ], [0. , 0. , 0. , 1. , 0. , 0.5]])