包括多分散集合的概率密度在Langevin-Derivative函数的拟合中

时间:2017-06-19 15:41:15

标签: python model curve-fitting model-fitting

我知道以下内容需要耐心,我非常感谢您将给予的努力。

我有一个测量数据,它代表磁矩的导数:dM / dH。 M(H)曲线的良好数学模型是langevin函数:其中:

  

M(H)= 1 / coth(xi) - 1 / xi,xi = cte *Vi³

所以磁矩的导数可以从langevin函数导数的导数中得到:

  

dM / dH = 1 /xi² - 1 /(sinh²(xi))

对于拟合我使用此函数作为拟合函数:

    def langevinDeriv(xx):
        if not hasattr(xx, '__iter__'):
            xx = [ xx ]
        res = np.zeros(len(xx))
        eps = 1e-1
        for i in range(len(xx)):
            x = xx[i]
            if np.fabs(x) < eps:
                res[i] =  1./3. - x**2/15. + 2.* x**4 / 189. - x**6/675. + 2.* x**8 / 10395. - 1382. * x**10 / 58046625. + 4. * x**12 / 1403325.
            else:
                res[i] = (1./x**2 - 1./np.sinh(x)**2)
        return res     

并使用简单的最小二乘函数将误差降至最低。

这是我得到的:comparaison : fit and data

我想说,合身并不好,因为实际上我没有一个直径的粒子,而是具有不同直径的多分散合奏,因此具有不同的Langevin_derivative函数。

我的问题是,如何将直径的概率密度与我的拟合函数相结合,以便程序适合概率分布而不是单个Diameter Vi。概率密度的函数在这里给出: http://www.originlab.de/doc/LabTalk/ref/Lognpdf-func

1 个答案:

答案 0 :(得分:0)

所以我摆弄了一下。正如评论中所提到的,fit将永远不会给出超级结果,因为模型不会捕获末端信号的下降(以及图上的阶梯式行为)。然而,结果看起来比简单的Langevin衍生物要好得多。我基本上总结了具有不同颗粒体积的功能,提供了最大直径。您可以控制最大直径和使用的直径数,范围为0到最大直径。唯一的两个拟合参数是标准偏差和总振幅。详细说明,您必须小心缩放才能获得物理上有意义的结果。我已经在nd_max发现了我的缩放15,3就行了。我猜d_max应该比sn足够大,以便在对数正态分布的最大值附近有几个值。

enter image description here

import matplotlib
matplotlib.use('Qt5Agg')

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


def log_gauss(x,s):
    if x==0 or s==0:
        out=0
    else:
        exponent=-np.log(x)**2/(2*s**2)
        if abs(exponent)>100:
            out=0
        else:
        out=np.exp(exponent)/np.sqrt(2 * np.pi * x**2 * s**2)
return out

def langevin(x,epsilon=1e-4):
    if abs(x)<epsilon:
        out=x/3.-x**3/45.+2*x**5/945.
    else:
        out=1./np.tanh(x)-1./x
    return out

def langevin_d(x,epsilon=1e-4):
    if abs(x)<epsilon:
        out=1/3.-x**2/15.+2*x**4/189.
    elif abs(x)>100.:
        out= 1./x**2
    else:
        out=-1./np.sinh(x)**2+1./x**2
    return out

def langevin_d_distributed(h,s,n=25,dMax=10):
    diaList=np.linspace(.01,dMax,n)
    pdiaList=[log_gauss(d,s) for d in diaList]
    volList=[d**3 for d in diaList]
    dm=0
    for v,p in zip(volList,pdiaList):
        dm+=p*langevin_d(h*v)
    return dm

def residuals(parameters,dataPoint,n=25,dMax=10):
    a,s = abs(parameters)
    dist = [y -a*langevin_d_distributed(x,s,n=n,dMax=dMax) for x,y in dataPoint] 
    return dist

meas_x,meas_y=np.loadtxt('OBaPH.txt', delimiter=',',unpack=True)
meas_x=meas_x*300
meas_y=meas_y-min(meas_y)
hList=np.linspace(0,8,155)

langevinDList=[langevin_d(h) for h in hList]
langevinDList=np.array(langevinDList)/langevinDList[0]

distList_01=[langevin_d_distributed(h,.29) for h in hList]
distList_01=np.array(distList_01)/distList_01[0]

dataTupel=zip(meas_x,meas_y)
estimate = [1,0.29]
bestFitValues=dict()
myFit=dict()
for nnn,ddd in [(15,3),(15,1.5),(15,10),(5,3),(25,3)]:
    bestFitValues[(nnn,ddd)], ier = leastsq(residuals, estimate,args=(dataTupel,nnn,ddd))
    print bestFitValues[(nnn,ddd)]
    myFit[(nnn,ddd)]= [bestFitValues[(nnn,ddd)][0]*langevin_d_distributed(h,bestFitValues[(nnn,ddd)][1],n=nnn,dMax=ddd) for h in hList]

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

ax.plot(meas_x,meas_y,linestyle='',marker='o',label='rescaled data')
ax.plot(hList,langevinDList,label='Langevin')
ax.plot(hList,distList_01,label='log_norm test')
for key,val in myFit.iteritems():    
    ax.plot(hList,val,label=key)
ax.legend(loc=0)

plt.show()