曲线拟合方程python

时间:2018-06-05 14:28:46

标签: python curve-fitting lmfit circuit-diagram

我正在尝试使用导纳等式拟合数据,用于具有6个分量的rlc电路。我正在关注给出he[fit] 1的示例并插入我的等式。该等式是使用Mathcad简化的6分量电路导纳的实部。在附图中,x轴是欧米茄(w = 2 * pi * f),y是毫西门子的导纳。

该程序运行但尽管具有良好的试验功能,它仍然没有进行拟合。我感谢任何帮助为什么合身是一条直线。我还附上了一个高斯拟合的例子。

fit

这是我在尝试使用等式时得到的结果。数据是左边较小峰值的数据,试验函数是虚线。拟合是一条直线

enter image description here

from numpy import sqrt, pi, exp, linspace, loadtxt
from lmfit import  Model

import matplotlib.pyplot as plt

data = loadtxt("C:/Users/susu/circuit_eq_real5.dat")
x = data[:, 0]
y = data[:, 1]

def circuit(x,C0,Cm,Lm,Rm,R0,Rs):


    return ((C0**2*Cm**2*Lm**2*R0*x**4)+(Rs*C0**2*Cm**2*Lm**2*x**4)+(C0**2*Cm**2*R0**2*Rm*x**2)+(Rs*C0**2*Cm**2*R0**2*x**2)+(C0**2*Cm**2*R0*Rm**2*x**2)+(2*Rs*C0**2*Cm**2*R0*Rm*x**2)+(Rs*C0**2*Cm**2*Rm**2*x**2)-(2*C0**2*Cm*Lm*R0*x**2)-(2*Rs*C0**2*Cm*Lm*x**2)+(C0**2*R0)+(Rs*C0**2)-(2*Rs*C0*Cm**2*Lm*x**2)+(2*Rs*C0*Cm)+(Cm**2*Rm)+(Rs*Cm**2))/((C0**2*Cm**2*Lm**2*x**4)+(C0**2*Cm**2*R0**2*x**2)+(2*C0**2*Cm**2*R0*Rm*x**2)+(C0**2*Cm**2*Rm**2*x**2)-(2*C0**2*Cm*Lm*x**2)+(C0**2)-(2*C0*Cm**2*Lm*x**2)+(2*C0*Cm)+(Cm**2))

gmodel = Model(circuit)
result = gmodel.fit(y, x=x, C0=1.0408*10**(-12), Cm=5.953*10**(-14), 
Lm=1.475*10**(-7), Rm=1.571, R0=2.44088, Rs=0.42)

print(result.fit_report())

plt.plot(x, y,         'bo')
plt.plot(x, result.init_fit, 'k--')
plt.plot(x, result.best_fit, 'r-')
plt.show()

以下是适合报告

 [[Fit Statistics]]
# fitting method   = leastsq
# function evals   = 14005
# data points      = 237
# variables        = 6
chi-square         = 32134074.5
reduced chi-square = 139108.548
Akaike info crit   = 2812.71607
Bayesian info crit = 2833.52443
[[Variables]]
C0: -7.5344e-15 +/- 6.3081e-09 (83723736.65%) (init = 1.0408e-12)
Cm: -8.9529e-13 +/- 1.4518e-06 (162164237.47%) (init = 5.953e-14)
Lm:  2.4263e-06 +/- 1.94051104 (79978205.20%) (init = 1.475e-07)
Rm: -557.974399 +/- 1.3689e+09 (245334051.75%) (init = 1.571)
R0: -5178.53517 +/- 6.7885e+08 (13108904.45%) (init = 2.44088)
Rs:  2697.67659 +/- 7.3197e+08 (27133477.70%) (init = 0.42)
[[Correlations]] (unreported correlations are < 0.100)
C(R0, Rs) = -1.003
C(Rm, Rs) = -0.987
C(Rm, R0) =  0.973
C(C0, Lm) =  0.952
C(C0, Cm) = -0.502
C(Cm, R0) = -0.483
C(Cm, Rs) =  0.453
C(Cm, Rm) = -0.388
C(Cm, Lm) = -0.349
C(C0, R0) =  0.310
C(C0, Rs) = -0.248
C(C0, Rm) =  0.148

非常感谢M Newville和Mikuszefski等人的见解和反馈。我同意我把它放在一个程序中可能是一团糟。从python代码可以明显看出,我不熟悉Python或编程。

Mikuszefsky,感谢发布rlc示例代码。你的方法很整洁有趣。我不知道Python确实指向复杂的拟合。我会尝试你的方法,看看能否做到合适。我想要适合Y(入场)的实部和虚部。我肯定会被卡在某处,并会在这里发布我的进展。 最好, 素素

2 个答案:

答案 0 :(得分:4)

这是一种用并联和串联连接清理RLC电路的方法。这避免了这种超长线并且难以检查功能。它还避免使用Matlab或类似程序,因为它直接计算电路。当然,它可以很容易地扩展OP的电路。正如M Newville所指出的,简单的契合失败了。另一方面,如果单位被缩放到自然单位,即使没有初始参数,它也可以工作。注意,结果通过缩放因子是正确的。人们需要知道至少一个组件值。

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

def r_l( w, l ):
    return 1j * w * l

def r_c( w, c ):
    return 1. / ( 1j * w * c )

def parallel( a, b ):
    return( 1. / ( 1./ a + 1. / b ) )

def series( a, b ):
    return a + b

# simple rlc band pass filter (to be extended)
def rlc_band( w , r, l, c ):
    lc = parallel( r_c( w , c ), r_l( w, l ) )
    return lc / series( r, lc )

def rlc_band_real( w , r, l, c ):
    return rlc_band( w , r, l, c ).real

def rlc_band_real_milli_nano( w , r, l, c ):
    return rlc_band_real( w , r, 1e-6 * l, 1e-9 * c ).real

wList = np.logspace( 5, 7, 25 )
wFullList = np.logspace( 5, 7, 500 )
rComplexList = np.fromiter( ( rlc_band(w, 12, 1.3e-5, 1e-7 ) for w in wList ), np.complex )
rList = np.fromiter( ( r.real for r in rComplexList ), np.float )
pList = np.fromiter( ( np.angle( r ) for r in rComplexList ), np.float )

fit1, pcov = curve_fit( rlc_band_real, wList, rList )
print fit1
print "does not work"

fit2, pcov = curve_fit( rlc_band_real_milli_nano, wList, rList )
print fit2
print "works, but is not unique (scaling is possible)"
print 12, fit2[1] * 12 / fit2[0], fit2[2] * fit2[0] / 12.

fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )

ax.plot( wList, rList , ls='', marker='o', label='data')
#~ ax.plot( wList, pList )
ax.plot( wFullList, [ rlc_band_real( w , *fit1 ) for w in wFullList ], label='naive fit')
ax.plot( wFullList, [ rlc_band_real_milli_nano( w , *fit2 ) for w in wFullList ], label='scaled units')
ax.set_xscale('log')
ax.legend( loc=0 )

plt.show()

提供了:

>> /...minpack.py:785: OptimizeWarning: Covariance of the parameters could not be estimated category=OptimizeWarning)
>> [1. 1. 1.]
>> does not work
>> [ 98.869924   107.10908434  12.13715912]
>> works, but is not unique (scaling is possible)
>> 12 13.0 100.0

fit in log scale

答案 1 :(得分:1)

提供您正在使用的实际数据的文本文件的真实链接和/或您实际看到的实际情节将是最有帮助的。另外,请提供准确完整的结果说明,包括print(result.fit_report())实际打印出来的内容。基本上,问问自己如何尝试帮助提出这样问题的人,并提供尽可能多的信息。

没有人(包括你)能够拼写检查你的功能的实现。您将需要对此功能进行全面而强大的测试,以说服任何人(包括您,我希望)它正在做您认为应该做的事情。您应该先提供这些测试的结果,然后再担心它为什么不能作为拟合函数。你绝对应该考虑将一个方程式的混乱重构为更易于管理和可读的部分。

那就是说,我也强烈建议您不要使用Farads和Henrys,而是使用picoFarads或nanoFarads和microHenrys。这将使值更接近于1(例如,顺序为1e-6到1e + 6),这将使其更容易完成其工作。