简单的优化问题与scipy,最小化(SLSQP)给出错误“正方向导数的线性”

xoshrz7s  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(133)

我试图解决一个简单的优化问题,但无法绕过错误“线性的正方向导数”,我想知道这里发生了什么,我没有看到任何问题的梯度,问题是凸的,但非线性。请参阅下面的代码作为参考:

import numpy as np

bounds = [(6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (6.274329865160556e-06, 14.919501068721157), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.0005248360152365689, 27.172072902944304), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635), (0.00014238207960809104, 60.130237219435635)]


maxcovers = {'x1;cost': 2.5, 'x2;cost': 2.5, 'x3;cost': 2.5}
maxjumps = {'x1;cost': 2.5, 'x2;cost': 2.5, 'x3;cost': 2.5}

paramvaluemappings = {"saturations": {0: np.full((1, 31), 0.234835),
                                      1: np.full((1, 31), 0.339884),
                                      2: np.full((1, 31), 0.583774)},
                      "timevariables": {0: np.full((1, 31), -1.206971),
                                        1: np.full((1, 31), 0.36720),
                                        2: np.full((1, 31), 1.0164)},
                      "adstock": {0: np.zeros((1)),
                                  1: np.zeros((1)),
                                  2: np.zeros((1))},
                      "intercept": np.full((1, 31), 0.7899)}

totalbudget = 194

x0 = [0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01000627432986516, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.01052483601523657, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091, 0.010142382079608091]

from scipy.optimize import minimize

cons = []

totalbudgetconstraint = {'type': 'ineq',
                         'fun': lambda x: totalbudget - sum(x)}

cons.append(totalbudgetconstraint)

def newobjective2(x, *args):
    paramvaluemappingsordered = args[0]
    horizon = args[3]
    channels = args[4]

    lookbackadstock = 4

    previousxs = {0: np.array([0.06926, 0.70988, 0.00676, 1.4556, 0.0006, 0.0006]),
                  1: np.array([0.64502, 0.56519, 2.38517, 0.05514, 2.65093, 0.00538]),
                  2: np.array([0.15333, 0.01496, 0.00146, 1.57163, 1.84324, 5.86636])}
    summed = 0
    for idx, channel in enumerate(channels):
        saturationentries = paramvaluemappingsordered['saturations'][idx]# .data[firstdimension,seconddimension, :]
        timevariableentries = paramvaluemappingsordered['timevariables'][idx] #.data[firstdimension, seconddimension, :]
        expenditurechannel = np.append(previousxs[idx],
                                            x[idx * horizon: idx * horizon + horizon])
        channelentry = timevariableentries * np.power(expenditurechannel, saturationentries)
        summed += channelentry

    intercept = paramvaluemappingsordered['intercept'] #.data[firstdimension, seconddimension,:]

    summed += intercept

    summed = summed[:, lookbackadstock:]
    meanvalue = np.mean(summed, axis=0)

    return -np.sum(meanvalue)

args = [paramvaluemappings, None, None, 25, ["x1;cost", "x2;cost", "x3;cost"]]
res = minimize(fun=newobjective2,
               x0=x0,
               args=(paramvaluemappings, None, None, 25, ["x1;cost", "x2;cost", "x3;cost"]),
               constraints=cons,
               method='SLSQP',  # 'trust-constr',  # 'SLSQP',  # method='trust-constr',
               bounds=bounds,
               options={'maxiter': 500_0,
                        # 'xtol': 1e-20,
                        'disp': True,  # ,
                        'xtol': 1e-5,
                        # 'verbose': 2
                        # ,
                        'ftol': 1e-8
                        }
               )

print(res)

字符串
这是一个简单的分配问题,线性约束和非线性奖励函数,应该是可解的SLSQP,并应导致全局最优,因为问题是凸的。
将x 0更改为e.g += 1工作...我想想出一种自动设置x 0的方法,但不需要使用它。...也理解为什么会出现这个问题。
注意,初始x 0满足约束。
增加ftol也工作。。为xtol > 1 e-7。。我想知道为什么。

w3nuxt5m

w3nuxt5m1#

我发现我可以通过两个变化成功地优化这个函数。
1.将预算改写为线性约束。

totalbudgetconstraint = scipy.optimize.LinearConstraint(A=np.ones((1, len(x0))), lb=-np.inf, ub=totalbudget)

字符串
这要求x的总和小于totalbudget。
1.**删除截距。**此函数在取均值之前向输出添加一个常数截距。

summed += intercept


由于优化函数g(x)= f(x)+ c与优化f(x)相同,因此可以将这一行注解掉。
我认为这是有帮助的,因为summed包含了一堆相对于截距来说很小的数字,将一个大的数字添加到一个小的数字会导致组合数字失去精度。
或者,如果您出于其他原因需要此截取,您可以将截取设置为有条件的,并且仅包含它而不优化函数。示例:

def newobjective2(x, *args, with_intercept=False):
    # rest of function same as before
    if with_intercept:
        summed += intercept
    # ...


通过这些修改,我得到了以下结果:

Optimization terminated successfully    (Exit mode 0)
            Current function value: -90.8754619614387
            Iterations: 21
            Function evaluations: 1325
            Gradient evaluations: 17
 message: Optimization terminated successfully
 success: True
  status: 0
     fun: -90.8754619614387
       x: [ 6.274e-06  6.274e-06 ...  7.413e+00  7.423e+00]
     nit: 21
     jac: [ 2.709e+03  2.709e+03 ... -2.578e-01 -2.576e-01]
    nfev: 1325
    njev: 17
with intercept -112.2027619614387


我没有看到任何问题的梯度,问题是凸,但非线性
看看这个函数的梯度,我看到前25个变量相对于其他变量有很大的梯度。

>>> scipy.optimize.approx_fprime(x0, newobjective2, 1.4901161193847656e-08, *args)
array([2710.27860928, 2710.27860928, 2710.27860928, 2710.27860928,
       2710.27860928, 2710.27860928, 2710.27861023, 2710.27861023,
       2710.27860928, 2710.27860928, 2710.27860928, 2710.27860928,
       2710.27860928, 2710.27860928, 2710.27861023, 2710.27861023,
       2710.27860928, 2710.27860928, 2710.27860928, 2710.27860928,
       2710.27860928, 2710.27860928, 2710.27861023, 2710.27861023,
       2710.27861023,   -0.04204273,   -0.04204273,   -0.04204369,
         -0.04204369,   -0.04204369,   -0.04204369,   -0.04204369,
         -0.04204273,   -0.04204273,   -0.04204273,   -0.04204369,
         -0.04204369,   -0.04204369,   -0.04204369,   -0.04204273,
         -0.04204273,   -0.04204273,   -0.04204273,   -0.04204369,
         -0.04204369,   -0.04204369,   -0.04204369,   -0.04204273,
         -0.04204273,   -0.04204273,   -0.40110588,   -0.40110588,
         -0.40110779,   -0.40110779,   -0.40110683,   -0.40110683,
         -0.40110588,   -0.40110588,   -0.40110588,   -0.40110588,
         -0.40110779,   -0.40110779,   -0.40110683,   -0.40110683,
         -0.40110588,   -0.40110588,   -0.40110588,   -0.40110588,
         -0.40110779,   -0.40110779,   -0.40110683,   -0.40110683,
         -0.40109634,   -0.40109634,   -0.40109634])


这是minimize不能很好地容忍的事情,但是我不太了解你正在优化的函数的细节,不知道如何改进它。还有一点值得怀疑的是,有些变量具有完全相同的梯度-这表明你可以将其重新参数化为更少的变量。

相关问题