Подгонка кривой в Python с использованием scipy.optimise curve_fit - PullRequest
0 голосов
/ 25 мая 2018

Как относительный новичок в Python, я изо всех сил пытаюсь понять (и поэтому использую) "curve_fit" из scipy.optimise

Я попробовал следующие ответы на предыдущие вопросы: python numpyаппроксимация кривой / scipy и аппроксимация экспоненциальной кривой с python , но, к сожалению, не получилось заставить его работать.

Поскольку это техническая проблема (работа с данными измерений на испытательном стенде) поэтому я знаю, что формула имеет формат Y = (X / A) + (X / B) ^ (1 / C), где A, B, C - это константы, которые необходимо найти

[Текущий код]

import numpy as np
from scipy.optimize import curve_fit

valY_list = [yyy1,yyy2,yyy3,yyy4]
valX_list = [xxx1,xxx2,xxx3,xxx4]

val_Y = np.array(valY_list)
val_X = np.array(valX_list)

def fit_func(val_X,A,B,C):
    return (val_X/A)+((val_X/B)^(1/C))

params = curve_fit(fit_func, val_X, val_Y)

[A,B,C] = params[0]

NB1: в действительности valY_list & valX_list имеют длину> 500 записей (хранятся как числа с плавающей запятой)

NB2: я также знаю, что значения A, B, Cдолжно быть в пределах определенного диапазона значений, чтобы я мог ограничить решение при выполнении оптимизации.

0,005

0,0 0,0001 Я понимаю, что мой код, вероятно, довольно элементарный,и, вероятно, многие вещи отсутствуют (или явно очевидные ошибки для опытного программиста!), поэтому я приношу свои извинения.Любая помощь будет оценена!

1 Ответ

0 голосов
/ 25 мая 2018

Для этой и других задач подбора кривой может оказаться полезным lmfit (https://lmfit.github.io/lmfit-py)). Он обеспечивает более высокий уровень интерфейса для подбора кривой, чем curve_fit, и имеет много удобных и расширенных опций для построения модели иработа с параметрами и статистикой подгонки.

С lmfit я бы предложил следующий подход:

import numpy as np
from scipy.optimize import curve_fit
from lmfit import Model

valY_list = [yyy1,yyy2,yyy3,yyy4]
valX_list = [xxx1,xxx2,xxx3,xxx4]

val_Y = np.array(valY_list)
val_X = np.array(valX_list)

def fit_func(x, a, b, c):
    return (a*x)+(b*x)**c

mymodel = Model(fit_func)

params = mymodel.make_params(a=10, b=1, c=100.0)

params['a'].min = 2.0
params['a'].max = 200.

params['b'].min = 0.002
params['b'].max = 1.e8

params['c'].min = 10.0
params['c'].max = 10000.0

result = mymodel.fit(val_Y, params, x=val_X)

print(result.fit_report())

for par_name, param in result.params.items():
    print(par_name, param.value, param.stderr)

Обратите внимание, что я немного изменил функцию вашей модели, чтобы использовать 1 / PARAM, и скорректировал границысоответственно (я думаю!). Напечатанный отчет о подгонке будет включать в себя статистику подбора, значения наилучшего подбора и стандартные ошибки для каждой из переменных. Также обратите внимание, что в lmfit эти параметры именуются в соответствии с именами аргументов вашей функции подбора, ичто мин / макс границы идут с объектом Parameter. Хотя в приведенном выше примере устанавливаются границы, вы также можете исправить любой из параметров, например (*):

params['c'].vary = False

И, если вы действительно хотите, чтобы вашA, B и C, вы можете сделать параметры для них как выражения с ограничениями:

params.add('A', expr='1/a')
params.add('B', expr='1/b')
params.add('C', expr='1/c')

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

Существует множество других функций и достойной документации и примеров, но с этого следует начать.

...