def reduce_after_multiply(M1, M2):
    r, c = sp.sparse.find(M2.T)[:2]
IDs, start = np.unique(r, return_index=1)
stop = np.append(start[1:], c.size)
m, n = M1.shape[0], M2.shape[1]
out = np.zeros((m, n))
for iterID, i in enumerate(IDs):
    idx = c[start[iterID]:stop[iterID]]
mult = M1[:, (idx)] * M2.getcol(i).data
out[:, (i)] = np.max(mult, axis=1)
return out
SciPy — обобщение скалярного произведения по разреженной и плотной матрице