Как написать оболочку для исправления произвольных параметров в функции - PullRequest
0 голосов
/ 26 января 2019

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

def func(x, *p):
    assert len(p) % 2 == 0
    fval = 0
    for j in xrange(0, len(p), 2):
        fval += p[j]*np.exp(-p[j+1]*t)
    return fval

Например, допустим, я хочу p = [p1, p2, p3, p4], и я хочу, чтобы p2 и p3 были постоянными A и B (переход от подбора с 4 параметрами к подгонке с 2 параметрами).Я понимаю, что functools.partial не позволяет мне делать это, поэтому я хочу написать свою собственную обертку.Но у меня немного проблем с этим.Это то, что у меня есть до сих пор:

def fix_params(f, t, pars, fix_pars):
    # fix_pars = ((ind1, A), (ind2, B))
    new_pars = [None]*(len(pars) + len(fix_pars))
    for ind, fix in fix_pars:
        new_pars[ind] = fix
    for par in pars:
        for j, npar in enumerate(new_pars):
            if npar == None:
                new_pars[j] = par
                break
    assert None not in new_pars
    return f(t, *new_pars)

Проблема с этим, я думаю, в том, что scipy.optimize.curve_fit не будет хорошо работать с функцией, переданной через этот тип оболочки.Как мне обойти это?

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Так что я думаю, что у меня есть что-то работоспособное.Может быть, есть способ улучшить это.

Вот мой код (без обработки всех исключений):

def func(x, *p):
    fval = 0
    for j in xrange(0, len(p), 2):
        fval += p[j]*np.exp(-p[j+1]*x)
    return fval

def fix_params(f, fix_pars):
    # fix_pars = ((1, A), (2, B))
    def new_func(x, *pars):
        new_pars = [None]*(len(pars) + len(fix_pars))
        for j, fp in fix_pars:
            new_pars[j] = fp
        for par in pars:
            for j, npar in enumerate(new_pars):
                if npar is None:
                    new_pars[j] = par
                    break
        return f(x, *new_pars)
    return new_func

p1 = [1, 0.5, 0.1, 1.2]
pfix = ((1, 0.5), (2, 0.1))
p2 = [1, 1.2]

new_func = fix_params(func, pfix)

x = np.arange(10)
dat1 = func(x, *p1)
dat2 = new_func(x, *p2)

if (dat1==dat2).all()
    print "ALL GOOD"
0 голосов
/ 26 января 2019

Похоже, что вы хотите сделать, это карри? В Python вы можете сделать это с помощью внутренних функций.

Пример:

def foo(x):
    def bar(y):
        return x + y
    return bar

bar = foo(3)
print(type(bar))    # a function (of one variable with the other fixed to 3)
print(bar(8))       # 11
bar = foo(9)
print(bar(8))       # 17

Таким образом мы можем исправить x в функции x + y. Вы также можете поместить это в декоратор.

Вот сообщение в блоге, которое кто-то написал об этом: https://mtomassoli.wordpress.com/2012/03/18/currying-in-python/

Что касается того, что будет хорошо работать с внешними библиотеками, функция foo здесь вернет функцию. В Python функции являются объектами первого класса. Поэтому все, что вы дадите возвращенной функции, будет просто видеть ее как функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...