简体   繁体   English

Scipy 中的共享目标和约束计算优化 Minimize() SLSQP

[英]Sharing objective and constraint calculation within Scipy Optimize Minimize() SLSQP

I've made an app that performs multivariate constrained optimization using Scipy's minimize() function (using the SLSQP solver).我制作了一个使用 Scipy 的 minimize() function (使用 SLSQP 求解器)执行多元约束优化的应用程序。 It's working ok, so now I'm looking at improving the performance of it.它工作正常,所以现在我正在考虑提高它的性能。

The process for calculating my objective value is quite heavy, and takes about a quarter of a second to compute.计算我的目标值的过程非常繁重,大约需要四分之一秒的时间来计算。 That doesn't sound like much, but when minimise() does its thing, it does this calculation about 600 times.这听起来并不多,但是当 minimise() 执行它的操作时,它会执行大约 600 次此计算。 Additionally, the process for running the constraint function takes about the same time, and is also computed about 600 times during optimisation.此外,运行约束 function 的过程大约需要相同的时间,并且在优化期间也计算了大约 600 次。

The thing is, the code for calculating the objective value and the constraint value is nearly identical, just the very last bit at the end differs.问题是,计算目标值和约束值的代码几乎相同,只是最后一位不同。 (My code processes a set of variables, and produces a set of results. Some of those results are relevant for calculating the objective value, while others are relevant for calculating the constraint value). (我的代码处理一组变量,并产生一组结果。其中一些结果与计算目标值相关,而其他结果与计算约束值相关)。

Is there a way that I can share the bulk of the calculation between the objective value calculation and the constraint value calculation?有没有办法可以在目标值计算和约束值计算之间共享大部分计算? If this is possible, then I could nearly halve my optimization time.如果这是可能的,那么我的优化时间几乎可以减半。

I've noticed that the constraints dictionary can have extra arguments 'args' passed to it.我注意到约束字典可以有额外的 arguments 'args' 传递给它。 Perhaps there is a way of passing it the set of 'results' gained during the objective value calculation?也许有一种方法可以将目标值计算期间获得的一组“结果”传递给它?

Thanks, Hugh.谢谢,休。

First, what is the dimension of your problem?首先,您的问题的维度是什么?

SLSQP uses very few function and constraints evaluations, so my guess is that most of the 600 evals you mention come from the gradient approximation code. SLSQP 使用很少的 function 和约束评估,所以我猜你提到的 600 个评估中的大部分来自梯度近似代码。 So one way to make it faster (as @sascha already pointed out) is to pass the explicit gradient function to the solver, if (1) you can compute it and (2) this computation is faster than dimension times the time to compute the objective.因此,使其更快的一种方法(正如@sascha 已经指出的那样)是将显式梯度 function 传递给求解器,如果(1)您可以计算它并且(2)此计算速度快于维度乘以计算客观的。

Now to answer the original question, I think the solution is caching .现在回答最初的问题,我认为解决方案是缓存 If your objective and constraint share most of the computation, then do it only once for both.如果您的目标和约束共享大部分计算,那么两者只执行一次。

You can encapsulate this in a class, like this (Disclaimer: this is not running code):您可以将其封装在 class 中,如下所示(免责声明:这不是运行代码):

class Model:

    def __init__(self):
        self.cache = {}

    def _in_cache(self, x):
        # search for x as key in self.cache
        return x in self.cache

    def _compute_solution(self, x):
        # do all your calculations only once here
        # in the end fill the cache
        self.cache[x] = {"objective": f, "constraint": g}  # f, g are scalars

    def objective(x):
        if not self.in_cache(x):
             self._compute_solution(x) # this fills the cache with objective and constraint values for x
        return self.cache[x]["objective"]

    def constraint(x):
        if not self.in_cache(x):
             self._compute_solution(x) # same idea
        return self.cache[x]["constraint"]

Of course the cache may grow to un-manageable size, so you may have to clean it sometimes, but 600 will not be a problem here.当然,缓存可能会增长到无法管理的大小,因此您有时可能需要清理它,但在这里 600 不会有问题。 you may also assign a unique id to each x and use something like a look-up table, since I'm not sure if you can (and how efficient it is) to use arrays as dictionary keys.您还可以为每个 x 分配一个唯一的 id 并使用诸如查找表之类的东西,因为我不确定您是否可以(以及它的效率如何)使用 arrays 作为字典键。

This solution has the advantage that you can call any method first (the objective or the constraint) and also many times (until you clean the cache).此解决方案的优点是您可以首先调用任何方法(目标或约束),也可以多次调用(直到您清理缓存)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM