lmfit минимизирует (или scipy.optimize leastsq) на сложное уравнение / данные - PullRequest
0 голосов
/ 15 февраля 2019

Редактировать:
Моделирование и подгонка с этим подходом работают нормально, данные здесь не очень хорошие.
-------------------

Я хочу сделать подгонку кривой для сложного набора данных.После тщательного прочтения и поиска я обнаружил, что могу использовать несколько методов (например, lmfit optimize, scipy leastsq).

Но ни один из них не подходит мне совсем.

вотуравнение подгонки:

enter image description here

вот данные, которые нужно установить (список значений y):

[(0.00011342104914066835+8.448890220616275e-07j),
 (0.00011340386404065371+7.379293582429708e-07j),
 (0.0001133540327309949+6.389834505824625e-07j),
 (0.00011332170913939336+5.244566142401774e-07j),
 (0.00011331311156154074+4.3841061618015007e-07j),
 (0.00011329383047059048+3.6163513508002877e-07j),
 (0.00011328700094846502+3.0542249453666894e-07j),
 (0.00011327650033983806+2.548725558622188e-07j),
 (0.00011327702539337786+2.2508174567697671e-07j),
 (0.00011327342238146558+1.9607648998100523e-07j),
 (0.0001132710747364799+1.721721661949941e-07j),
 (0.00011326933241850936+1.5246061350710235e-07j),
 (0.00011326798040984542+1.3614817802178457e-07j),
 (0.00011326752037650585+1.233483784504962e-07j),
 (0.00011326758290166552+1.1258801448459512e-07j),
 (0.00011326813100914905+1.0284749122099354e-07j),
 (0.0001132684076390416+9.45791423595816e-08j),
 (0.00011326982474882009+8.733105218572698e-08j),
 (0.00011327158639135678+8.212191452217794e-08j),
 (0.00011327366823516856+7.747920115589205e-08j),
 (0.00011327694366034208+7.227069986108343e-08j),
 (0.00011327915327873038+6.819405851172907e-08j),
 (0.00011328181165961218+6.468392148750885e-08j),
 (0.00011328531688122571+6.151393311227958e-08j),
 (0.00011328857849500441+5.811704586613896e-08j),
 (0.00011329241716561626+5.596645863242474e-08j),
 (0.0001132970129528527+5.4722461511610696e-08j),
 (0.0001133002881788021+5.064523218904898e-08j),
 (0.00011330507671740223+5.0307457368330284e-08j),
 (0.00011331106068787993+4.7703959367963307e-08j),
 (0.00011331577350707601+4.634615394867111e-08j),
 (0.00011332064001939156+4.6914747648361504e-08j),
 (0.00011333034985824086+4.4992151257444304e-08j),
 (0.00011334188526870483+4.363662798446445e-08j),
 (0.00011335491299924776+4.364164366097129e-08j),
 (0.00011337451201475147+4.262881852644385e-08j),
 (0.00011339778209066752+4.275096587356569e-08j),
 (0.00011342832992628646+4.4463907608604945e-08j),
 (0.00011346526768580432+4.35706649329342e-08j),
 (0.00011351108008292451+4.4155812379491554e-08j),
 (0.00011356967192325835+4.327004709646922e-08j),
 (0.00011364164970635006+4.420660396556604e-08j),
 (0.00011373150199883139+4.3672898914161596e-08j),
 (0.00011384660942003356+4.326171366194325e-08j),
 (0.00011399193321804955+4.1493065523925126e-08j),
 (0.00011418043916260295+4.0762418512759096e-08j),
 (0.00011443271767970721+3.91359909722939e-08j),
 (0.00011479600563688605+3.845666332695652e-08j),
 (0.0001153652105925112+3.6224677316584614e-08j),
 (0.00011638635682516399+3.386843079212692e-08j),
 (0.00011836223959714231+3.6692295450490655e-08j)]


вот список значений x:

[999.9999960000001,
 794.328231,
 630.957342,
 501.18723099999994,
 398.107168,
 316.22776400000004,
 251.188642,
 199.52623,
 158.489318,
 125.89254,
 99.999999,
 79.432823,
 63.095734,
 50.118722999999996,
 39.810717,
 31.622776,
 25.118864000000002,
 19.952623000000003,
 15.848932000000001,
 12.589253999999999,
 10.0,
 7.943282000000001,
 6.309573,
 5.011872,
 3.981072,
 3.1622779999999997,
 2.511886,
 1.9952619999999999,
 1.584893,
 1.258925,
 1.0,
 0.7943279999999999,
 0.630957,
 0.5011869999999999,
 0.398107,
 0.316228,
 0.251189,
 0.199526,
 0.15848900000000002,
 0.125893,
 0.1,
 0.079433,
 0.063096,
 0.050119,
 0.039811,
 0.031623000000000005,
 0.025119,
 0.019953,
 0.015849000000000002,
 0.012589,
 0.01]


и вот код, который работает, но не так, как я хочу:

import numpy as np
import matplotlib.pyplot as plt
from lmfit import minimize, Parameters

#%% the equation
def ColeCole(params, fr): #fr is x values array and params are the fitting parameters 
    sig0 = params['sig0']
    m = params['m']
    tau = params['tau']
    c = params['c']
    w = fr*2*np.pi
    num = 1
    denom = 1+(1j*w*tau)**c
    sigComplex = sig0*(1.0+(m/(1-m))*(1-num/denom))
    return sigComplex

def res(params, fr, data): #calculating reseduals of fit
    resedual = ColeCole(params, fr) - data
    return resedual.view(np.float)

#%% Adding model parameters and fitting 
params = Parameters()
params.add('sig0', value=0.00166)
params.add('m', value=0.19,)
params.add('tau', value=0.05386)
params.add('c', value=0.80)

params['tau'].min = 0 # these conditions must be met but even if I remove them the fit is ugly!!
params['m'].min = 0

out= minimize(res, params , args= (np.array(fr2), np.array(data)))

#%%plotting Imaginary part

fig, ax = plt.subplots()

plotX = fr2
plotY = data.imag
fitplot = ColeCole(out.params, fr2)
ax.semilogx(plotX,plotY,'o',label='imc')
ax.semilogx(plotX,fitplot.imag,label='fit')
#%%plotting real part
fig2, ax2 = plt.subplots()

plotX2 = fr2
plotY2 = data.real
fitplot2 = ColeCole(out.params, fr2)
ax2.semilogx(plotX2,plotY2,'o',label='imc')
ax2.semilogx(plotX2,fitplot2.real,label='fit')


Я мог бы делатьэто совершенно неправильно, пожалуйста, помогите мне, если вы знаете правильное решение для подбора кривой на сложных данных.

1 Ответ

0 голосов
/ 15 февраля 2019

Я бы предложил сначала преобразовать сложные данные в массивы и получить реальные пары imag отдельно, а затем использовать модель lmfit для моделирования данных такого же типа.Возможно, что-то вроде этого:

cdata = np.array((0.00011342104914066835+8.448890220616275e-07j,
             0.00011340386404065371+7.379293582429708e-07j,
             0.0001133540327309949+6.389834505824625e-07j,
             0.00011332170913939336+5.244566142401774e-07j,
             0.00011331311156154074+4.3841061618015007e-07j,
             0.00011329383047059048+3.6163513508002877e-07j,
             0.00011328700094846502+3.0542249453666894e-07j,
             0.00011327650033983806+2.548725558622188e-07j,
             0.00011327702539337786+2.2508174567697671e-07j,
             0.00011327342238146558+1.9607648998100523e-07j,
             0.0001132710747364799+1.721721661949941e-07j,
             0.00011326933241850936+1.5246061350710235e-07j,
             0.00011326798040984542+1.3614817802178457e-07j,
             0.00011326752037650585+1.233483784504962e-07j,
             0.00011326758290166552+1.1258801448459512e-07j,
             0.00011326813100914905+1.0284749122099354e-07j,
             0.0001132684076390416+9.45791423595816e-08j,
             0.00011326982474882009+8.733105218572698e-08j,
             0.00011327158639135678+8.212191452217794e-08j,
             0.00011327366823516856+7.747920115589205e-08j,
             0.00011327694366034208+7.227069986108343e-08j,
             0.00011327915327873038+6.819405851172907e-08j,
             0.00011328181165961218+6.468392148750885e-08j,
             0.00011328531688122571+6.151393311227958e-08j,
             0.00011328857849500441+5.811704586613896e-08j,
             0.00011329241716561626+5.596645863242474e-08j,
             0.0001132970129528527+5.4722461511610696e-08j,
             0.0001133002881788021+5.064523218904898e-08j,
             0.00011330507671740223+5.0307457368330284e-08j,
             0.00011331106068787993+4.7703959367963307e-08j,
             0.00011331577350707601+4.634615394867111e-08j,
             0.00011332064001939156+4.6914747648361504e-08j,
             0.00011333034985824086+4.4992151257444304e-08j,
             0.00011334188526870483+4.363662798446445e-08j,
             0.00011335491299924776+4.364164366097129e-08j,
             0.00011337451201475147+4.262881852644385e-08j,
             0.00011339778209066752+4.275096587356569e-08j,
             0.00011342832992628646+4.4463907608604945e-08j,
             0.00011346526768580432+4.35706649329342e-08j,
             0.00011351108008292451+4.4155812379491554e-08j,
             0.00011356967192325835+4.327004709646922e-08j,
             0.00011364164970635006+4.420660396556604e-08j,
             0.00011373150199883139+4.3672898914161596e-08j,
             0.00011384660942003356+4.326171366194325e-08j,
             0.00011399193321804955+4.1493065523925126e-08j,
             0.00011418043916260295+4.0762418512759096e-08j,
             0.00011443271767970721+3.91359909722939e-08j,
             0.00011479600563688605+3.845666332695652e-08j,
             0.0001153652105925112+3.6224677316584614e-08j,
             0.00011638635682516399+3.386843079212692e-08j,
             0.00011836223959714231+3.6692295450490655e-08j))

fr = np.array((999.9999960000001, 794.328231, 630.957342,
          501.18723099999994, 398.107168, 316.22776400000004,
          251.188642, 199.52623, 158.489318, 125.89254, 99.999999,
          79.432823, 63.095734, 50.118722999999996, 39.810717,
          31.622776, 25.118864000000002, 19.952623000000003,
          15.848932000000001, 12.589253999999999, 10.0,
          7.943282000000001, 6.309573, 5.011872, 3.981072,
          3.1622779999999997, 2.511886, 1.9952619999999999, 1.584893,
          1.258925, 1.0, 0.7943279999999999, 0.630957,
          0.5011869999999999, 0.398107, 0.316228, 0.251189, 0.199526,
          0.15848900000000002, 0.125893, 0.1, 0.079433, 0.063096,
          0.050119, 0.039811, 0.031623000000000005, 0.025119, 0.019953,
          0.015849000000000002, 0.012589, 0.01))


data = np.concatenate((cdata.real, cdata.imag))

# model function for lmfit
def colecole_function(x, sig0, m, tau, c):
    w = x*2*np.pi
    denom = 1+(1j*w*tau)**c
    sig = sig0*(1.0+(m/(1.0-m))*(1-1.0/denom))
    return np.concatenate((sig.real, sig.imag))


mod = Model(colecole_function)
params = mod.make_params(sig0=0.002, m=-0.19, tau=0.05, c=0.8)

params['tau'].min = 0

result = mod.fit(data, params, x=fr)

print(result.fit_report())

Затем вы захотите отобразить результаты как nf = len (fr) plt.plot (fr, data [: nf], label = 'data (real)')plt.plot (fr, result.best_fit [: nf], label = 'fit (real)')

и аналогично

plt.plot(fr, data[nf:], label='data(imag)')
plt.plot(fr, result.best_fit[nf:], label='fit(imag)')

Обратите внимание, что вы, вероятно, захотитеразрешить m быть отрицательным (или, возможно, я неправильно понимаю вашу модель).Я не работал тщательно, чтобы получить хорошую форму, но я думаю, что это должно помочь вам начать.

...