Самый быстрый способ вставить одну матрицу в другую с помощью индексов.
Для иллюстрации с вашим внешним продуктом:
In [94]: a = np.array(((1,0,2,0)))
In [95]: idx = np.where(a>0)[0]
In [96]: idx
Out[96]: array([0, 2])
In [97]: a1 = a[idx]
Внешний продукт массива конденсатов:
In [98]: a2 = a1[:,None]*a1
In [99]: a2
Out[99]:
array([[1, 2],
[2, 4]])
Настройте массив результатов и используйте блочную индексацию, чтобы определить, куда идут значения a2
:
In [100]: res = np.zeros((4,4),int)
In [101]: res[idx[:,None], idx] = a2
In [102]: res
Out[102]:
array([[1, 0, 2, 0],
[0, 0, 0, 0],
[2, 0, 4, 0],
[0, 0, 0, 0]])
Прямой внешний вид неконденсированного массива:
In [103]: a[:,None]*a
Out[103]:
array([[1, 0, 2, 0],
[0, 0, 0, 0],
[2, 0, 4, 0],
[0, 0, 0, 0]])
In [104]: np.outer(a,a)
Out[104]:
array([[1, 0, 2, 0],
[0, 0, 0, 0],
[2, 0, 4, 0],
[0, 0, 0, 0]])
Если a
было 2d, (n, 1), это внешнее можно записать как np.dot(a.T,a)
.dot
включает в себя сумму, в данном случае измерения размера 1.
Я думаю, a
пришлось бы довольно разреженным, чтобы извлечь выгоду из этой дополнительной работы по индексированию.Я обнаружил, что с разреженными разреженными матрицами разреженность порядка 1% дает преимущество в скорости, даже если матрицы предварительно изготовлены.
In [105]: from scipy import sparse
In [106]: A = sparse.csr_matrix(a)
In [107]: A
Out[107]:
<1x4 sparse matrix of type '<class 'numpy.int64'>'
with 2 stored elements in Compressed Sparse Row format>
In [108]: A.A
Out[108]: array([[1, 0, 2, 0]], dtype=int64)
In [109]: A.T*A # sparse matrix product, dot
Out[109]:
<4x4 sparse matrix of type '<class 'numpy.int64'>'
with 4 stored elements in Compressed Sparse Column format>
In [110]: _.A
Out[110]:
array([[1, 0, 2, 0],
[0, 0, 0, 0],
[2, 0, 4, 0],
[0, 0, 0, 0]], dtype=int64)