问题
I am trying to optimise a function to find max value of rev_tot
using scipy minimise. Here obj_data
is a list of probabilities, prem
is a constant and inc
can take any real value. Following is the code I have written for the objective function :
import numpy as np
import pandas as pd
import scipy
from scipy.optimize import minimize
def objective(x,*args):
prem = args[0]
prob = args[1]
inc = x[0]
rev_tot = 0
rev = 0
del_p = 0.2*(1-np.exp(-2*(1-np.exp(-inc/400))))
for i in range(len(prob)):
rev = (prob[i]*(1+del_p)*prem) - inc
rev_tot = rev_tot + rev
return 1/rev_tot
prem = 3300
par = [0.9,0.1,0.5,0.4]
x0 = np.array([3]) # initial guess
solve = minimize(objective,x0,args=(prem,par),method='SLSQP')
solve.x
I want to find the inc
value which will minimize 1/rev_tot
(and thus maximising rev_tot
.
When I call:
minimize(objective,x0,args=(prem,par),method='SLSQP')
the function runs, but solve.x
shows no change in initial value. I am unable to figure out why the minimisation is not happening.
回答1:
Your problem is that the solver has to deal with tiny numbers due to your return 1/rev_tot
. Hence changes over the x-axis are not well reflected in changes in y-values and the solver estimates that it has already converged:
import numpy as np
import pandas as pd
import scipy
from scipy.optimize import minimize
def objective(x,*args):
prem = args[0]
prob = args[1]
inc = x[0]
rev_tot = 0
rev = 0
del_p = 0.2*(1-np.exp(-2*(1-np.exp(-inc/400))))
for i in range(len(prob)):
rev = (prob[i]*(1+del_p)*prem) - inc
rev_tot = rev_tot + rev
return 1/rev_tot
prem = 3300
par = [0.9,0.1,0.5,0.4]
x0 = np.array([2]) # initial guess
solve = minimize(objective,x0,args=(prem,par),method='SLSQP')
x_min = solve.x
print(x_min)
#plot your function to visualize the outcome
x_func = np.linspace(1, 100, 1000)
y_func = []
for item in x_func:
y_func.append((objective(np.asarray([item]), prem, par)))
y_min = objective(np.asarray([x_min]), prem, par)
plt.plot(x_func, y_func)
plt.plot(x_min, y_min, "ro")
plt.show()
Output:
[2.]
Solution 1)
Different solvers manage certain problems better than others. Change your solver to "Nelder-Mead". Output:
[63.07910156]
Solution 2)
Scale up your return value with return 1000000/rev_tot
for solver "SLSQP". Output:
[63.07110511]
来源:https://stackoverflow.com/questions/51459467/scipy-minimize-unable-to-minimize-objective-function