我试图拟合一个函数p
,该函数取决于两个变量x
,T
。 p
,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
中是否有一种(简便)方法来强制所有系数接受大于零的值?谢谢
最佳答案
一些优化器支持对系数的限制约束(例如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)]
关于python - “scipy.optimize.minimize”如何强制系数不为零,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54867911/