代码之家  ›  专栏  ›  技术社区  ›  Kevin

如何使用多个数组优化函数?

  •  2
  • Kevin  · 技术社区  · 6 年前

    给定数组 a , b c :

    import numpy as np
    
    a = np.array([100, 200, 300])
    b = np.array([[1, 0, 0],
                  [1, 0, 1],
                  [0, 1, 1],
                  [1, 1, 1]])
    c = np.array([150, 300, 500, 650])
    

    使每一个值使中定义的绝对差之和最小化 c_prime .

    c_prime = c - np.sum(a*b, axis=1)
    print(c_prime)
    print(np.abs(c_prime).sum())
    
    [  50 -100    0   50]
    200
    

    手动。。。通过更改 c\素数 开始达到预期的结果。

    a = np.array([150, 200, 300])
    
    c_prime = c - np.sum(a*b, axis=1)
    print(c_prime)
    print(np.abs(c_prime).sum())
    
    [   0 -150    0    0]
    150
    

    现在,我的问题,尴尬的是,我如何才能达到预期的结果? 我试过了 scipy.optimize.minimize ,但很明显,这段代码漏掉了标记,函数在概念上可能完全不正确。

    def f(x, b, c):
        return np.abs(c - np.sum(x*b, axis=1)).sum()
    
    x0 = a
    minimize(f, x0, args=(b,c))
    
          fun: 200.0
     hess_inv: array([[1, 0, 0],
           [0, 1, 0],
           [0, 0, 1]])
          jac: array([-1.,  0.,  1.])
      message: 'Desired error not necessarily achieved due to precision loss.'
         nfev: 327
          nit: 0
         njev: 63
       status: 2
      success: False
            x: array([100., 200., 300.])
    

    考虑到手动设置的改进结果 a[0] 150 x

    1 回复  |  直到 6 年前
        1
  •  3
  •   user2357112    6 年前

    这里的问题是你的目标函数是不可微的。SciPy默认为BFGS优化,它要求目标函数的一阶导数存在。

    我可以想出三种主要的方法来解决这个问题:使用无导数优化,使用目标函数的可微近似,或者将绝对值转化为约束。


    scipy.optimize.minimize 需要一个可微的目标函数。一些人没有,但即使这样,也不能保证他们能找到最小值。

    method='Nelder-Mead' 成功的优化结果和 x: array([ 149.99998103, 349.99999851, 150.00000599]) 在我的 test run x0=[1, 1, 1] 结果 convergence to a non-minimum


    目标函数的一个可微逼近是容易的,并且提供了更好的收敛性,但代价是一些错误。例如,替换 np.abs 具有

    def pseudoabs(x):
        return (x**2+0.1)**0.5
    

    results in convergence x: array([ 150.00000001, 350.00000011, 150.00000039])


    至于转换绝对值,你的问题几乎是一个标准的线性规划问题,但是目标函数中有绝对值。通过引入额外的变量, it's possible to convert an absolute value into two new linear constraints . 我们的想法是取代 |x| x' 受限条款 x' >= x x' >= -x .

    这样做可以让你用一个标准的线性规划求解器来解决你的问题 scipy.optimize.linprog scipy.优化.最小化


    除此之外,对于这种形式的优化问题,可能还有其他算法。我试着用谷歌搜索“l1优化”,就像“最小二乘优化”一样,但结果却是最小化了解向量的l1范数,这在这种情况下是错误的向量。