«Scipy.optimize.minimize» Как заставить коэффициенты быть не нулевыми

1

Я пытаюсь подобрать функцию p которая зависит от двух переменных x, T Данные для p, T, x предоставляются через лист Excel с pandas. Следующий код работает довольно хорошо.

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 чтобы заставить все коэффициенты принять значение больше нуля?

Спасибо

  • 0
    У вас есть диапазон значений, которые вы хотите связать T или x ? Если это так, указание этого может привести к локальному минимуму с ненулевыми коэффициентами.
  • 0
    На самом деле я не очень понимаю, как работают границы. Если у меня есть что-то вроде этого, bnds = ((1, 0.1, 1),(300, 1, 67)) и bounds=bnds в строке minimize . Означает ли это bnds = ((Tmin, xmin, pmin),(Tmax, xmax, pmax)) ? Если это так, то, к сожалению, это не решает мою проблему.
Теги:
python-3.x
scipy
minimize

1 ответ

0
Лучший ответ

Некоторые оптимизаторы поддерживают ограничивающие ограничения (например, 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)]
  • 0
    Спасибо! Ваше решение с method='L-BFGS-B' работает нормально, но, к сожалению, метод не поддерживает ограничения, которые мне нужны для моего условия, где вывод функции везде положительный (см. def constr() ). С другой стороны, 'method =' cobyla'` не поддерживает границы. знак равно
  • 0
    Но вы дали мне хороший совет, чтобы посмотреть, как сформулировать границы в качестве ограничений stackoverflow.com/questions/12781622/… Так что спасибо за это!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню