Scipy Minimize - Невозможно минимизировать целевую функцию
Я пытаюсь оптимизировать функцию, чтобы найти максимальное значение rev_tot
используя scipy свести к минимуму. Вот obj_data
это список вероятностей, prem
постоянная и inc
может принять любое реальное значение. Ниже приведен код, который я написал для целевой функции:
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
Я хочу найти inc
значение, которое минимизирует 1/rev_tot
(и таким образом максимизировать rev_tot
, Когда я звоню:
minimize(objective,x0,args=(prem,par),method='SLSQP')
функция работает, но solve.x
не показывает изменений в исходном значении. Я не могу понять, почему минимизация не происходит.
1 ответ
Ваша проблема в том, что решатель должен иметь дело с крошечными числами из-за вашего return 1/rev_tot
, Следовательно, изменения по оси x не очень хорошо отражаются в изменениях значений y и вычислителей, которые уже сходятся:
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()
Выход:
[2.]
Решение 1)
Различные решатели решают одни проблемы лучше, чем другие. Измените свой решатель на "Nelder-Mead". Выход:
[63.07910156]
Решение 2)
Увеличьте ваше возвращаемое значение с return 1000000/rev_tot
для решателя "SLSQP". Выход:
[63.07110511]