为什么这个约束函数比类似的函数慢得多?如何提高 Scipy Optimize 中的速度?

问题描述 投票:0回答:1

我有一个包含大约 22 个约束函数的优化。我尝试将其转换为单个约束函数,但优化器花费了 10 倍的时间。有什么办法可以降低速度吗

以下是原始约束函数。我只包含了 2 个,但大约有 22 个,每个都有不等式约束的硬编码值。这些参数是优化器正在寻找的值,优化器正在寻找大约 50 个值。例如,对于第一个约束,它基本上表示,前 2 个参数值相加不得超过 129:

def MaxConstraint000(parameters): 
    _count = np.sum(parameters[0:2])
    return (129 - _count)

def MaxConstraint001(parameters): 
    _count = np.sum(parameters[2:5])
    return (2571 - _count)

_Constraints = ({'type': 'ineq', 'fun': MaxConstraint000}
                , {'type': 'ineq', 'fun': MaxConstraint001})

为了简化我的代码,而不是预先确定参数的位置,我尝试了这样的方法,其中我提供了一个键值,该键值提取参数值的索引位置以及常量值 [129、2571 等。 ..] 来自数据框。 DFData 的行数与参数数相同。该约束与第一个约束相同,只是我提供了一个 keyValue,它允许我查找最大值以及索引位置。

def MaxConstraint(parameters, keyValue):
    _parameters= np.array(parameters)
    _index = np.where(DFData['KeyValues'].values == keyValue)[0] 
    
    _count = np.sum(_parameters[_index])
    _target = DFMaxValues.loc[[keyValue], ['MaxValue']].values[0][0]
    return (_target - _count )

_Constraints = ({'type': 'ineq', 'fun': MaxConstraint, 'args': ('keyValue1', )}
                , {'type': 'ineq', 'fun': MaxConstraint, 'args': ('keyValue2', )}

这会导致执行时间延长 10 倍。如何使其速度降至与第一个速度大致相同?我更喜欢第二种实现,因为我可以只更新字典或 CSV 文件,而不是进入每个约束并更改 MaxValue。此外,如果数据行混合,我就没有硬编码的索引值。

谢谢!


全套约束:

def MaxConstraint000(parameters):
    _count = np.sum(parameters[0:2])
    return (129 - _count)

def MaxConstraint001(parameters): 
    _count = np.sum(parameters[2:5])
    return (2571 - _count)

def MaxConstraint002(parameters): 
    _count = np.sum(parameters[5:8])
    return (3857 - _count)

def MaxConstraint003(parameters): 
    _count = np.sum(parameters[8:10])
    return (823 - _count)

def MaxConstraint004(parameters): 
    _count = np.sum(parameters[10:13])
    return (823 - _count)

def MaxConstraint005(parameters): 
    _count = np.sum(parameters[13:16])
    return (3857 - _count)

def MaxConstraint006(parameters): 
    _count = np.sum(parameters[16:21])
    return (4714 - _count)

def MaxConstraint007(parameters): 
    _count = np.sum(parameters[21:25])
    return (3429 - _count)

def MaxConstraint008(parameters): 
    _count = np.sum(parameters[25:28])
    return (3429 - _count)

def MaxConstraint009(parameters): 
    _count = np.sum(parameters[28:30])
    return (3429 - _count)

def MaxConstraint010(parameters): 
    _count = np.sum(parameters[30:33])
    return (2914 - _count)

def MaxConstraint011(parameters):
    _count = np.sum(parameters[33:38])
    return (6000 - _count)

def MaxConstraint012(parameters): 
    _count = np.sum(parameters[38:43])
    return (6000 - _count)

def MaxConstraint013(parameters): 
    _count = np.sum(parameters[43:45])
    return (429 - _count)

def MaxConstraint014(parameters): 
    _count = np.sum(parameters[45:47])
    return (1457 - _count)

def MaxConstraint015(parameters): 
    _count = np.sum(parameters[47:51])
    return (4286 - _count)

def MaxConstraint016(parameters): 
    _count = np.sum(parameters[51:53])
    return (2143 - _count)

def MaxConstraint017(parameters): 
    _count = np.sum(parameters[53:57])
    return (4286 - _count)

def MaxConstraint018(parameters): 
    _count = np.sum(parameters[57:64])
    return (2143 - _count)

def MaxConstraint019(parameters): 
    _count = np.sum(parameters[64:67])
    return (2571 - _count)

def MaxConstraint020(parameters): 
    _count = np.sum(parameters[67:72])
    return (1714 - _count)

def MaxConstraint021(parameters): 
    _count = np.sum(parameters[72:75])
    return (4286 - _count)
    
_Bounds = ((0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000), (0, 10000)
           , (0, 10000), (0, 10000), (0, 10000))

_Constraints = ({'type': 'ineq', 'fun': MaxConstraint000}
                , {'type': 'ineq', 'fun': MaxConstraint001}
                , {'type': 'ineq', 'fun': MaxConstraint002}
                , {'type': 'ineq', 'fun': MaxConstraint003}
                , {'type': 'ineq', 'fun': MaxConstraint004}
                , {'type': 'ineq', 'fun': MaxConstraint005}
                , {'type': 'ineq', 'fun': MaxConstraint006}
                , {'type': 'ineq', 'fun': MaxConstraint007}
                , {'type': 'ineq', 'fun': MaxConstraint008}
                , {'type': 'ineq', 'fun': MaxConstraint009}
                , {'type': 'ineq', 'fun': MaxConstraint010}
                , {'type': 'ineq', 'fun': MaxConstraint011}
                , {'type': 'ineq', 'fun': MaxConstraint012}
                , {'type': 'ineq', 'fun': MaxConstraint013}
                , {'type': 'ineq', 'fun': MaxConstraint014}
                , {'type': 'ineq', 'fun': MaxConstraint015}
                , {'type': 'ineq', 'fun': MaxConstraint016}
                , {'type': 'ineq', 'fun': MaxConstraint017}
                , {'type': 'ineq', 'fun': MaxConstraint018}
                , {'type': 'ineq', 'fun': MaxConstraint019}
                , {'type': 'ineq', 'fun': MaxConstraint020}
                , {'type': 'ineq', 'fun': MaxConstraint021}
               )

############# Solve Optim Problem ############### 
_OptimResultsConstraint = scipy_opt.minimize(ObjectiveFunction
                                             , x0 = [10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000,
                                                   10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000,
                                                   10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000,
                                                   10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000,
                                                   10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000,
                                                   10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000,
                                                   10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000,
                                                   10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000,
                                                   10000, 10000, 10000] # starting guesses
                                             , method = 'trust-constr' # trust-constr, SLSQP
                                             , options = {'maxiter': 1000000000}
                                             , bounds = _Bounds
                                             , constraints = _Constraints) 
python python-3.x scipy constraints scipy-optimize
1个回答
0
投票

你的多重限制实际上只是一种限制。最紧凑的表示方式是一个稀疏 CSR 数组:

import numpy as np
from scipy.optimize import LinearConstraint
import scipy.sparse

A = scipy.sparse.csr_array(
    (
        np.ones(75),    # data
        np.arange(75),  # indices
        (
            0, 2, 5, 8, 10, 13, 16, 21, 25, 28,
            30, 33, 38, 43, 45, 47, 51, 53, 57,
            64, 67, 72, 75,
        ),
    ),
)

constraint = LinearConstraint(
    A=A,
    ub=(
        129, 2571, 3857, 823, 823, 3857, 4714, 3429, 3429, 3429,
        2914, 6000, 6000, 429, 1457, 4286, 2143, 4286, 2143, 2571,
        1714, 4286,
    ),
)
© www.soinside.com 2019 - 2024. All rights reserved.