我有一个优化问题,我想使用scipy.optimize.minimize包,也就是没有预见到任何约束或界限的方法之一,比如‘nelder’,'powell','cg','bfgs',newton‘,’dog腿‘,'trust-ncg’-参见:最小化关于边界和约束的异常。
我想通过在我的成本函数上添加一个包装器来自我介绍界限:
这个包装器由优化器调用,并将参数传递给我想要优化的代价函数。成本函数返回一个值给包装器。
如果优化器使用参数超出参数允许范围的参数调用包装器,则包装器随后向代价函数的结果添加一些额外的“惩罚”,并将惩罚和代价函数的结果传递给优化器。
我的问题是:
如果我有一个像这样的二元惩罚函数(仅在上界的上限上显示),那么优化是否正常工作(这意味着:它会以更高的概率找到我的成本函数的绝对最小值吗):
if parameter > upperBound:
penalty = 1.e6
else:
penalty = 0.0还是更好地使用更流畅的惩罚函数(以模拟lipschitz连续函数),例如移位平方函数:
if parameter > upperBound:
penalty = VERY_HIGH_NUMBER * (parameter - upperBound)**2
else:
penalty = 0.0如果使用更平滑的惩罚函数更好,那么对于这类函数是否有“最佳实践”(例如使用乙状结肠函数或平方函数等)?
发布于 2019-08-28 19:20:22
我通常会转换参数空间,以便-Inf对应于最低值,而+Inf对应于最高值,例如,如果乙状结肠函数在顶部和底部有界,或者“1+exp日志”(不确定该值的规范名称),则可以使用它。天真的版本是:
def sigfn(x):
return 1 / (1 + exp(-x))
def logexpfn(x):
return log1p(exp(x))但是,您可能需要特别小心地处理较大的值,因为大于700个值会导致exp溢出。因此,这些功能可以扩展到:
def sigfn(x):
if x < -36:
return exp(x)
return 1 / (1 + exp(-x))
def logexpfn(x):
if x > 36:
return x
return log1p(exp(x))我使用36,因为这是我们失去精度的点,也就是exp(37) * float_info.epsilon > 1。
如果你只想要一个上限,你可以用这些来做:
def optfn(param):
param = upperValue - logexpfn(-param)或者任何对你的代码有意义的东西。这显然使事情比直接使用东西更尴尬,但这是一种非常普遍的技术,而且普遍适用。
https://stackoverflow.com/questions/57694340
复制相似问题