python - How can I vectorize this triple-loop over 2d arrays in numpy? -
can eliminate python loops in computation:
result[i,j,k] = (x[i] * y[j] * z[k]).sum() where x[i], y[j], z[k] vectors of length n , x,y,z have first dimensions length a,b,c s.t. output shape (a,b,c) , each element sum of triple-product (element-wise).
i can down 3 1 loops (code below), stuck trying eliminate last loop.
if necessary make a=b=c (via small amount of padding).
# example 3 loops, 2 loops, 1 loop (testing omitted) n = 100 # more 100k in real problem = 2 # more 20 in real problem b = 3 # more 20 in real problem c = 4 # more 20 in real problem import numpy x = numpy.random.rand(a, n) y = numpy.random.rand(b, n) z = numpy.random.rand(c, n) # outputs of each variant result_slow = numpy.empty((a,b,c)) result_vec_c = numpy.empty((a,b,c)) result_vec_cb = numpy.empty((a,b,c)) # 3 nested loops in range(a): j in range(b): k in range(c): result_slow[i,j,k] = (x[i] * y[j] * z[k]).sum() # vectorize loop on c (2 nested loops) in range(a): j in range(b): result_vec_c[i,j,:] = (x[i] * y[j] * z).sum(axis=1) # vectorize 1 c , b (one loop) in range(a): result_vec_cb[i,:,:] = numpy.dot(x[i] * y, z.transpose()) numpy.testing.assert_almost_equal(result_slow, result_vec_c) numpy.testing.assert_almost_equal(result_slow, result_vec_cb)
if using numpy > 1.6, there awesome np.einsum function:
np.einsum('im,jm,km->ijk',x,y,z) which equivalent looped versions. i'm not sure how fair on efficiency once size of arrays in real problem (i'm getting segfault on machine, when move sizes). other solution prefer these sorts of problems re-writing method using cython.
Comments
Post a Comment