对复杂方程式/数据进行lmfit最小化(或scipy.optimize Minimumsq)

时间:2019-02-14 23:49:32

标签: python optimization curve-fitting lmfit complex-data-types

编辑:
使用这种方法进行建模和拟合效果很好,这里的数据不好。
-------------------

我想对复杂的数据集进行曲线拟合。仔细阅读和搜索后,我发现我可以使用几种方法(例如lmfit优化,scipy Minimumsq)。

但是没有一个完全适合我。

这是拟合方程:

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 :(得分:0)

我建议先将复杂的数据转换为numpy数组,然后分别获取真实的imag对,然后使用lmfit Model建模相同类型的数据。也许是这样的:

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为负数(或者我可能会误解您的模型)。我并没有认真地努力使自己适应,但是我认为这应该可以帮助您入门。