Python scipy.optimized受限最小化SLSQP-无法与目标100%

Python scipy.optimized受限最小化SLSQP-无法与目标100%,python,math,optimization,machine-learning,scipy,Python,Math,Optimization,Machine Learning,Scipy,我试图得到最小的重量,接近平均重量的总和。我目前的问题是使用SLSQP解算器,我无法找到满足目标100%的正确权重。有没有其他解决方案可以用来解决我的问题?或者任何数学建议。请帮忙 我现在的数学是 **min⁡(∑|x-mean(x)|)** **s.t.** Aw-b=0, w>=0 **bound** 0.2'<'x<0.5 问题:找到接近平均值的最小重量 Python代码: A = np.arra

我试图得到最小的重量,接近平均重量的总和。我目前的问题是使用SLSQP解算器,我无法找到满足目标100%的正确权重。有没有其他解决方案可以用来解决我的问题?或者任何数学建议。请帮忙

我现在的数学是

           **min⁡(∑|x-mean(x)|)**

           **s.t.** Aw-b=0, w>=0


           **bound** 0.2'<'x<0.5
问题:找到接近平均值的最小重量


Python代码:

A = np.array([[3582.000000, 3394.000000, 3356.000000, 3256.000000, 3415.000000,
        3505.000000, 3442.000000, 3381.000000, 3392.000000],
       [233445193.000000, 217344811.000000, 237746918.000000,
        219204892.000000, 225272825.000000, 242819442.000000,
        215258725.000000, 227681178.000000, 215189377.000000],
       [559090945.000000, 496500751.000000, 493639029.000000,
        461547877.000000, 501057960.000000, 505073223.000000,
        490458632.000000, 503102998.000000, 487026744.000000]])

b = np.array([8531, 1079115532, 429386951]) 

n=9
def fsolveMin(A,b,n):

    # The constraints: Ax = b

    def cons(x):
        return A.dot(x)-b

    cons = ({'type':'eq','fun':cons},

            {'type':'ineq','fun':lambda x:x[0]})

    # The minimizing constraints: the total absolute difference between the coefficients

    def fn(x):
        return np.sum(np.abs(x-np.mean(x)))       

    # Initialize the coefficients randomly
    z0 = abs(np.random.randn(len(A[1,:])))

    # Set up bound
   # bnds = [(0, None)]*n

    # Solve the problem

    sol = minimize(fn, x0 = z0, constraints = cons, method = 'SLSQP', options={'disp': True})



    #expected 35%
    print(sol.x)
    print(A.dot(sol.x))

    #print(fn(sol.x))

print(str(fsolveMin(A,b,n))+"\n\n")

首先引入一个带有约束的自由变量mu:

   mu = sum(i, x(i))/n
然后引入非负变量
y(i)

   -y(i) <= x(i) - mu <= y(i)

现在这是一个直接的LP(线性目标和线性约束),可以用任何LP解算器来解决。

为了让您了解像scipy的这样的低级工具会有多臃肿,我们必须模仿它们的标准形式

其基本思想是:

  • 为平均值添加一个辅助变量,如Erwin建议的
  • 添加n个辅助变量来处理绝对值
  • (我使用n-extra-aux-vars作为
    x-mean
    的临时变量)
现在这个例子起作用了

对于您的数据,您必须小心边界。确保问题始终可行。问题本身非常不稳定,因为硬约束用于
Ax=b
;通常,您会在这里最小化一些范数/最小二乘(不再是LP;QP/SOCP),并将此误差添加到目标中)

可能需要在某个点将解算器从
method='simplex'
切换到
method='interior-point'
(仅自scipy 1.0起可用)

备选方案:

使用,公式更容易(提到的两种变体),并且您可以免费获得相当好的解算器(ECOS)

代码:

现在,对于您的原始数据,,事情变得艰难了

您需要:

  • 缩放数据,因为变量的大小会影响解算器
    • 根据您的任务,您可能需要分析缩放/反转的效果
  • 使用内部点解算器
  • 小心边界
例如:

A = np.array([[3582.000000, 3394.000000, 3356.000000, 3256.000000, 3415.000000,
        3505.000000, 3442.000000, 3381.000000, 3392.000000],
       [233445193.000000, 217344811.000000, 237746918.000000,
        219204892.000000, 225272825.000000, 242819442.000000,
        215258725.000000, 227681178.000000, 215189377.000000],
       [559090945.000000, 496500751.000000, 493639029.000000,
        461547877.000000, 501057960.000000, 505073223.000000,
        490458632.000000, 503102998.000000, 487026744.000000]])
b = np.array([8531., 1079115532., 429386951.])

A /= 10000.  # scaling
b /= 10000.  # scaling

bounds = [(-50., 50.) for i in range(n)] +     \
...

result = spo.linprog(c, A_ineq, b_ineq, A_eq, b_eq, bounds=bounds, method='interior-point')
输出:

Original A
[[  4.17022005e-01   7.20324493e-01   1.14374817e-04]
 [  3.02332573e-01   1.46755891e-01   9.23385948e-02]]
hidden x:  [ 0.18626021  0.34556073  0.39676747]
target:  [ 0.32663584  0.14366255]
Reformulation
y = mean A:
[ 0.33333333  0.33333333  0.33333333 -1.          0.          0.          0.          0.          0.          0.        ]
y = mean b:
[0]
Ax=b A:
[[  4.17022005e-01   7.20324493e-01   1.14374817e-04   0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
    0.00000000e+00   0.00000000e+00   0.00000000e+00]
 [  3.02332573e-01   1.46755891e-01   9.23385948e-02   0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
    0.00000000e+00   0.00000000e+00   0.00000000e+00]]
Ax=b b:
[ 0.32663584  0.14366255]
z = x - mean A:
[[-1. -0. -0.  1.  1.  0.  0.  0.  0.  0.]
 [-0. -1. -0.  1.  0.  1.  0.  0.  0.  0.]
 [-0. -0. -1.  1.  0.  0.  1.  0.  0.  0.]]
z = x - mean b:
[ 0.  0.  0.]
solve...
     fun: 0.078779576294411263
 message: 'Optimization terminated successfully.'
     nit: 10
   slack: array([ 0.07877958,  0.        ,  0.        ,  0.        ,  0.07877958,  0.        ,  0.76273076,  0.68395118,
        0.72334097])
  status: 0
 success: True
       x: array([ 0.23726924,  0.31604882,  0.27665903,  0.27665903, -0.03938979,  0.03938979,  0.        ,  0.03938979,
        0.03938979,  0.        ])
x:  [ 0.23726924  0.31604882  0.27665903]
residual Ax-b:  [  5.55111512e-17   0.00000000e+00]
mean:  0.276659030053
x - mean:  [-0.03938979  0.03938979  0.        ]
l1-norm(x - mean) / objective:  0.0787795762944
solve...
     con: array([  3.98410760e-09,   1.18067724e-08,   8.12879938e-04,   1.75969041e-03,  -3.93853838e-09,  -3.96305566e-09,
        -4.10043555e-09,  -3.94957667e-09,  -3.88362764e-09,  -3.89452381e-09,  -3.95134592e-09,  -3.92182287e-09,
        -3.85762178e-09])
     fun: 52.742900697626389
 message: 'Optimization terminated successfully.'
     nit: 8
   slack: array([  5.13245265e+01,   1.89309145e-08,   1.83429094e-09,   4.28687782e-09,   1.03726911e-08,   2.77000474e-09,
         1.41837413e+00,   6.75769654e-09,   8.65285462e-10,   2.78501844e-09,   3.09591539e-09,   5.27429006e+01,
         1.30944103e-08,   5.32994799e-09,   3.15369669e-08,   2.51943821e-09,   7.54848797e-09,   3.22510447e-09])
  status: 0
 success: True
       x: array([ -2.51938304e+01,   4.68432810e-01,   2.68398831e+01,   4.68432822e-01,   4.68432815e-01,   4.68432832e-01,
        -2.40754247e-01,   4.68432818e-01,   4.68432819e-01,   4.68432822e-01,  -2.56622633e+01,  -7.91749954e-09,
         2.63714503e+01,   4.40376624e-09,  -2.52137156e-09,   1.43834811e-08,  -7.09187065e-01,   3.95395716e-10,
         1.17990950e-09,   2.56622633e+01,   1.10134149e-08,   2.63714503e+01,   8.69064406e-09,   7.85131955e-09,
         1.71534858e-08,   7.09187068e-01,   7.15309226e-09,   2.04519496e-09])
x:  [-25.19383044   0.46843281  26.83988313   0.46843282   0.46843282   0.46843283  -0.24075425   0.46843282   0.46843282]
residual Ax-b:  [ -1.18067724e-08  -8.12879938e-04  -1.75969041e-03]
mean:  0.468432821891
x - mean:  [ -2.56622633e+01  -1.18805552e-08   2.63714503e+01   4.54189575e-10  -6.40499920e-09   1.04889573e-08  -7.09187069e-01
  -3.52642715e-09  -2.67771227e-09]
l1-norm(x - mean) / objective:  52.7429006758
 ECOS 2.0.4 - (C) embotech GmbH, Zurich Switzerland, 2012-15. Web: www.embotech.com/ECOS

It     pcost       dcost      gap   pres   dres    k/t    mu     step   sigma     IR    |   BT
 0  +2.637e-17  -1.550e+06  +7e+08  1e-01  2e-04  1e+00  2e+07    ---    ---    1  1  - |  -  -
 1  -8.613e+04  -1.014e+05  +8e+06  1e-03  2e-06  2e+03  2e+05  0.9890  1e-04   2  1  1 |  0  0
 2  -1.287e+03  -1.464e+03  +1e+05  1e-05  9e-08  4e+01  3e+03  0.9872  1e-04   3  1  1 |  0  0
 3  +1.794e+02  +1.900e+02  +2e+03  2e-07  1e-07  1e+01  5e+01  0.9890  5e-03   5  3  4 |  0  0
 4  -1.388e+00  -6.826e-01  +1e+02  1e-08  7e-08  9e-01  3e+00  0.9458  4e-03   7  6  6 |  0  0
 5  +5.491e+00  +5.683e+00  +1e+01  1e-09  8e-09  2e-01  3e-01  0.9617  6e-02   1  1  1 |  0  0
 6  +6.480e+00  +6.505e+00  +1e+00  2e-10  5e-10  3e-02  4e-02  0.8928  2e-02   1  1  1 |  0  0
 7  +6.746e+00  +6.746e+00  +2e-02  3e-12  5e-10  5e-04  6e-04  0.9890  5e-03   1  0  0 |  0  0
 8  +6.759e+00  +6.759e+00  +3e-04  2e-12  2e-10  6e-06  7e-06  0.9890  1e-04   1  0  0 |  0  0
 9  +6.759e+00  +6.759e+00  +3e-06  2e-13  2e-10  6e-08  8e-08  0.9890  1e-04   2  0  0 |  0  0
10  +6.758e+00  +6.758e+00  +3e-08  5e-14  2e-10  7e-10  9e-10  0.9890  1e-04   1  0  0 |  0  0

OPTIMAL (within feastol=2.0e-10, reltol=4.7e-09, abstol=3.2e-08).
Runtime: 0.002901 seconds.

Objective:  6.757722879805085
x:  [[-18.09169736  -5.55768047  11.12130645  11.48355878  -1.13982006
   12.4290884   -3.00165819  -1.05158589  -2.4468432 ]]
mean:  0.416074272576
Ax-b:
[[  2.17051777e-03]
 [  1.90734863e-06]
 [ -5.72204590e-06]]
x - mean:  [[-18.50777164  -5.97375474  10.70523218  11.0674845   -1.55589434
   12.01301413  -3.41773246  -1.46766016  -2.86291747]]
Objective:  785913288.2410747
x:  [[ -5.57966858e-08  -4.74997454e-08   1.56066068e+00   1.68021234e-07
   -3.55602958e-08   1.75340641e-06  -4.69609562e-08  -3.10216680e-08
   -4.39482554e-08]]
mean:  0.173406926909
Ax-b:
[[ -3.29341696e+03]
 [ -7.08072860e+08]
 [  3.41016903e+08]]
x - mean:  [[-0.17340698 -0.17340697  1.38725375 -0.17340676 -0.17340696 -0.17340517
  -0.17340697 -0.17340696 -0.17340697]]
编辑

这里是一个基于SOCP的最小二乘(软约束)方法,我建议在数值稳定性方面使用它!这种方法可以而且应该根据您的需要进行调整。它是使用前面提到的建模工具(使用ECOS解算器)实现的

基本思想是:

  • 代替
    最小(l1标准(x-平均值(x))标准轴=b
  • 求解
    min(l2范数(Ax-b)+c*l1范数(x-均值(x))
    • 其中
      c
      是非负权衡参数
    • 小的
      c
      Ax=b
      更重要
    • c
      x-均值(x)
      更重要
数据的示例代码和输出以及
-50、50
c=1e-3
的界限:

import numpy as np
import cvxpy as cvx

""" DATA """
A = np.array([[3582.000000, 3394.000000, 3356.000000, 3256.000000, 3415.000000,
        3505.000000, 3442.000000, 3381.000000, 3392.000000],
       [233445193.000000, 217344811.000000, 237746918.000000,
        219204892.000000, 225272825.000000, 242819442.000000,
        215258725.000000, 227681178.000000, 215189377.000000],
       [559090945.000000, 496500751.000000, 493639029.000000,
        461547877.000000, 501057960.000000, 505073223.000000,
        490458632.000000, 503102998.000000, 487026744.000000]])
b = np.array([8531., 1079115532., 429386951.])
n = 9

# A /= 10000.  scaling would be a good idea
# b /= 10000.  """

""" SOCP-based least-squares approach """
def solve(A, b, n, c=1e-1):
    x = cvx.Variable(n)
    y = cvx.Variable(1)             # mean

    lower_bounds = np.zeros(n) - 50  # -50
    upper_bounds = np.zeros(n) + 50  #  50

    constraints = []
    constraints.append(x >= lower_bounds)
    constraints.append(x <= upper_bounds)
    constraints.append(y == cvx.sum_entries(x) / n)

    objective = cvx.Minimize(cvx.norm(A*x-b, 2) + c * cvx.norm(x - y, 1))
    problem = cvx.Problem(objective, constraints)

    problem.solve(solver=cvx.ECOS, verbose=True)

    print('Objective: ', problem.value)
    print('x: ', x.T.value)
    print('mean: ', y.value)
    print('Ax-b: ')
    print((A*x - b).value)
    print('x - mean: ', (x - y).T.value)

solve(A, b, n)
这种方法将始终输出一个可行的解决方案(对于我们的任务),然后您可以决定观察到的残差是否适合您

正如您所观察到的,在所有公式中,0的下限都是致命的(看看数据中的大小差异!)

在这里,0的下限将为您提供一个残差较高的解决方案

例如:

  • c=1e-7
  • 界限=
    0/15
输出:

Original A
[[  4.17022005e-01   7.20324493e-01   1.14374817e-04]
 [  3.02332573e-01   1.46755891e-01   9.23385948e-02]]
hidden x:  [ 0.18626021  0.34556073  0.39676747]
target:  [ 0.32663584  0.14366255]
Reformulation
y = mean A:
[ 0.33333333  0.33333333  0.33333333 -1.          0.          0.          0.          0.          0.          0.        ]
y = mean b:
[0]
Ax=b A:
[[  4.17022005e-01   7.20324493e-01   1.14374817e-04   0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
    0.00000000e+00   0.00000000e+00   0.00000000e+00]
 [  3.02332573e-01   1.46755891e-01   9.23385948e-02   0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
    0.00000000e+00   0.00000000e+00   0.00000000e+00]]
Ax=b b:
[ 0.32663584  0.14366255]
z = x - mean A:
[[-1. -0. -0.  1.  1.  0.  0.  0.  0.  0.]
 [-0. -1. -0.  1.  0.  1.  0.  0.  0.  0.]
 [-0. -0. -1.  1.  0.  0.  1.  0.  0.  0.]]
z = x - mean b:
[ 0.  0.  0.]
solve...
     fun: 0.078779576294411263
 message: 'Optimization terminated successfully.'
     nit: 10
   slack: array([ 0.07877958,  0.        ,  0.        ,  0.        ,  0.07877958,  0.        ,  0.76273076,  0.68395118,
        0.72334097])
  status: 0
 success: True
       x: array([ 0.23726924,  0.31604882,  0.27665903,  0.27665903, -0.03938979,  0.03938979,  0.        ,  0.03938979,
        0.03938979,  0.        ])
x:  [ 0.23726924  0.31604882  0.27665903]
residual Ax-b:  [  5.55111512e-17   0.00000000e+00]
mean:  0.276659030053
x - mean:  [-0.03938979  0.03938979  0.        ]
l1-norm(x - mean) / objective:  0.0787795762944
solve...
     con: array([  3.98410760e-09,   1.18067724e-08,   8.12879938e-04,   1.75969041e-03,  -3.93853838e-09,  -3.96305566e-09,
        -4.10043555e-09,  -3.94957667e-09,  -3.88362764e-09,  -3.89452381e-09,  -3.95134592e-09,  -3.92182287e-09,
        -3.85762178e-09])
     fun: 52.742900697626389
 message: 'Optimization terminated successfully.'
     nit: 8
   slack: array([  5.13245265e+01,   1.89309145e-08,   1.83429094e-09,   4.28687782e-09,   1.03726911e-08,   2.77000474e-09,
         1.41837413e+00,   6.75769654e-09,   8.65285462e-10,   2.78501844e-09,   3.09591539e-09,   5.27429006e+01,
         1.30944103e-08,   5.32994799e-09,   3.15369669e-08,   2.51943821e-09,   7.54848797e-09,   3.22510447e-09])
  status: 0
 success: True
       x: array([ -2.51938304e+01,   4.68432810e-01,   2.68398831e+01,   4.68432822e-01,   4.68432815e-01,   4.68432832e-01,
        -2.40754247e-01,   4.68432818e-01,   4.68432819e-01,   4.68432822e-01,  -2.56622633e+01,  -7.91749954e-09,
         2.63714503e+01,   4.40376624e-09,  -2.52137156e-09,   1.43834811e-08,  -7.09187065e-01,   3.95395716e-10,
         1.17990950e-09,   2.56622633e+01,   1.10134149e-08,   2.63714503e+01,   8.69064406e-09,   7.85131955e-09,
         1.71534858e-08,   7.09187068e-01,   7.15309226e-09,   2.04519496e-09])
x:  [-25.19383044   0.46843281  26.83988313   0.46843282   0.46843282   0.46843283  -0.24075425   0.46843282   0.46843282]
residual Ax-b:  [ -1.18067724e-08  -8.12879938e-04  -1.75969041e-03]
mean:  0.468432821891
x - mean:  [ -2.56622633e+01  -1.18805552e-08   2.63714503e+01   4.54189575e-10  -6.40499920e-09   1.04889573e-08  -7.09187069e-01
  -3.52642715e-09  -2.67771227e-09]
l1-norm(x - mean) / objective:  52.7429006758
 ECOS 2.0.4 - (C) embotech GmbH, Zurich Switzerland, 2012-15. Web: www.embotech.com/ECOS

It     pcost       dcost      gap   pres   dres    k/t    mu     step   sigma     IR    |   BT
 0  +2.637e-17  -1.550e+06  +7e+08  1e-01  2e-04  1e+00  2e+07    ---    ---    1  1  - |  -  -
 1  -8.613e+04  -1.014e+05  +8e+06  1e-03  2e-06  2e+03  2e+05  0.9890  1e-04   2  1  1 |  0  0
 2  -1.287e+03  -1.464e+03  +1e+05  1e-05  9e-08  4e+01  3e+03  0.9872  1e-04   3  1  1 |  0  0
 3  +1.794e+02  +1.900e+02  +2e+03  2e-07  1e-07  1e+01  5e+01  0.9890  5e-03   5  3  4 |  0  0
 4  -1.388e+00  -6.826e-01  +1e+02  1e-08  7e-08  9e-01  3e+00  0.9458  4e-03   7  6  6 |  0  0
 5  +5.491e+00  +5.683e+00  +1e+01  1e-09  8e-09  2e-01  3e-01  0.9617  6e-02   1  1  1 |  0  0
 6  +6.480e+00  +6.505e+00  +1e+00  2e-10  5e-10  3e-02  4e-02  0.8928  2e-02   1  1  1 |  0  0
 7  +6.746e+00  +6.746e+00  +2e-02  3e-12  5e-10  5e-04  6e-04  0.9890  5e-03   1  0  0 |  0  0
 8  +6.759e+00  +6.759e+00  +3e-04  2e-12  2e-10  6e-06  7e-06  0.9890  1e-04   1  0  0 |  0  0
 9  +6.759e+00  +6.759e+00  +3e-06  2e-13  2e-10  6e-08  8e-08  0.9890  1e-04   2  0  0 |  0  0
10  +6.758e+00  +6.758e+00  +3e-08  5e-14  2e-10  7e-10  9e-10  0.9890  1e-04   1  0  0 |  0  0

OPTIMAL (within feastol=2.0e-10, reltol=4.7e-09, abstol=3.2e-08).
Runtime: 0.002901 seconds.

Objective:  6.757722879805085
x:  [[-18.09169736  -5.55768047  11.12130645  11.48355878  -1.13982006
   12.4290884   -3.00165819  -1.05158589  -2.4468432 ]]
mean:  0.416074272576
Ax-b:
[[  2.17051777e-03]
 [  1.90734863e-06]
 [ -5.72204590e-06]]
x - mean:  [[-18.50777164  -5.97375474  10.70523218  11.0674845   -1.55589434
   12.01301413  -3.41773246  -1.46766016  -2.86291747]]
Objective:  785913288.2410747
x:  [[ -5.57966858e-08  -4.74997454e-08   1.56066068e+00   1.68021234e-07
   -3.55602958e-08   1.75340641e-06  -4.69609562e-08  -3.10216680e-08
   -4.39482554e-08]]
mean:  0.173406926909
Ax-b:
[[ -3.29341696e+03]
 [ -7.08072860e+08]
 [  3.41016903e+08]]
x - mean:  [[-0.17340698 -0.17340697  1.38725375 -0.17340676 -0.17340696 -0.17340517
  -0.17340697 -0.17340696 -0.17340697]]

你使这成为一个困难的NLP(不可微非线性规划问题)。我将把它表述为LP(线性规划);这样可以得到一个经验证的全局最优值。@Erwin.你如何在线性规划部分添加约束?我在回答中详细说明了我的建议。谢谢Sascha。我肯定已经接近了。我收到了以下错误消息:“优化失败。找不到可行的起点。”我提到了可能的问题和事情检查并执行。因此:(1)确保编辑边界后问题仍然可行(2)使用内部点解算器(它也检测不可行)(3)放弃lp硬约束方式并制定SOCP。谢谢sascha。我调整了我的边界并得到了我想要的答案。非常感谢!!嗨sascha,当我将边界设置为0到50时。它给我一个错误消息“算法成功终止并确定问题不可行”。你能帮我吗?是的…或者没有非否定ive x解决方案或者你遇到了数字问题。我都提到过。这是不可能从这里调试的,即使有时很难向人们解释为什么这和那不正确,如果他们不知道这些解决方案的内部结构。(我或多或少已经提到,您尝试优化的模型非常不稳定;Ax=b上的硬约束)