简体   繁体   English

scipy.optimize.fmin_slsqp 的使用

[英]Usage of scipy.optimize.fmin_slsqp

I'm trying to use the scipy.optimize package to find the maximum of my cost function.我正在尝试使用 scipy.optimize 包来找到我的成本函数的最大值。

In this particular case: I have a list of prices which vary over the day.在这种特殊情况下:我有一个一天内变化的价格列表。 To make it easier, lets assume the day has 8 hours and the price in each hour are as follows:为方便起见,假设一天有 8 小时,每小时的价格如下:

price_list = np.array([1,2,6,8,8,5,2,1])

In this simplified case I want to select the 4 highest prices from that price_list.在这个简化的例子中,我想从那个 price_list 中选择 4 个最高的价格。 And for various reasons I don't want to simply sort and select the best four prices, but use some optimization algorithm.出于各种原因,我不想简单地排序和选择最好的四个价格,而是使用一些优化算法。 I have several constraints, therefore I decided to use the least square algorithm from scipy, scipy.optimize.fmin_slsqp.我有几个限制,因此我决定使用 scipy 中的最小二乘算法,scipy.optimize.fmin_slsqp。

I first create a schedule for the hours I select:我首先为我选择的时间创建一个时间表:

schedule_list = np.zeros( len(price_list), dtype=float)

Next I need to define my inversed profit_function.接下来我需要定义我的逆利润函数。 For all selected hours I want to sum up my profit.对于所有选定的时间,我想总结我的利润。 While I want to optimize my schedule, the price_list is fixed, therefore I need to put it to the *args:虽然我想优化我的日程安排,但 price_list 是固定的,因此我需要把它放在 *args 中:

def price_func( schedule_list, *price_list ):
    return -1.*np.sum( np.dot( schedule_list, price_list ) )

Once I understand how things work in principle I will move some stuff around.一旦我理解了事情的原理,我就会移动一些东西。 So long, I simply avoid using more *args and define my constraint with a hard coded number of hours to run.长期以来,我只是避免使用更多 *args 并使用硬编码的运行小时数来定义我的约束。 And I want my selected hours to be exactly 4, therefore I use an equality constrain:我希望我选择的小时数正好是 4,因此我使用等式约束:

def eqcon(x, *price_list):
    return sum( schedule_list ) - 4

Furthermore I want to restrict my schedule values to be either 0 or 1. I'm not sure how to implement this right now, therefore I simply use the bounds keywords.此外,我想将我的计划值限制为 0 或 1。我现在不确定如何实现这一点,因此我只使用 bounds 关键字。

The unrestricted optimization with bounds works fine.带边界的无限制优化工作正常。 I simply pass my schedule_list as first guess.我只是通过我的 schedule_list 作为第一次猜测。

scipy.optimize.fmin_slsqp( price_func, schedule_list, args=price_list, bounds=[[0,1]]*len(schedule_list) )

and the output is as good as it can be:并且输出尽可能好:

Optimization terminated successfully.    (Exit mode 0)
        Current function value: -33.0
        Iterations: 2
        Function evaluations: 20
        Gradient evaluations: 2
Out[8]: array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])

Without any further constraints, this is the optimal solution!没有任何进一步的限制,这是最佳解决方案!

Using the constrained optimization with the following command:通过以下命令使用约束优化:

scipy.optimize.fmin_slsqp( price_func, schedule_list, args=price_list, bounds=[[0,1]]*len(schedule_list), eqcons=[eqcon, ] )

gives me the error:给我错误:

Singular matrix C in LSQ subproblem    (Exit mode 6)
        Current function value: -0.0
        Iterations: 1
        Function evaluations: 10
        Gradient evaluations: 1
Out[9]: array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

From gnuplot I know that this is often related to non-sense questions or bad initial values.从 gnuplot 我知道这通常与无意义的问题或错误的初始值有关。 I tried almost optimal initial values, but that does not help.我尝试了几乎最佳的初始值,但这无济于事。 Does anybody has an idea or even solution for me?有没有人对我有想法甚至解决方案?

In a next step, I already have formulated inequality constrains.在下一步中,我已经制定了不等式约束。 Do I understand it correctly that in the scipy minimize wrapper the inequalities are assumed to be larger than 0, while in fmin_slsqp it is vice versa.我是否正确理解在 scipy 最小化包装器中假设不等式大于 0,而在 fmin_slsqp 中反之亦然。 Solutions are constrained to negative constrain functions?解决方案受限于负约束函数?

You have a plain linear program, is that right ?你有一个简单的线性程序,对吗?

min: - prices . x
constrain: x >= 0, sum x = 4

so the second derivative matrix aka Hessian is exactly 0.所以二阶导数矩阵又名 Hessian 正好是 0。
slsqp is trying to invert this --- not possible. slsqp正试图反转这个 --- 不可能。 Agreed, the error message could be better.同意,错误信息可能会更好。
(The same will happen with other quadratic methods, in any package: they'll converge much faster on smooth functions, but crash on rough cliffs.) (在任何包中,其他二次方法也会发生同样的情况:它们在平滑函数上收敛更快,但在崎岖的悬崖上崩溃。)

See also why-cant-i-rig-scipys-constrained-optimization-for-integer-programming --另请参阅为什么不能-i-rig-scipys-constrained-optimization-for-integer-programming --
but LP should do the job (max 4), Integer programming is harder.但 LP 应该完成这项工作(最多 4 个), 整数编程更难。

The SLSQP algorithm is a gradient-based optimizer, meaning it expects the derivatives of the objective and constraints to be continuous. SLSQP 算法是基于梯度的优化器,这意味着它期望目标和约束的导数是连续的。 From my understanding, it seems like you're trying to solve an integer programming problem (continuous values in the schedule list are not acceptable).根据我的理解,您似乎正在尝试解决整数规划问题(计划列表中的连续值是不可接受的)。 You need an algorithm that selects appropriate values (0 or 1) for the independent variables, rather than trying to find the minimum of a continuous space of values.您需要一种为自变量选择适当值(0 或 1)的算法,而不是试图找到连续值空间的最小值。 Unfortunately, I'm not sure that there are any in scipy that do that.不幸的是,我不确定 scipy 中是否有这样做的。

There are some errors in your code.您的代码中有一些错误。 the correct:正确的:

1. def price_func( schedule_list, price_list )
2. def eqcon(schedule_list , price_list):
       return sum( schedule_list ) - 4
3. scipy.optimize.fmin_slsqp( price_func, schedule_list, args=(price_list,), bounds=[[0,1]]*len(schedule_list), eqcons=[eqcon, ] )

then it works.那么它的工作原理。

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

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