Это в основном сравнение с внешним равенством, сохраняющее первую из этих осей маски выровненной. Мы можем использовать matrix-multiplication
с идеей, что умножение матриц самих масок и их одновременных отрицательных версий приведет нас к этим внешним суммированиям равенства. Следовательно, для суммирования равенств просто выполните -
out = (~masksB).astype(int).dot(~masksA.T) + masksB.astype(int).dot(masksA.T)
В качестве альтернативы, получите версию int
и используйте ее, чтобы получить также отрицательную версию -
mB = masksB.astype(int)
out = (1-mB).dot(~masksA.T) + mB.dot(masksA.T)
Окончательный выводбудет out/float(M)
. Или мы можем заменить эти int
преобразования на float
, а затем разделить вывод на M
.
Синхронизация (с N вместо 1000) для получения суммирования равенства
# Setup
In [39]: np.random.seed(0)
...: N = 1000
...: M = 580
...: masksA = np.array(np.random.randint(0,2, size=(N,M)), dtype=np.bool)
...: masksB = np.array(np.random.randint(0,2, size=(N,M)), dtype=np.bool)
# Approach #1 with int dtype converison
In [40]: %timeit (~masksB).astype(int).dot(~masksA.T) + masksB.astype(int).dot(masksA.T)
1 loop, best of 3: 870 ms per loop
# Approach #1 with float dtype converison
In [41]: %timeit (~masksB).astype(float).dot(~masksA.T) + masksB.astype(float).dot(masksA.T)
10 loops, best of 3: 74 ms per loop
# Approach #2 with int dtype converison
In [42]: %%timeit
...: mB = masksB.astype(int)
...: out = (1-mB).dot(~masksA.T) + mB.dot(masksA.T)
1 loop, best of 3: 882 ms per loop
# Approach #2 with float dtype converison
In [43]: %%timeit
...: mB = masksB.astype(float)
...: out = (1-mB).dot(~masksA.T) + mB.dot(masksA.T)
10 loops, best of 3: 59.3 ms per loop
Таким образом, предпочтительным способом было бы использовать преобразование с плавающей точкой при втором подходеи разделите выходные данные на M
.
Используйте одно умножение матриц со суммированием
Так как суммы по существу равны int
числам, мы можем использоватьменьшая точность dtype для умножения матриц. Кроме того, еще одной идеей будет сложить исходные маски с их отрицательными версиями, а затем выполнить матричное умножение. Следовательно, для суммирования равенства мы бы имели -
m1 = np.hstack((masksA,~masksA))
m2 = np.hstack((masksB,~masksB))
out = m2.astype(np.float32).dot(m1.T)
Таймингс (такая же настройка, как и ранее) -
In [49]: %%timeit
...: m1 = np.hstack((masksA,~masksA))
...: m2 = np.hstack((masksB,~masksB))
...: out = m2.astype(np.float32).dot(m1.T)
10 loops, best of 3: 36.8 ms per loop