I have to calculate the Kronecker's product in the following loop:
import numpy as np
M=48
G=120
H=5
P=6
we=np.random.normal(size=(P,P,G))
qu=np.random.normal(size=(P,G))
f = np.random.normal(size=(H,G))
P, G = qu.shape
nu = np.full((P * H, 1), 0.0)
de = np.full((P * H, P * H), 0.0)
for g in range(G):
qu_g = qu[:, g].reshape((-1, 1))
f_g = f[:, g].reshape((-1, 1))
we_g = we[:, :, g]
nu += (qu_gt[:, None]*f_g[None, :]).reshape(P*H,1)
de += (we_g[:, None, :, None]*f_g.dot(f_g.T)[None, :, None, :]).reshape(P*H,P*H)
nu = nu.sum(axis=0)
de = de.sum(axis=0)
ga2 = np.linalg.solve(de, nu).reshape((P, H))
Notice that (qu_g[:, None]*f_g[None, :]).reshape(P*H,1)
is equivalent to np.kron(qu_g, f_g)
but faster thanks to broadcasting. Analgously for (we_g[:, None, :, None]*f_g.dot(f_g.T)[None, :, None, :]).reshape(P*H,P*H)
.
I would like to exploit numpy broadcasting to avoid the loop and speed up the process. What I mean is that my aim is to do everything at once exploiting the fact that, given a 3d array, numpy carries out the dot product to the last two dimensions using matmul
, such that one can avoid looping over the first dimension. I would like to exploit the same logic also for kron.
However, I cannot obtain the same results. My attempt for the nu
component:
(qu[:, None].transpose(2,0,1)*f[:, None].transpose(2,1,0)).reshape(G, P*H, 1)
does not give the same result. How can I proceed here?
Here's the solution I propose: