Parameter identification with Optim.jl to optimize a first order output error-model

Hello,

I would like to start with Optim.jl to optimize some dynamical systems. The following code should optmize the parameters of a linear output error model which approximates a nonlinear system.

using Optim

function system(u_k_1::Array{Float64})
    y_k_1 = zeros(size(u_k_1))
    for i in 2:length(u_k_1)
        y_k_1[i] = 0.2 * ((atan(8.0 * u_k_1[i-1] - 4.0) + atan(4.0)) / (2.0 * atan(4.0))) + 0.8 * y_k_1[i-1]
    end
    return y_k_1
end

u = [1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 1.0; 0.25; 0.25; 0.25; 0.25; 0.25; 0.25; 0.25; 0.75; 0.75; 0.75; 0.75; 0.75; 0.75; 0.75; 0.5; 0.5; 0.5; 0.5; 0.5; 0.5; 0.5; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0]
y  = vec(system(u))

order_x=1
order_y=1
x0 = rand(order_x+order_y)

N=length(u)

e = zeros(N)
y_hat = zeros(N)
function f(x)
    for i in 2:N
        y_hat[i] = x[1]*u[i-1] - x[2] * y_hat[i-1]
        e[i] = abs2(y[i]-y_hat[i])
    end
    return sum(e)
end

optimize(f, x0, LBFGS(); autodiff = :forward)

I get the following error message:
ERROR: MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(f), Float64}, Float64, 2})

This is my first attempt to use Optim.jl, so I’m quite unfamiliar with API. Can somebody tell me what I’ve to do to solve my problem?

Best regards

Autodiff works by computing your function with a dual number (in this case a ForwardDiff.Dual) so you need to ensure your function is typed loosely enough to work with duals.

One way of writing your objective to achieve this is:

function f(x)
    ŷ = zeros(eltype(x), N)
    for i in 2:N
        ŷ[i] = x[1] * u[i-1] - x[2] * ŷ[i-1]
    end
    return sum(abs2.(y .- ŷ))
end

Note that here I’ve pulled the creation of into the function and am instantiating it with eltype(x) to ensure that it is an array which can hold dual numbers if f is called with a dual number.

1 Like

Thank you very much