2012-01-28 25 views
12

Tengo un comportamiento extraño en mi código python relacionado con - y -=. Estoy escribiendo una descomposición QR usando numpy, y tienen la siguiente línea de código en un bucle doble:- vs - = operadores con numpy

v = v - r[i,j] * q[:,i] 

donde q y r son tanto numpy.array y v es un pedazo de otro numpy.array tomado como v = x[:,j].

El código anterior no funciona como se espera en todos los casos. Sin embargo, si realizo el siguiente cambio:

v -= r[i,j] * q[:,i] 

Entonces todo funciona a la perfección.

Tenía la impresión de que esas dos líneas deberían ser idénticas. Para probar si -= y _ = _ - estaban trabajando de manera diferente, he creado el siguiente fragmento

import numpy 

x = numpy.array(range(0,6)) 
y = numpy.array(range(0,6)) 

u = x[3:5] 
v = y[3:5] 

print u,v 

u = u - [1,1] 
v -= [1,1] 

print u,v 

que a su vez funciona como se espera, produciendo en ambos [2 3] [2 3] declaraciones de impresión.

Así que estoy completamente confundido por qué esas dos líneas funcionan de manera diferente. Lo único posible que se me ocurre es que a veces tengo que lidiar con números extremadamente pequeños (del orden de 10^-8 o menos) y hay algún problema de precisión en que -= es mejor? La primera línea se vuelve cada vez peor a medida que los elementos de x se hacen más pequeños.

Pido disculpas si hay otras publicaciones sobre este problema similar, no puedo buscar - y -= y no sé si hay términos correctos para estos además de asignación/operadores.

¡Gracias por cualquier ayuda!

+4

para referencia futura si desea buscar cosas como esta los nombres de '' -' y - = 'son [' __sub__'] [1] y [ '__isub__'] [2] respectivamente. Entonces: 'a = a - b' es equivalente a' a = a .__ sub __ (b) ' ' a - = b' es equivalente a 'a .__ isub __ (b)'. (a menos que __isub__ no esté definido, entonces vuelve a aparecer en el anterior) [1]: http://pyref.infogami.com/__add__ [2]: http://pyref.infogami.com/__iadd__ –

Respuesta

19

Cuando v es una porción, entonces v -= X y v = v - X producen resultados muy diferentes. Considere

>>> x = np.arange(6) 
>>> v = x[1:4] 
>>> v -= 1 
>>> v 
array([0, 1, 2]) 
>>> x 
array([0, 0, 1, 2, 4, 5]) 

donde v -= 1 actualiza la rebanada, y por lo tanto la matriz que se ve, en el lugar, vs.

>>> x = np.arange(6) 
>>> v = x[1:4] 
>>> v = v - 1 
>>> v 
array([0, 1, 2]) 
>>> x 
array([0, 1, 2, 3, 4, 5]) 

donde v = v - 1 restablece la variable v dejando intacta x. Para obtener el resultado anterior sin -=, que tendría que hacer

v[:] = v - 1 
+0

Gracias, esto aclara un montón de confusión para mí. –

11

Usted podría obtener resultados diferentes de x - y y x -= y si los tipos de datos de x y y difieren.

Por ejemplo:

import numpy as np 

x = np.array(range(0,6)) 
y = np.array(np.arange(0,3,0.5)) 

print x - y 
x -= y 
print x 

Esto muestra:

[ 0. 0.5 1. 1.5 2. 2.5] 
[0 0 1 1 2 2] 

puede valer la pena asegurarse de que sus matrices dtypes son exactamente como se espera (por ejemplo, usted no se está utilizando de forma inadvertida o número entero float32 matrices en lugar de float64), prestando especial atención a las matrices utilizadas en el lado izquierdo de -=.

+1

+1 incluso si resulta que esta no es la razón; Había pasado por alto esa posibilidad por completo, y no debería haberlo hecho. – DSM

4

+1 a las dos otras respuestas a estas preguntas. Cubren dos diferencias importantes entre = y -=, pero quiero resaltar una más. La mayoría de las veces x -= y es lo mismo que x[:] = x - y, pero no cuando x y y son segmentos de la misma matriz. Por ejemplo:

x = np.ones(10) 
y = np.ones(10) 

x[1:] += x[:-1] 
print x 
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.] 

y[1:] = y[1:] + y[:-1] 
print y 
[ 1. 2. 2. 2. 2. 2. 2. 2. 2. 2.] 
+0

Eso es increíblemente flojo. ¿Puedes explicar cómo se produce el primer resultado? –