transpuesta - multiplicacion de matrices python numpy
Comparando dos matrices numpy para la igualdad, elemento-sabio (4)
¿Cuál es la forma más sencilla de comparar dos matrices numpy para la igualdad (donde la igualdad se define como: A = B iff para todos los índices i: A[i] == B[i]
)?
Simplemente usando ==
me da una matriz booleana:
>>> numpy.array([1,1,1]) == numpy.array([1,1,1])
array([ True, True, True], dtype=bool)
¿Tengo que hacerlo and
los elementos de esta matriz para determinar si las matrices son iguales o existe una forma más simple de comparar?
La solución (A==B).all()
es muy clara, pero hay algunas funciones integradas para esta tarea. A saber, array_equal
, allclose
y array_equiv
.
(Aunque, algunas pruebas rápidas con timeit
parecen indicar que el método (A==B).all()
es el más rápido, lo cual es un poco peculiar, dado que tiene que asignar una matriz completamente nueva).
Si desea verificar si dos matrices tienen la misma shape
Y elements
, debe usar np.array_equal
ya que es el método recomendado en la documentación.
En lo que respecta al rendimiento, no espere que cualquier control de igualdad supere a otro, ya que no hay mucho espacio para optimizar
comparing two elements
. Solo por el bien, aún hice algunas pruebas.
import numpy as np
import timeit
A = np.zeros((300, 300, 3))
B = np.zeros((300, 300, 3))
C = np.ones((300, 300, 3))
timeit.timeit(stmt=''(A==B).all()'', setup=''from __main__ import A, B'', number=10**5)
timeit.timeit(stmt=''np.array_equal(A, B)'', setup=''from __main__ import A, B, np'', number=10**5)
timeit.timeit(stmt=''np.array_equiv(A, B)'', setup=''from __main__ import A, B, np'', number=10**5)
> 51.5094
> 52.555
> 52.761
Así que casi igual, no hay necesidad de hablar sobre la velocidad.
El (A==B).all()
comporta casi como el siguiente fragmento de código:
x = [1,2,3]
y = [1,2,3]
print all([x[i]==y[i] for i in range(len(x))])
> True
Vamos a medir el rendimiento usando la siguiente pieza de código.
import numpy as np
import time
exec_time0 = []
exec_time1 = []
exec_time2 = []
sizeOfArray = 5000
numOfIterations = 200
for i in xrange(numOfIterations):
A = np.random.randint(0,255,(sizeOfArray,sizeOfArray))
B = np.random.randint(0,255,(sizeOfArray,sizeOfArray))
a = time.clock()
res = (A==B).all()
b = time.clock()
exec_time0.append( b - a )
a = time.clock()
res = np.array_equal(A,B)
b = time.clock()
exec_time1.append( b - a )
a = time.clock()
res = np.array_equiv(A,B)
b = time.clock()
exec_time2.append( b - a )
print ''Method: (A==B).all(), '', np.mean(exec_time0)
print ''Method: np.array_equal(A,B),'', np.mean(exec_time1)
print ''Method: np.array_equiv(A,B),'', np.mean(exec_time2)
Salida
Method: (A==B).all(), 0.03031857
Method: np.array_equal(A,B), 0.030025185
Method: np.array_equiv(A,B), 0.030141515
De acuerdo con los resultados anteriores, los métodos numpy parecen ser más rápidos que la combinación del operador == y el método all () y al comparar los métodos numpy, el más rápido parece ser el método numpy.array_equal .
(A==B).all()
prueba si todos los valores de la matriz (A == B) son verdaderos.
Editar (a partir de la respuesta de dbaupp y el comentario de yoavram)
Se debe notar que:
- esta solución puede tener un comportamiento extraño en un caso particular: si
A
oB
están vacíos y el otro contiene un solo elemento, entonces devuelveTrue
. Por alguna razón, la comparaciónA==B
devuelve una matriz vacía, para la cual el operadorall
devuelveTrue
. - Otro riesgo es que si
A
yB
no tienen la misma forma y no son de gran escala, entonces este enfoque generará un error.
En conclusión, la solución que propuse es la estándar, creo, pero si tiene alguna duda sobre la forma A
y B
o simplemente quiere estar seguro: use una de las funciones especializadas:
np.array_equal(A,B) # test if same shape, same elements values
np.array_equiv(A,B) # test if broadcastable shape, same elements values
np.allclose(A,B,...) # test if same shape, elements have close enough values