ValueError: невозможно определить количество подходящих параметров. «Проблема в подгонке кривой» - PullRequest
0 голосов
/ 11 ноября 2019

Я новичок в python, поэтому мои знания неадекватны. У меня есть файл данных с именем "tlove_cc_seq2_k2_NL3.dat". Я хочу подогнать кривую к данным. Код, который я использую, выглядит следующим образом: *

...

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    import math
    import pandas as pd
    import lmfit
    from lmfit import Model
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    from array import *

    def test(x, a, b, c): 
         return (a + b*math.log(x) + c*math.log(x)**2)

    func = np.vectorize(test)

    data_k2_2fl_NL3=np.loadtxt('tlove_cc_seq2_k2_NL3.dat')
    plt.plot(data_k2_2fl_NL3[:,8], data_k2_2fl_NL3[:,5], 'b-', label='data')
    popt, pcov = curve_fit(func, data_k2_2fl_NL3[:,8], data_k2_2fl_NL3[:,5])
    popt

    plt.plot(data_k2_2fl_NL3[:,8], func(data_k2_2fl_NL3[:,8], *popt), 'r-',
             label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))
    popt, pcov = curve_fit(func, data_k2_2fl_NL3[:,8], data_k2_2fl_NL3[:,5], bounds=(-20, 
    [30., 30., 20.5]))
    popt

    plt.plot(data_k2_2fl_NL3[:,8], func(data_k2_2fl_NL3[:,8], *popt), 'g--',
             label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    plt.show()

...

Я получаю следующую ошибку: *

... ValueError Traceback (последний последний вызов) в 13 #y = data [:, 1] 14 plt.plot (data_k2_2fl_NL3 [:, 8], data_k2_2fl_NL3 [:, 5], 'b-', метка= 'data') ---> 15 popt, pcov = curve_fit (func, data_k2_2fl_NL3 [:, 8], data_k2_2fl_NL3 [:, 5]) 16 popt 17

    ~/anaconda3/lib/python3.7/site-packages/scipy/optimize/minpack.py in curve_fit(f, xdata, 
    ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, **kwargs)
        678         args, varargs, varkw, defaults = _getargspec(f)
        679         if len(args) < 2:
    --> 680             raise ValueError("Unable to determine number of fit parameters.")
        681         n = len(args) - 1
        682     else:

    ValueError: Unable to determine number of fit parameters.

Как решить эту проблему? Спасибо.

Ответы [ 2 ]

1 голос
/ 11 ноября 2019

Кажется, что большинство проблем, с которыми вы столкнулись при использовании numpy против math. Для полноты и поскольку вы упомянули lmfit, чтобы сделать это с lmfit, вы можете использовать

import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model

def test(x, a, b, c): 
    return (a + b*np.log(x) + c*np.log(x)**2)

# create model from your model function
mymodel = Model(test)

# create initial set of named parameters from argument of your function
params = mymodel.make_params(a=0.5, b=1.1, c=0.5)

# Create some dummy data
x_data = np.linspace(1, 10, 10)
y_data = np.log(x_data) + np.log(x_data)**2 + np.random.random(len(x_data))

# run fit, get result
result = mymodel.fit(y_data, params, x=x_data)

# print out full fit report: fit statistics, best-fit values, uncertainties
print(result.fit_report())

# make a stacked plot of residual and data + fit
result.plot()
plt.show()

Обратите внимание, что curve_fit() с радостью примет неинициализированные параметры, назначив значение по умолчанию, которое невозможно оправдатьзначение 1 для всех параметров. Lmfit не позволяет этого и заставляет вас явно устанавливать начальные значения. Но он также лучше отражает статистику, неопределенности и позволяет составлять более сложные модели.

Для вашего примера отчет о подгонке будет иметь вид

[[Model]]
    Model(test)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 8
    # data points      = 10
    # variables        = 3
    chi-square         = 0.91573485
    reduced chi-square = 0.13081926
    Akaike info crit   = -17.9061352
    Bayesian info crit = -16.9983799
[[Variables]]
    a:  0.69752193 +/- 0.34404583 (49.32%) (init = 0.5)
    b:  1.17700278 +/- 0.59765274 (50.78%) (init = 1.1)
    c:  0.85298657 +/- 0.23838141 (27.95%) (init = 0.5)
[[Correlations]] (unreported correlations are < 0.100)
    C(b, c) = -0.961
    C(a, b) = -0.782
    C(a, c) =  0.607

и график

enter image description here

0 голосов
/ 11 ноября 2019

Я думаю, что проблема в том, что функция curve_fit не может определить количество параметров путем самоанализа, потому что функция, которую вы запрашиваете, чтобы она соответствовала (test), заключена в функцию np.vectorize.

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

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def test(x, a, b, c): 
        return (a + b*np.log(x) + c*np.log(x)**2)

func = np.vectorize(test)

#Create some dummy data
x_data = list(range(1, 11))
y_data = np.log(x_data) + np.log(x_data)**2 + np.random.random(10)

plt.plot(x_data, y_data, 'b-', label='data')
popt, pcov = curve_fit(test, x_data, y_data)
popt

Если вам нужно vectorize по соображениям производительности, вы также можете передать параметр p0 массивисходных параметров. Например:

popt, pcov = curve_fit(func, x_data, y_data, p0=[1,1,1])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...