Некоторые оптимизаторы поддерживают ограничивающие ограничения (например, 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)]