Построение и моделирование данных с помощью lmfit - Fit не соответствует данным. Что я делаю неправильно?

У меня есть данные, которые я пытаюсь смоделировать с помощью модели lmfit.

В частности, я измеряю сверхпроводящие резисторы. Я пытаюсь подогнать экспериментальные данные (зависимость сопротивления от температуры) к модели, которая включает критическую температуру Tc (зависит от материала), сопротивление ниже Tc (номинально 0) и сопротивление выше Tc (зависит от конструкции).

Вот упрощенная версия (с смоделированными данными) кода, который я использую для построения моих данных вместе с графиком вывода.

Я не получаю никаких ошибок, но, как видите, я также не получаю соответствие, которое соответствует моим данным.

Что я делаю неправильно? Я впервые использую lmfit и Model, поэтому, возможно, совершаю ошибку новичка. Я подумал, что подписался на пример lmfit, но, как я уже сказал, я явно делаю что-то не так.

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


def main():
    x = np.linspace(0, 12, 50)
    x_ser = pd.Series(x)  # Simulated temperature data

    y1 = [0] * 20
    y2 = [10] * 30
    y1_ser = pd.Series(y1)  # Simulated resistance data below Tc
    y2_ser = pd.Series(y2)  # Simulated resistance data above Tc (
    y_ser = y1_ser.append(y2_ser, ignore_index=True)

    xcrit_model = Model(data_equation)
    params = xcrit_model.make_params(y1_guess=0, y2_guess=12, xcrit_guess=9)
    print('params: {}'.format(params))
    result = xcrit_model.fit(y_ser, params, x=x_ser)
    print(result.fit_report())

    plt.plot(x_ser, y_ser, 'bo', label='simulated data')
    plt.plot(x_ser, result.init_fit, 'k.', label='initial fit')
    plt.plot(x_ser, result.best_fit, 'r:', label='best fit')
    plt.legend()
    plt.show()


def data_equation(x, y1_guess, y2_guess, xcrit_guess):
    x_lt_xcrit = x[x < xcrit_guess]
    x_ge_xcrit = x[x >= xcrit_guess]
    y1 = [y1_guess] * x_lt_xcrit.size
    y1_ser = pd.Series(data=y1)
    y2 = [y2_guess] * x_ge_xcrit.size
    y2_ser = pd.Series(data=y2)

    y = y1_ser.append(y2_ser, ignore_index=True)

    return y

if __name__ == '__main__':
    main()

введите описание изображения здесь


person BobInBaltimore    schedule 03.06.2020    source источник


Ответы (1)


lmfit (и в основном все аналогичные решатели) работают с непрерывными переменными и исследуют, как они изменяют результат, внося крошечные изменения в значения параметров и наблюдая, как это влияет на это соответствие.

Но ваш параметр xcrit_guess используется только как дискретная переменная. Если его значение изменится с 9.0000 на 9.00001, посадка не изменится вообще.

Итак, в основном, не делайте:

x_lt_xcrit = x[x < xcrit_guess]
x_ge_xcrit = x[x >= xcrit_guess]

Вместо этого вы должны использовать более плавную сигмоидальную ступенчатую функцию. Фактически, lmfit имеет один из таких встроенных. Итак, вы можете попробовать что-то вроде этого (обратите внимание, нет смысла преобразовывать numpy.arrays в pandas.Series - код в любом случае просто вернет их обратно в массивы numpy):

import numpy as np
from lmfit.models import StepModel
import matplotlib.pyplot as plt

x = np.linspace(0, 12, 50)
y = 9.5*np.ones(len(x))
y[:26] = 0.0
y = y + np.random.normal(size=len(y), scale=0.0002)

xcrit_model = StepModel(form='erf')
params = xcrit_model.make_params(amplitude=4, center=5, sigma=1)

result = xcrit_model.fit(y, params, x=x)
print(result.fit_report())

plt.plot(x, y, 'bo', label='simulated data')
plt.plot(x, result.init_fit, 'k', label='initial fit')
plt.plot(x, result.best_fit, 'r:', label='best fit')
plt.legend()
plt.show()
person M Newville    schedule 03.06.2020
comment
Спасибо за информацию и предложения! И re: Series Я подозревал, что что-то подобное может иметь место, но данные приходят ко мне в виде серии pandas, поэтому было проще всего написать сценарий анализа для использования series. - person BobInBaltimore; 06.06.2020
comment
@BobInBaltimore с использованием pandas.Series в порядке, и lmfit преобразует их в массивы numpy, если вы этого не сделаете. - person M Newville; 06.06.2020
comment
@M Newville - Еще раз спасибо за вашу помощь. Я пометил ваш ответ как принятый. Я также просмотрел документацию lmfit StepModel. Я попробовал различные формы моделей. Линейная модель по умолчанию вызвала ошибку ValueError на моем этапе result = xcrit_model.fit (...), в то время как модель atan, похоже, выполняла обратную подгонку - высоко, когда я ожидал минимум, и низкий, когда я ожидал высокого. Я постараюсь разобраться в этом позже, в основном для собственного образования. Логистическая модель, похоже, дала результаты, более или менее идентичные предложенной вами модели ERF. Я буду придерживаться erf - person BobInBaltimore; 08.06.2020