非线性拟合

先用

\[ f(x)=8\sin(x)\exp(x)-\frac{12}{\ln(x)} \]

生成数据。

然后给以上数据一些随机扰动:

\[ g(x) = f(x) + rnd \]

扰动\(rnd \in [-8000,8000]\)。

设置模型如下:

\[ p_{1}\sin(x)\exp(x)+\frac{p_{2}}{\ln(x)} \]

nlpfit

其解是\(p = [ 7.3725843942648,19.999999999999 ]^{T}\),相关系数是\(0.97885363869532\),残差平方和是\(464521063.49528\)。

随机扰动的取值范围越小,相关系数越接近于\(1\),\(p\)值也越接近\(8\)和\(-12\),残差平方和越小。当扰动为零时,拟合模型与生成数据的\(f(x)\)完全重合。

local print = require('package.print'). print
local plt = require('package.plot')
local mol = libminoptlab

local xdat = mol.matrix.linspace(2,10,20)

function f(x)
	return 8*math.sin(x)*math.exp(x)-12/math.log(x)
end

local rnd = mol.random.new(-8000,8000)

function g(x)
	return f(x)+rnd:generate()
end

local ydat1 = mol.apply(xdat:tovector(),f)
local ydat2 = mol.apply(xdat:tovector(),g)

function model(x,p)
	return {math.sin(x[1])*math.exp(x[1]),1/math.log(x[1])}
end

local eqcon = mol.nullconfun()
local ineqcon = mol.nullconfun()

local lb = {0,-20}
local ub = {10,20}
local algo = mol.listoptalgo()[1]
local eps = 1e-5
local n = 1000

local p, corr,fval= mol.nlpfit(xdat,ydat2,model,lb,ub,eqcon,ineqcon,algo,eps,n)

local fitmodel = mol.tofit(model,p)
local fitx = mol.matrix.linspace(2,10,50)
local fity = fitx:apply(fitmodel)

print({
	p = p,
	corr = corr,
	fval = fval
})

local img1 = plt.scatter({{xdat:tovector(),ydat1}},{'f(x)'},{{marker='s',color='r'}})
local img2 = plt.scatter({{xdat:tovector(),ydat2}},{'g(x)'},{{marker='o',color='g'}})
local img3 = plt.line({{fitx:tovector(),fity}},{'fitmodel(x)'})
local fw = plt.framework(111,'非线性拟合',{'x','y'})
plt.show({{fw,{img1,img2,img3}}})