Подгонка с ограничениями функциональных параметров в Python - PullRequest
0 голосов
/ 11 января 2020

У меня есть некоторые данные {x_i,y_i}, и я хочу подобрать модельную функцию y=f(x,a,b,c), чтобы найти наилучшие подходящие значения параметров (a,b,c); однако три из них не являются полностью независимыми, но имеют ограничения на 1<b, 0<=c<1 и g(a,b,c)>0, где g - это "хорошая" функция. Как я могу реализовать это в Python, так как с помощью Curve_fit нельзя напрямую устанавливать ограничения параметри c?

Я читал с помощью lmfit, но я вижу только числовые ограничения, такие как 1<b, 0<=c<1, а не те, которые имеют g(a,b,c)>0, что является наиболее важным.

Ответы [ 2 ]

0 голосов
/ 13 января 2020

Если я правильно понимаю, у вас есть

def g(a,b,c):
    c1 = (1.0 - c)
    cx = 1/c1
    c2 = 2*c1
    g  = a*a*b*gamma(2+cx)*gamma(cx)/gamma(1+3/c2)-b*b/(1+b**c2)**(1/c2)
    return g

Если это так, и если вы правильно понимаете математику, это может быть представлено как

    a = sqrt((g+b*b/(1+b**c2)**(1/c2))*gamma(1+3/c2)/(b*gamma(2+cx)*gamma(cx)))

То есть вы может думать о вашей проблеме как о переменной g, которая> 0, и значении a, полученном из b, c и g с помощью Выражение выше.

И что вы можете сделать с lmfit и его механизмом ограничения на основе выражений. Вам нужно будет добавить функцию gamma, как с

  from lmfit import Parameters
  from scipy.special import gamma

  params = Parameters()
  params._asteval.symtable['gamma'] = gamma

, а затем установить параметры с границами и ограничениями. Я бы, вероятно, следовал приведенной выше математике, чтобы улучшить отладку и использовать что-то вроде:

  params.add('b', 1.5, min=1)
  params.add('c', 0.4, min=0, max=1)
  params.add('g', 0.2, min=0)
  params.add('c1', expr='1-c')
  params.add('cx', expr='1.0/c1')
  params.add('c2', expr='2*c1')
  params.add('gprod', expr='b*gamma(2+cx)*gamma(cx)/gamma(1+3/c2)')
  params.add('bfact', expr='(1+b**c2)**(1/c2)')
  params.add('a', expr='sqrt(g+b*b/(bfact*gprod))')

Обратите внимание, что это дает 3 фактические переменные (теперь g, b и c) с большим количеством производные значения рассчитаны из них, в том числе a. Я бы обязательно проверил всю эту математику. Похоже, вы в безопасности от negative**fractional_power, sqrt(negitive) и gamma(-1), но помните об этих возможностях, которые убьют подгонку.

Вы можете встроить все это в свою функцию подгонки, но использование выражений ограничений дает возможность ограничивать значения параметров независимо от того, как определена функция подгонки или модели.

Надеюсь, это поможет. Опять же, если это не соответствует тому, что вы пытаетесь сделать, опубликуйте более подробную информацию об ограничении, которое вы пытаетесь навязать.

0 голосов
/ 12 января 2020

Как и Джеймс Филлипс, я собирался предложить SciPy curve_fit. Но то, как вы определили свою функцию, одно из ограничений касается самой функции, а границы SciPy определяются только в терминах входных переменных.

Каковы, собственно, формы ваших функций? Можете ли вы преобразовать их так, чтобы вы могли использовать стандартное определение границ, а затем отменить преобразование, чтобы получить функцию в исходной форме, которую вы хотели?

Я столкнулся с связанной проблемой при попытке подгонки экспоненциальных регрессий используя SciPy curve_fit. Алгоритмы поиска параметров варьируются линейно, и действительно легко установить градиент sh. Если я напишу функцию, которая соответствует логарифму функции, которую я хочу, гораздо проще заставить функцию curve_fit работать. Затем, для моей последней работы, я возьму показатель моей подходящей функции.

Эта та же самая стратегия могла бы работать для вас. Прогноз ln (y) . Значение этой функции может быть неограниченным. Затем для вашего окончательного результата выведите exp (ln (y)) = y .

...