朱莉娅:使用CurveFit包非线性

时间:2016-01-17 16:51:15

标签: julia curve-fitting non-linear-regression

为什么下面的代码不起作用?

xa = [0  0.200000000000000 0.400000000000000  1.00000000000000  1.60000000000000  1.80000000000000  2.00000000000000  2.60000000000000  2.80000000000000  3.00000000000000  3.80000000000000  4.80000000000000  5.00000000000000  5.20000000000000  6.00000000000000  6.20000000000000  7.40000000000000  7.60000000000000  7.80000000000000  8.60000000000000  8.80000000000000  9.00000000000000  9.20000000000000  9.40000000000000  10.0000000000000  10.6000000000000  10.8000000000000  11.2000000000000  11.6000000000000  11.8000000000000  12.2000000000000  12.4000000000000];

ya = [-0.183440428023042  -0.131101157495126  0.0268875670852843 0.300000000120000  0.579048247883555  0.852605831272159  0.935180993484717  1.13328608090532  1.26893326843583  1.10202945535186  1.09201137189664  1.14279083803453  0.811302535321072  0.909735376251797  0.417067545528244  0.460107770989798  -0.516307074859654  -0.333994077331822  -0.504124744955962  -0.945794320817293  -0.915934553082780  -0.975458595671737  -1.09943707404275  -1.11254211607374  -1.29739980589100  -1.23440439602665  -0.953807504156356  -1.12240274852172  -0.609284630192522  -0.592560286759450  -0.402521296049042  -0.510090363150962];

x0 = vec(xa) 
y0 = vec(ya)
fun(x,a) = a[1].*sin(a[2].*x - a[3])
a0 = [1,2,3] 
eps = 0.000001 
maxiter=200 
coefs, converged, iter = CurveFit.nonlinear_fit(x0 , fun , a0 , eps, maxiter ) 
y0b = fit(x0) 
Winston.plot(x0, y0, "ob", x0, y0b, "r-", linewidth=3)
  

错误:LoadError:MethodError:convert没有方法匹配convert(:: Type {Float64},:: Array {Float64,1})这可能是由于   调用构造函数Float64(...),因为类型构造函数会下降   回转换方法。最接近的候选人是:致电{T}(:: Type {T},   :: Any)convert(:: Type {Float64} ,! Matched :: Int8)   convert(:: Type {Float64} ,! Matched :: Int16)

     

加载时[269],表达式从第8行开始        在Nonlinearhfit /home/jmarcellopereira/.julia/v0.4/CurveFit/src/nonlinfit.jl:75

3 个答案:

答案 0 :(得分:2)

来自Doc:

  

我们正在尝试适应关系fun(x, a) = 0

因此,如果您希望以下列方式查找a的元素:xi,yi =>中的每个[x0 y0] a[1].*sin(a[2].*xi - a[3])==yi,然后正确的方法是:

fun(xy,a) = a[1].*sin(a[2].*xy[1] - a[3])-xy[2];
xy=hcat(x0,y0);
coefs,converged,iter = CurveFit.nonlinear_fit(xy,fun,a0,eps,maxiter);

答案 1 :(得分:2)

fun函数必须返回类型r的残差值Float64,在每次迭代数据时计算,如下所示:

r = y - fun(x, coefs)

因此您的函数y=a1*sin(x*a2-a3)将被定义为:

fun(x,a) = x[2]-a[1]*sin(a[2]*x[1] - a[3])

其中:

  x[2] is a value of 'y' vector  
  x[1] is a value of 'x' vector  
  a[...] is the set of parameters

fun函数必须返回单个Float64,因此运算符不能是点版本' (.*)。

通过调用 nonlinear_fit 函数,第一个参数必须是数组Nx2,第一列包含N个值x,第二个列包含N个值{{1}所以你必须在两列数组中连接两个向量yx

y

最后,调用函数:

xy = [x y]

回答有关返回系数的评论不正确:

coefs, converged, iter = CurveFit.nonlinear_fit(xy , fun , a0 , eps, maxiter ) 谐波函数,因此从函数调用返回的系数依赖严重参数y = 1 * sin (x * a2-a3)"每个拟合参数" 的初始猜测,您将作为第三个参数发送(a0):

maxiter=200_000

我认为您获得的结果是谐波,如图:

Plot result of harmonics

其中:

a0=[1.5, 1.5, 1.0]  
coefficients: [0.2616335317043578, 1.1471991302529982,0.7048665905560775]

a0=[100.,100.,100.]  
coefficients: [-0.4077952060368059, 90.52328921205392, 96.75331155303707]

a0=[1.2, 0.5, 0.5]  
coefficients: [1.192007321713507, 0.49426296880933257, 0.19863645732313934]

图表是使用Gadfly

生成的
blue line:  
f1(xx)=0.2616335317043578*sin(xx*1.1471991302529982-0.7048665905560775)

yellow line:
f2(xx)=1.192007321713507*sin(xx*0.49426296880933257-0.19863645732313934)

pink line:
f3(xx)=-0.4077952060368059*sin(xx*90.52328921205392-96.75331155303707)

blue dots are your initial data.

使用Julia Version 0.4.3进行测试

答案 2 :(得分:1)

我发现LsqFit package使用起来更简单,只需首先定义模型,然后“适应它”#34;与您的数据:

using DataFrames, Plots, LsqFit

xa         = [0  0.200000000000000 0.400000000000000  1.00000000000000  1.60000000000000  1.80000000000000  2.00000000000000  2.60000000000000  2.80000000000000  3.00000000000000  3.80000000000000  4.80000000000000  5.00000000000000  5.20000000000000  6.00000000000000  6.20000000000000  7.40000000000000  7.60000000000000  7.80000000000000  8.60000000000000  8.80000000000000  9.00000000000000  9.20000000000000  9.40000000000000  10.0000000000000  10.6000000000000  10.8000000000000  11.2000000000000  11.6000000000000  11.8000000000000  12.2000000000000  12.4000000000000];
ya         = [-0.183440428023042  -0.131101157495126  0.0268875670852843 0.300000000120000  0.579048247883555  0.852605831272159  0.935180993484717  1.13328608090532  1.26893326843583  1.10202945535186  1.09201137189664  1.14279083803453  0.811302535321072  0.909735376251797  0.417067545528244  0.460107770989798  -0.516307074859654  -0.333994077331822  -0.504124744955962  -0.945794320817293  -0.915934553082780  -0.975458595671737  -1.09943707404275  -1.11254211607374  -1.29739980589100  -1.23440439602665  -0.953807504156356  -1.12240274852172  -0.609284630192522  -0.592560286759450  -0.402521296049042  -0.510090363150962];
x0         = vec(xa)
y0         = vec(ya)
xbase      = collect(linspace(minimum(x0),maximum(x0),100))
p0         = [1.2, 0.5, 0.5]                                                      # initial value of parameters
fun(x0, p) = p[1] .* sin.(p[2] .* x0 .- p[3])                                     # definition of the model
fit        = curve_fit(fun,x0,y0,p0)                                              # actual fitting job
yFit       = [fit.param[1] * sin(fit.param[2] * x - fit.param[3]) for x in xbase] # building the fitted values
# Plotting..
scatter(x0, y0, label="obs")
plot!(xbase, yFit, label="fitted")

plotted data

请注意,使用LsqFit无法解决Gomiero突出显示的初始条件的依赖问题。