Python 3.x scipy优化最小化中忽略了终止公差

Python 3.x scipy优化最小化中忽略了终止公差,python-3.x,optimization,scipy,scipy-optimize-minimize,Python 3.x,Optimization,Scipy,Scipy Optimize Minimize,我有一个简单的优化问题,使用一些特定的数据,使scipy.optimize.minimize忽略tol参数。根据我的理解,tol确定了“终止容差”,即目标函数可接受的最大误差(我错了吗?)。然而,在下一个工作示例中,例如,当tol设置为0.1或其他小数值时,即使目标函数>tol,优化也会以“Optimization terminated successfully”(优化成功终止)消息结束。这是Scipy方法中的一个错误还是我在这里误解了什么 优化问题:我需要对var1和var2进行线性组合,这是

我有一个简单的优化问题,使用一些特定的数据,使scipy.optimize.minimize忽略
tol
参数。根据我的理解,
tol
确定了“终止容差”,即目标函数可接受的最大误差(我错了吗?)。然而,在下一个工作示例中,例如,当
tol
设置为0.1或其他小数值时,即使目标函数>
tol
,优化也会以“Optimization terminated successfully”(优化成功终止)消息结束。这是Scipy方法中的一个错误还是我在这里误解了什么

优化问题:我需要对
var1
var2
进行线性组合,这是两个时间序列,通过参数
Btd
Bta
对它们进行缩放。我需要线性组合的平均值近似于一个目标值
target
,一个标量。因此,我只需最小化
np.mean(Btd*var1+Bta*var2)
目标之间的绝对差异。约束条件是标度系数必须大于0,且均值
np.mean(Btd*var1)/np.mean(Bta*var2)
的比率应近似于函数
gi/(1-gi)
,其中
gi
是区间[0,1]中的标量

可复制代码:

将numpy导入为np
导入scipy.optimize作为选项
#准确再现错误的数据:
时间=np.arange(19792011)
var2=np.数组([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.数组([300,420.89552239333.58208955355.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.转置([var1,var2])
#全局参数
目标=3.0
gi=0.7
#该模型是两个时间序列的简单线性组合。
def MyModel(modelparams,X,gi):
Bta,Btd=模型参数
Eta=Bta*X[:,0]
Etd=Btd*X[:,1]
Etot=Eta+Etd
返回Etot、Eta、Etd
#目标函数
def Obj(模型参数):
Bta,Bdt=modelparams
Etot,Eta,Etd=MyModel([Bta,Bdt],X,gi)
返回abs(净现值平均值(Etot)-目标值)
#比率约束
def比率(模型参数):
将numpy作为np导入
Bta,Btd=模型参数
Etot,Eta,Etd=MyModel([Bta,Btd],X,gi)
A=净现值平均值(Etd)/净现值平均值(Eta)
B=gi/(1-gi)
#epsilon进来只是稍微放松了这个约束
ε=0.1
返回-abs(abs(A-B)-ε)
#这是我的解决方案,使参数不同于零。
#ineq类型约束使它们>=0。
def TDPos(模型参数):
Bta,Btd=模型参数
返回Btd-10**(-5)
def TAPos(模型参数):
Bta,Btd=模型参数
返回Bta-10**(-5)
约束=[{'type':'ineq','fun':Ratio},
{'type':'ineq','fun':TDPos},
{'type':'ineq','fun':TAPos}]
#模型参数的界
界限=((0,无),(0,无))
#最小化
modelparams0=[Target/np.nanmean(var1),Target/np.nanmean(var2)]
结果=选择最小化(对象,模型参数0,
tol=0.1,
方法='SLSQP',
选项={'maxiter':40000},#,'ftol':0.1},
界限=界限,
约束=约束)
打印(结果)
打印出:

     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>tol:0.1 这是不可取的

TL;DR:scipy.optimize.minimize忽略停止参数
tol
。为什么?


编辑:此外,最佳解决方案[0,0]忽略了两个ineq约束,旨在使这对参数>10**(-5)。这是同一个问题的一部分吗?

不管tol到底是什么,它都依赖于解算器,当然不是你所假设的。对于您的解释,解算器必须知道零的下限,或者需要遵循一些原始-对偶或类似的方法来获得边界。tol通常是一个简单的一阶临界值,如abs(func(it x)-func(it x-1))。Slsqp可能使用近似的二阶信息。但我不会盲目地玩这个游戏。你对托尔和马克西特的区别也很奇怪。前者非常放松。后者非常咄咄逼人。谢谢@sascha,我误解了
tol
的意思。你能看到一种方法来施加这个终止阈值,作为目标函数的一个可接受的错误吗?这就是我对tol的目标。你可以使用回调来拼凑一些东西;看见