简体   繁体   English

如何对实验数据进行非线性数据拟合

[英]How to do nonlinear data-fitting a function on the experiment data

I have some experiment data. 我有一些实验数据。 Hereby, I need to fit the following function to determine one of the variable. 因此,我需要拟合以下函数以确定变量之一。 A Levenberg–Marquardt least-squares algorithm was used in this procedure. 在此过程中使用了Levenberg-Marquardt最小二乘算法。

I have used curve fitting option in Igor Pro software. 我在Igor Pro软件中使用了曲线拟合选项。 I defined new fit function and tried to define independent and dependent variable. 我定义了新的拟合函数,并试图定义自变量和因变量。 Nevertheless, I don't know what is the reason that I got the this error: 但是,我不知道出现此错误的原因是什么:

"The fitting function returned INF for at least one X variable" “拟合函数为至少一个X变量返回了INF”

My function is : 我的职能是:

sin(theta) = -1+2*sqrt(alpha/x)*exp(-beta*(x-alpha)^2)

beta = 1.135e-4;

sin(theta) = [-0.81704 -0.67649 -0.83137 -0.73468 -0.66744 -0.43602 0.45368 0.75802 0.96705 0.99717 ]

x = [72.01 59.99 51.13 45.53 36.15 31.66 30.16 29.01 25.62 23.47 ]

Is there any suggestion to find alpha variable here? 有什么建议在这里找到alpha变量吗?

Is there any handy software or program for nonlinear curve fitting? 是否有用于非线性曲线拟合的便捷软件或程序

In gnuplot, it would look like this. 在gnuplot中,它看起来像这样。 The fit is not great, but that's not the "fault" of gnuplot, but apparently this data cannot be fitted with this function very well. 拟合度不是很好,但这不是gnuplot的“故障”,但是显然此数据无法很好地与该函数拟合。

Code: 码:

### nonlinear curve fitting
reset session

$Data <<EOD
72.01 -0.81704
59.99 -0.67649
51.13 -0.83137
45.53 -0.73468
36.15 -0.66744
31.66 -0.43602
30.16 0.45368
29.01 0.75802
25.62 0.96705
23.47 0.99717
EOD

f(x) = -1+2*sqrt(alpha/x)*exp(-beta*(x-alpha)**2)

# initial guessed values
alpha = 25
beta = 1
set fit nolog results
fit f(x) $Data u 1:2 via alpha,beta

plot $Data u 1:2 w lp pt 7, \
    f(x) lc rgb "red"

print sprintf("alpha=%g, beta=%g",alpha,beta)
### end of code

Result: 结果:

alpha=25.818, beta=0.0195229

在此处输入图片说明

If it might be of some use, my equation search on your data turned up a good fit to a standard 4-parameter logistic equation "y = d + (a - d) / (1.0 + pow(x / c, b))" with parameters a = 0.96207949, b = 44.14292256, c = 30.67324939, and d = -0.74830947 yielding RMSE = 0.0565 and R-squared = 0.9943, and I have included code for a Python graphical fitter using this equation. 如果可能有用,我对您数据的方程式搜索非常适合标准的四参数对数方程式“ y = d +(a-d)/(1.0 + pow(x / c,b))参数a = 0.96207949,b = 44.14292256,c = 30.67324939和d = -0.74830947,得出RMSE = 0.0565和R-squared = 0.9943,并且我已经使用此方程式包含了Python图形拟合程序的代码。

情节

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


theta = [-0.81704, -0.67649, -0.83137, -0.73468, -0.66744, -0.43602, 0.45368, 0.75802, 0.96705, 0.99717]
x = [72.01, 59.99, 51.13, 45.53, 36.15, 31.66, 30.16, 29.01, 25.62, 23.47]

# rename to match previous example code
xData = numpy.array(x)
yData = numpy.array(theta)

# StandardLogistic4Parameter equation from zunzun.com
def func(x, a, b, c, d):
    return  d + (a - d) / (1.0 + numpy.power(x / c, b))


# these are the same as the scipy defaults
initialParameters = numpy.array([1.0, 1.0, 1.0, 1.0])

# curve fit the test data
fittedParameters, pcov = curve_fit(func, xData, yData, initialParameters)

modelPredictions = func(xData, *fittedParameters) 

absError = modelPredictions - yData

SE = numpy.square(absError) # squared errors
MSE = numpy.mean(SE) # mean squared errors
RMSE = numpy.sqrt(MSE) # Root Mean Squared Error, RMSE
Rsquared = 1.0 - (numpy.var(absError) / numpy.var(yData))

print('Parameters:', fittedParameters)
print('RMSE:', RMSE)
print('R-squared:', Rsquared)

print()


##########################################################
# graphics output section
def ModelAndScatterPlot(graphWidth, graphHeight):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)
    axes = f.add_subplot(111)

    # first the raw data as a scatter plot
    axes.plot(xData, yData,  'D')

    # create data for the fitted equation plot
    xModel = numpy.linspace(min(xData), max(xData))
    yModel = func(xModel, *fittedParameters)

    # now the model as a line plot
    axes.plot(xModel, yModel)

    axes.set_xlabel('X Data') # X axis data label
    axes.set_ylabel('Y Data') # Y axis data label

    plt.show()
    plt.close('all') # clean up after using pyplot

graphWidth = 800
graphHeight = 600
ModelAndScatterPlot(graphWidth, graphHeight)

Matlab MATLAB

I slightly changed the function, -1 changed to -gamma and optimize to find gamma 我稍微更改了功能,将-1更改为-gamma并进行优化以查找gamma

The code is as follow 代码如下

ydata =  [-0.81704 -0.67649 -0.83137 -0.73468 -0.66744 -0.43602 0.45368...
    0.75802 0.96705 0.99717 ];
xdata = [72.01 59.99 51.13 45.53 36.15 31.66 30.16 29.01 25.62 23.47 ];

sin_theta = @(alpha, beta, gamma, xdata) -gamma+2.*sqrt(alpha./xdata).*exp(beta.*(xdata-alpha).^2);

%Fitting function as function of array(x) required by lsqcurvefit
f = @(x,xdata) sin_theta(x(1),x(2), x(3),xdata);
% [alpha, beta, gamma]
x0 = [25, 0, 1] ;

options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt', 'FunctionTolerance', 1e-30);


[x,resnorm,residual,exitflag,output] = lsqcurvefit(f,x0,xdata,ydata,[], [], options);

% Accuracy 
RMSE = sqrt(sum(residual.^2)/length(residual));

alpha = x(1); beta = x(2); gamma = x(3);

%Plotting data
data = linspace(xdata(1),xdata(end));
plot(xdata,ydata,'ro',data,f(x,data),'b-', 'linewidth', 3)
legend('Data','Fitted exponential')
title('Data and Fitted Curve')
set(gca,'FontSize',20)

Result 结果

alpha = 26.0582, beta = -0.0329, gamma = 0.7881 instead of 1, RMSE = 0.1498

Graph 图形 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM