I have a simple non linear objective function as followed. I want to maximize the total number of leads, with the leads
function being the leads for one of the df
rows and total_leads
being the optimization function:
def leads(x, feats):
a, b, c = feats
return a * x + b * np.sqrt(x) + c
def total_leads(spend_list, regress_features):
return -sum([leads(x,y) for x,y in zip(spend_list,regress_features)])
def max_budget(spends, max_spend):
# Needs to be positive to not violate constraint
return max_spend - sum(spends)
Here is the code to run the optimization.
reg_feats = [tuple(x) for x in df[list('abc')].values]
max_spend = 280000
min_spend = max_spend * 0.02
# List of (minbound,maxbound) row
bounds = [(min(min_spend,max_spend),max_spend) for max_spend in df['Max_spend']]
x0 = np.mean(bounds, axis=1)
constraints = {'type':'ineq','fun':max_budget,'args':(max_spend,)}
result = minimize(total_leads,x0,args=(reg_feats,),constraints=constraints,method='SLSQP',bounds=bounds,options={'maxiter': 10**5})
df =' Max_spend a b c
0 4459 0.001600 -0.050592 0.271046
1 6798 0.006000 -0.115749 -0.873647
2 18248 -0.000261 0.155548 -4.936540
3 7818 0.000571 -0.042275 0.688899
4 22419 -0.001117 0.581695 -13.277250
5 3643 0.001767 -0.065073 0.524264
6 51592 0.008957 -0.563969 6.754103
7 13179 0.000770 -0.075454 1.544488
8 16650 0.000256 0.004385 -0.391338
9 5994 0.007731 0.165316 1.010207
10 14070 0.019119 -0.442078 3.811875'
When I optimize this function, I get a result which is clearly not optimal. The budget is not fully used and not every variable is at its upper/lower bound. I know this function is a local optimizer, however the global optimizers don't seem to return results in a reasonable amount of time.
I also don't need a global optimum, just looking for a decent local optimum.
It seems that having x0 = np.max(bounds, axis=1)
instead of x0 = np.mean(bounds, axis=1)
works well in this case.