'Can numpy.tensordot or ufunc replace this nested for loop?
Note: I know this is very similar to Use numpy.tensordot to replace a nested loop , only that the actual instance we are working on seemed different( I need quadratic form caclculation) and I wasn't smart enough to extrapolate the discussion there, hence asking this question.
Objective: Make computational speed faster by replacing for loops with matrix calculation or/and univeral functions.
The problem:
#Toy example
def A(a):
return [[a,1,1],[1,1,1],[1,1,a**2]]
val = 0
for a in range(1,5):
for x in [ [1,1,1], [2,2,2], [3,3,3] ]:
val +=np.exp(-1* np.dot(np.dot(x,A(a)), x))
print(val)
In actual implementation, I have x as 9 dimensional vector ranging over 10**9 iterations, and a ranging over (50)**2 iterations, and it takes forever using this for loop? Any suggestions? I feel that tensordot seems most probable but I keep failing to get the result I want, hence asking. Since I'm a real beginner, it would really help if you could write out a sample code that I could directly apply... Thanks in advance.
Added: Upon further investigation, it does not necessarily seem to be that np.tensordot() is the fastest, so any solution other than for loops are welcome.(e.g. using np.einsum two times, combination of np.dot and np.einsum, etc. ) Thanks to @hpaulj , I know how to eliminate the z loop now , but I really want to solve the a loop as well...
Solution 1:[1]
The
In [155]: a=1
...: val=0
In [156]: for x in [ [1,1,1], [2,2,2], [3,3,3] ]:
...: val +=np.exp( np.dot(np.dot(x,A(a)), x))
...:
In [157]: val
Out[157]: 1.5060973145850306e+35
part can be replaced with
In [158]: X = np.array([ [1,1,1], [2,2,2], [3,3,3] ])
In [159]: np.exp(np.einsum('ki,ij,kj->k',X,A(a),X)).sum()
Out[159]: 1.5060973145850306e+35
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | hpaulj |