У меня есть простая проблема оптимизации, которая с некоторыми указанными c данными заставляет scipy.optimize.minimize игнорировать аргумент tol
. Из документации , tol
определяет «допуск для завершения», то есть максимальную ошибку, принятую для целевой функции, в моем понимании (я ошибаюсь?). Однако в следующем рабочем примере, когда, например, tol
установлено равным 0,1 или другими небольшими числами, оптимизация заканчивается сообщением «Оптимизация успешно завершена», даже когда целевая функция> tol
. Это ошибка в методе Сципи или я что-то здесь неправильно понимаю?
Проблема оптимизации: мне нужно сделать линейную комбинацию var1
и var2
, которые являются двумя временными рядами, масштабируя их по параметрам Btd
и Bta
. Мне нужно, чтобы среднее значение линейной комбинации приближалось к целевому значению Target
, скаляру. Поэтому я просто минимизирую абсолютную разницу между np.mean(Btd*var1 + Bta*var2)
и Target
. Ограничения заключаются в том, что коэффициенты масштабирования должны быть> 0, а отношение средних значений np.mean(Btd*var1)/np.mean(Bta*var2)
должно приближаться к функции gi/(1-gi)
, где gi
- скаляр в интервале [0,1].
Воспроизводимый код:
import numpy as np
import scipy.optimize as opt
# The data that exactly reproduce the error:
time = np.arange(1979,2011)
var2=np.array([ 88.95705521, 74.5398773 , 72.08588957, 65.64417178,
50. , 72.39263804, 77.3006135 , 72.08588957,
64.41717791, 96.62576687, 69.93865031, 84.96932515,
86.50306748, 82.20858896, 80.98159509, 73.00613497,
66.25766871, 67.48466258, 79.75460123, 65.64417178,
70.24539877, 84.66257669, 76.3803681 , 83.74233129,
83.74233129, 78.2208589 , 88.03680982, 87.73006135,
100. , 71.16564417, 73.6196319 , 85.58282209])
var1=np.array([300. , 420.89552239, 333.58208955, 355.97014925,
376.11940299, 510.44776119, 420.89552239, 434.32835821,
333.58208955, 394.02985075, 523.88059701, 411.94029851,
353.73134328, 434.32835821, 355.97014925, 398.50746269,
476.86567164, 371.64179104, 445.52238806, 544.02985075,
416.41791045, 427.6119403 , 541.79104478, 579.85074627,
429.85074627, 414.17910448, 420.89552239, 528.35820896,
577.6119403 , 490.29850746, 600. , 454.47761194])
X=np.transpose([var1, var2])
# Global parameters
Target = 3.0
gi = 0.7
# This model is a simple linear combination of the two time series.
def MyModel(modelparams, X, gi):
Bta, Btd = modelparams
Eta = Bta*X[:,0]
Etd = Btd*X[:,1]
Etot = Eta + Etd
return Etot, Eta, Etd
# Objective function
def Obj(modelparams):
Bta, Bdt = modelparams
Etot, Eta, Etd = MyModel([Bta, Bdt], X, gi)
return abs(np.mean(Etot)-Target)
# Ratio constraint
def Ratio(modelparams):
import numpy as np
Bta, Btd = modelparams
Etot, Eta, Etd = MyModel([Bta, Btd], X, gi)
A = np.mean(Etd)/np.mean(Eta)
B = gi/(1-gi)
# The epsilon comes in to loosen a bit only this constraint
epsilon = 0.1
return -abs(abs(A-B)-epsilon)
# This is my solution to make the parameters different from zero.
# The ineq-type constraint makes them >=0.
def TDPos(modelparams):
Bta, Btd = modelparams
return Btd - 10**(-5)
def TAPos(modelparams):
Bta, Btd = modelparams
return Bta - 10**(-5)
constraints=[{'type': 'ineq', 'fun': Ratio},
{'type': 'ineq', 'fun': TDPos},
{'type': 'ineq', 'fun': TAPos}]
# Bounds or Model Parameters
bounds=((0, None), (0, None))
# Minimize
modelparams0=[Target/np.nanmean(var1), Target/np.nanmean(var2)]
result = opt.minimize(Obj, modelparams0,
tol=0.1,
method='SLSQP',
options={'maxiter': 40000 }, #,'ftol': 0.1},
bounds=bounds,
constraints=constraints)
print(result)
Распечатывает:
fun: 3.0
jac: array([439.92537314, 77.31019938])
message: 'Optimization terminated successfully.'
nfev: 20
nit: 4
njev: 4
status: 0
success: True
x: array([0., 0.])
Моя проблема: веселье: 3,0> Тол: 0,1, что не желательно.
TL ; DR : scipy.optimize.minimize игнорирует аргумент stop tol
. Почему?
РЕДАКТИРОВАТЬ: Кроме того, оптимальное решение [0, 0] игнорирует два из неравенства ограничений, предназначенных для того, чтобы сделать эту пару параметров> 10 ** (- 5). Это часть той же проблемы?