所以我有以下问题要尽量减少。我有一个向量w
,我需要找到它,以便最小化以下功能:
import numpy as np
from scipy.optimize import minimize
matrix = np.array([[1.0, 1.5, -2.],
[0.5, 3.0, 2.5],
[1.0, 0.25, 0.75]])
def fct(x):
return x.dot(matrix).dot(x)
x0 = np.ones(3) / 3
cons = ({'type': 'eq', 'fun': lambda x: x.sum() - 1.0})
bnds = [(0, 1)] * 3
w = minimize(fct, x0, method='SLSQP', bounds=bnds, constraints=cons)['x']
我选择了method='SLSQP'
,因为它似乎是唯一允许bounds
和constraints
的人。我的问题是我必须在多个选择上循环我的解决方案,所以我想在这里获得一些速度。我的解决方案是使用优化器的最快的解决方案还是还有其他更快的解决方案?谢谢。
答案 0 :(得分:8)
一般来说,最快的方法始终是最适合问题的方法。
由于scipy.minimize中的所有优化算法都很普遍,所以会有 始终是更快的方法,从问题的特殊特征中获得性能。 这将是一种权衡,需要做多少分析和工作才能获得绩效。
重要的是要注意, SLSQP 例如是一种算法,它能够 解决非凸问题,在这种情况下,可以保证收敛到某些局部最优 (忽略实现中的数字问题;这总是一个可能的问题)。
这种功能需要付出代价:与算法相比,SLSQP的速度更快,稳定性更低 这是专为凸问题设计的(甚至在凸问题中也是如此) 它们都是多项式可解的,线性编程和更难的更容易 如SemidefiniteProgramming)。
如上面的评论所示,对于一些一般不定矩阵M ,这个问题 是非凸(概率很高;我没有提供正式证据),这意味着, 如果没有进一步的假设,就没有一般可行的方法(忽略 特殊分析,因为一些非凸问题可以在多项式时间内全局求解。)
这意味着:
如果我们假设矩阵M是正定或负定,但不是无限,则这是一个凸优化问题。您似乎对此案感兴趣,这里有一些评论和方法。
这意味着:
除了用于线性编程的linprog之外,没有特殊的凸优化求解器 因此无法解决这个问题。
还有其他选择,如上所述,有很多可能的路线 使用它们。
在这里,我将介绍一个最简单的方法:
示例代码:
代码:
import time
import numpy as np
from cvxpy import * # Convex-Opt
""" Create some random pos-def matrix """
N = 1000
matrix_ = np.random.normal(size=(N,N))
matrix = np.dot(matrix_, matrix_.T)
""" CVXPY-based Convex-Opt """
print('\ncvxpy\n')
x = Variable(N)
constraints = [x >= 0, x <= 1, sum(x) == 1]
objective = Minimize(quad_form(x, matrix))
problem = Problem(objective, constraints)
time_start = time.perf_counter()
problem.solve(solver=SCS, use_indirect=True, verbose=True) # or: solver=ECOS
time_end = time.perf_counter()
print(problem.value)
print('cvxpy (modelling) + ecos/scs (solving) used (secs): ', time_end - time_start)
示例输出:
cvxpy
----------------------------------------------------------------------------
SCS v1.2.6 - Splitting Conic Solver
(c) Brendan O'Donoghue, Stanford University, 2012-2016
----------------------------------------------------------------------------
Lin-sys: sparse-indirect, nnz in A = 1003002, CG tol ~ 1/iter^(2.00)
eps = 1.00e-03, alpha = 1.50, max_iters = 2500, normalize = 1, scale = 1.00
Variables n = 1001, constraints m = 3003
Cones: primal zero / dual free vars: 1
linear vars: 2000
soc vars: 1002, soc blks: 1
Setup time: 6.76e-02s
----------------------------------------------------------------------------
Iter | pri res | dua res | rel gap | pri obj | dua obj | kap/tau | time (s)
----------------------------------------------------------------------------
0| inf inf -nan -inf -inf inf 1.32e-01
100| 1.54e-02 1.48e-04 7.63e-01 -5.31e+00 -4.28e+01 1.10e-11 1.15e+00
200| 1.53e-02 1.10e-04 7.61e-01 -3.87e+00 -3.17e+01 1.08e-11 1.95e+00
300| 1.53e-02 7.25e-05 7.55e-01 -2.47e+00 -2.08e+01 1.07e-11 2.79e+00
400| 1.53e-02 3.61e-05 7.39e-01 -1.11e+00 -1.03e+01 1.06e-11 3.61e+00
500| 7.64e-03 2.55e-04 1.09e-01 -2.01e-01 -6.32e-02 1.05e-11 4.64e+00
560| 7.71e-06 4.24e-06 8.61e-04 2.17e-01 2.16e-01 1.05e-11 5.70e+00
----------------------------------------------------------------------------
Status: Solved
Timing: Solve time: 5.70e+00s
Lin-sys: avg # CG iterations: 1.71, avg solve time: 9.98e-03s
Cones: avg projection time: 3.97e-06s
----------------------------------------------------------------------------
Error metrics:
dist(s, K) = 5.1560e-16, dist(y, K*) = 0.0000e+00, s'y/|s||y| = 2.4992e-17
|Ax + s - b|_2 / (1 + |b|_2) = 7.7108e-06
|A'y + c|_2 / (1 + |c|_2) = 4.2390e-06
|c'x + b'y| / (1 + |c'x| + |b'y|) = 8.6091e-04
----------------------------------------------------------------------------
c'x = 0.2169, -b'y = 0.2157
============================================================================
0.21689554805292935
cvxpy (modelling) + ecos/scs (solving) used (secs): 7.105745473999832
额外示例:5000x5000使用~9分钟(没有调整参数)。
一些小小的额外评论:
答案 1 :(得分:2)
基于pylang注释,我计算了我的函数的jacobian,它导致了以下函数:
def fct_deriv(x):
return 2 * matrix.dot(x)
优化问题变为以下
minimize(fct, x0, method='SLSQP', jac=fct_deriv, bounds=bnds, constraints=cons)['x']
但是,该解决方案不允许添加Hessian,因为SLSQP方法不允许它。存在其他优化方法,但SLSQP是唯一同时接受边界和约束的方法(这对我的优化问题至关重要)。
请参阅下面的完整代码:
import numpy as np
from scipy.optimize import minimize
matrix = np.array([[1.0, 1.5, -2.],
[0.5, 3.0, 2.5],
[1.0, 0.25, 0.75]])
def fct(x):
return x.dot(matrix).dot(x)
def fct_deriv(x):
return 2 * matrix.dot(x)
x0 = np.ones(3) / 3
cons = ({'type': 'eq', 'fun': lambda x: x.sum() - 1.0})
bnds = [(0, 1)] * 3
w = minimize(fct, x0, method='SLSQP', jac=fct_deriv, bounds=bnds, constraints=cons)['x']
已编辑(添加了约束的jacobian):
cons2 = ({'type': 'eq', 'fun': lambda x: x.sum() - 1.0, 'jac': lambda x: np.ones_like(x)})
w = minimize(fct, x0, method='SLSQP', jac=fct_deriv, bounds=bnds, constraints=cons2)['x']