【问题标题】:"scipy.optimize.minimize" How to force the coefficients to be not zero“scipy.optimize.minimize”如何强制系数不为零
【发布时间】:2019-07-18 22:59:14
【问题描述】:

我正在尝试拟合一个函数 p,它取决于两个变量 x,Tp,T,x 的数据通过带有pandas 的 Excel 工作表提供。以下代码运行良好。

import pandas as pd
import os
from scipy.optimize import minimize
import numpy as np

df = pd.read_excel(os.path.join(os.path.dirname(__file__), "./DataTest.xlsx"))
df = df.sort_values('x')

T = np.array(df['T'], dtype=float)
x = np.array(df['x'], dtype=float)
p = np.array(df['p'], dtype=float)
p0 = 67.17

def cav2(pars, T, x): # function p(T,x)
    a,b,c,d,e,f = pars
    return x * p0 + x * (1 - x) * (a + b * T + c * T ** 2 + d * x + e * x * T + f * x * T ** 2) * p0

def resid(pars, T, x):
    return ((p - cav2(pars, T, x)) ** 2).sum()

def constr(pars):
    return np.gradient(cav2(pars, T, x))

con1 = {'type': 'ineq', 'fun': constr}
pars0 = np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1], dtype=float)
res = minimize(resid, pars0, args=(T, x), method='cobyla', options={'maxiter': 50000}, constraints=con1)

print("a = %f , b = %f, c = %f, d = %f, e = %f, f = %f" % (res.x[0], res.x[1], res.x[2], res.x[3], res.x[4], res.x[5]))

最后一个print给了我函数的系数:

a = 2.891584 , b = 0.000000, c = -0.000000, d = 0.792256, e = -0.000000, f = 0.000000

这让我想到了我的实际问题。因为一些系数变为零,它使函数p(T,x) 独立于T,这是我不想要的。需要明确的是,目前cav2(res.x, 300, 0.1) 给出的结果与例如cav2(res.x, 500, 0.1) 相同。

scipy.optimize.minimize 中是否有一种(简单的)方法可以强制所有系数接受大于零的值?

谢谢

【问题讨论】:

  • 您是否有希望绑定Tx 的值范围?如果是这样,指定它可能会产生具有非零系数的局部最小值。
  • 实际上我不太了解界限是如何工作的。如果我在minimize 行中有类似bnds = ((1, 0.1, 1),(300, 1, 67))bounds=bnds 的内容。这代表bnds = ((Tmin, xmin, pmin),(Tmax, xmax, pmax)) 吗?如果是这样,不幸的是它并不能解决我的问题。

标签: python python-3.x scipy minimize


【解决方案1】:

一些优化器支持对系数的约束(例如 L-BFGS-B)。

import pandas as pd
import os
from scipy.optimize import minimize
import numpy as np

T = np.random.normal(10)
x = np.random.normal(10)

p0 = 67.17

# Fake true parameters
a, b, c, d, e, f = np.random.uniform(-1, 1, size=6)

# targets
p = x * p0 + x * (1 - x) * (a + b * T + c * T ** 2 + d * x + e * x * T + f * x * T ** 2) * p0


def cav2(pars, T, x): # function p(T,x)
    a, b, c, d, e, f = pars
    return x * p0 + x * (1 - x) * (a + b * T + c * T ** 2 + d * x + e * x * T + f * x * T ** 2) * p0


def resid(pars, T, x):
    return ((p - cav2(pars, T, x)) ** 2).sum()


def constr(pars):
    return np.gradient(cav2(pars, T, x))

# this will force all parameters to be positive
bounds = [(0, None), (0, None), (0, None), (0, None), (0, None), (0, None)]
pars0 = np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1], dtype=float)

res = minimize(resid, pars0, args=(T, x), method='L-BFGS-B', options={'maxiter': 50000}, bounds=bounds)

print("a = %f , b = %f, c = %f, d = %f, e = %f, f = %f" % (res.x[0], res.x[1], res.x[2], res.x[3], res.x[4], res.x[5]))

边界的工作方式是(lower, upper),设置None 意味着没有应用边界。因此,如果您不想在第一个参数上设置边界,例如,您可以将边界替换为:

[(None, None), (0, None), (0, None), (0, None), (0, None), (0, None)]

【讨论】:

  • 谢谢!您使用method='L-BFGS-B' 的解决方案可以正常工作,但不幸的是,该方法不支持约束,我需要在函数的推导处处为正的情况下(参见def constr())。另一方面,'method='cobyla'` 不支持边界。 =(
  • 但是你给了我一个很好的提示,让我看看如何将边界公式化为约束stackoverflow.com/questions/12781622/… 所以谢谢你!
猜你喜欢
  • 2018-07-23
  • 2018-07-03
  • 2018-02-17
  • 2017-01-07
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多