简体   繁体   English

用numpy linalg lstsq拟合复杂方程的曲线

[英]curve fitting complicated equation with numpy linalg lstsq

I have a complicated function of three parameters a,b,c and one argument, nu: 我有一个复杂的函数,其中包含三个参数a,b,c和一个参数nu: 在此处输入图片说明

Python code equivalent to this is: 与此等效的Python代码是:

a / (1 + (nu/b)**2)**(c/2)

I am used to using numpy linalg lsqst or the scipy equivalent to curve fit eg x, x^2, x^4, or orthogonal coefficients. 我习惯于使用numpy linalg lsqst或scipy等效于曲线拟合,例如x,x ^ 2,x ^ 4或正交系数。

In this case how do I build up the shape (3,len(nu)) first argument to lsqst? 在这种情况下,如何建立lsqst的形状(3,len(nu))第一个参数?

Since I cannot format code in a comment I have placed it here. 由于我无法在注释中设置代码格式,因此将其放在此处。 This is an all-nonlinear fitting and graphing example using your equation and scipy's curve_fit() on my test data. 这是一个全非线性拟合和图形化示例,在您的测试数据上使用您的方程式和scipy的curve_fit()。 The scipy.optimize.differential_evolution genetic algorithm module used to estimate initial parameters for the nonlinear solver. scipy.optimize.differential_evolution遗传算法模块,用于估计非线性求解器的初始参数。 This scipy module uses the Latin Hypercube algorithm to ensure a thorough search of parameter space and that algorithm requires parameter bounds within which to search - this example uses the max and min data values for those bounds. 此scipy模块使用Latin Hypercube算法来确保对参数空间的彻底搜索,并且该算法需要在参数范围内进行搜索-本示例使用这些范围的max和min数据值。 In your case, you may need to search different parameter bounds if you know what range of parameter values to expect. 对于您的情况,如果您知道期望的参数值范围,则可能需要搜索不同的参数范围。

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

xData = numpy.array([19.1647, 18.0189, 16.9550, 15.7683, 14.7044, 13.6269, 12.6040, 11.4309, 10.2987, 9.23465, 8.18440, 7.89789, 7.62498, 7.36571, 7.01106, 6.71094, 6.46548, 6.27436, 6.16543, 6.05569, 5.91904, 5.78247, 5.53661, 4.85425, 4.29468, 3.74888, 3.16206, 2.58882, 1.93371, 1.52426, 1.14211, 0.719035, 0.377708, 0.0226971, -0.223181, -0.537231, -0.878491, -1.27484, -1.45266, -1.57583, -1.61717])
yData = numpy.array([0.644557, 0.641059, 0.637555, 0.634059, 0.634135, 0.631825, 0.631899, 0.627209, 0.622516, 0.617818, 0.616103, 0.613736, 0.610175, 0.606613, 0.605445, 0.603676, 0.604887, 0.600127, 0.604909, 0.588207, 0.581056, 0.576292, 0.566761, 0.555472, 0.545367, 0.538842, 0.529336, 0.518635, 0.506747, 0.499018, 0.491885, 0.484754, 0.475230, 0.464514, 0.454387, 0.444861, 0.437128, 0.415076, 0.401363, 0.390034, 0.378698])


def func(nu, a, b, c):
    return  a / (1.0 + (nu/b)**2.0)**(c/2.0)


# function for genetic algorithm to minimize (sum of squared error)
def sumOfSquaredError(parameterTuple):
    warnings.filterwarnings("ignore") # do not print warnings by genetic algorithm
    val = func(xData, *parameterTuple)
    return numpy.sum((yData - val) ** 2.0)


def generate_Initial_Parameters():
    # min and max used for bounds
    maxX = max(xData)
    minX = min(xData)
    maxY = max(yData)
    minY = min(yData)

    maxXY = max(maxX, maxY)
    minXY = max(minX, minY)

    parameterBounds = []
    parameterBounds.append([minXY, maxXY]) # seach bounds for a
    parameterBounds.append([minXY, maxXY]) # seach bounds for b
    parameterBounds.append([minXY, maxXY]) # seach bounds for c

    # "seed" the numpy random number generator for repeatable results
    result = differential_evolution(sumOfSquaredError, parameterBounds, seed=3)
    return result.x

# generate initial parameter values
geneticParameters = generate_Initial_Parameters()

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

print('Parameters', fittedParameters)

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('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)

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

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