I have a simple optimization problem in python which I need to re-run quite often (more than 10,000 times).
Most of the calculation can be done with numpy and the n-dimensional arrays quite efficient, however, when it comes to the optimization I am lost, since I have to switch to scipy.optimize.minimize.
Is there a method to run the optimization at once?
Currently I am looping through each line - see code below:
#%% imports
import numpy as np
from scipy import optimize
import time
#%% functions
def square(x, a, cov):
return (x-a).dot(cov).dot(x-a)
def minimization(args):
f, x, a, cov, beta, bnds = args
con_beta = {'type': 'eq', 'fun': lambda x, beta: np.sum(x*beta) - 1, 'jac': lambda x, beta: beta, 'args': (beta, ) }
res = optimize.minimize(f, x, bounds=bnds, method='SLSQP', args=(a, cov), constraints = con_beta)
return res.x
#%% initialize data
numberOfRuns = 260 * 100
numberOfAssets = 4
corr = np.ones((numberOfAssets,numberOfAssets))*0.8 + np.eye(numberOfAssets)*0.2
cov = (np.eye(numberOfAssets)*0.15).dot(corr).dot(np.eye(numberOfAssets)*0.15)
mu = np.zeros(numberOfAssets)
cov_n = np.zeros((numberOfRuns, numberOfAssets, numberOfAssets))
bm_n = np.zeros((numberOfRuns, numberOfAssets))
guess_n = np.ones((numberOfRuns, numberOfAssets))/(numberOfAssets-1)
bm_n[:,0] = 1
guess_n[:,0] = 0
bnds = [(0, None) for _ in range(numberOfAssets)]
bnds[0] = (0,0)
for i in range(numberOfRuns):
cov_n[i,:,:] = np.cov(np.random.multivariate_normal(mu, cov/260, 260).T)*260
beta_n = cov_n[:,0,:]/cov_n[:,0,0][:,np.newaxis]
#%% Run 1
tic = time.time()
for i in range(numberOfRuns):
res = minimization((square, guess_n[i,:], bm_n[i,:], cov_n[i,:,:], beta_n[i,:], bnds))
toc= time.time()
tictoc1 = toc - tic
print(tictoc1) #21.678 seconds
#%% Run 2
tic = time.time()
args = [(square, guess_n[i,:], bm_n[i,:], cov_n[i,:,:], bnds) for i in range(numberOfRuns)]
p = Pool(4)
res = p.map(minimization, args)
toc = time.time()
tictoc2 = toc - tic
print(toc - tic) #~11 seconds
#%% The End
Is there a more elegant and efficient way instead of looping through??
PS: I have tried to use "Pool", however this "just" halfes the time - still the same problem with the loop.