Commit 32b22926 authored by Fredrik Bagge Carlson's avatar Fredrik Bagge Carlson
Browse files

Solved the issue of negative precision

parent 59d2e3ac
......@@ -15,7 +15,8 @@ Based on implementation by
}
http://www.mathworks.com/matlabcentral/fileexchange/29809-cuckoo-search--cs--algorithm
"""
function cuckoo_search(f,X0;Lb=-convert(Float64,Inf),Ub=convert(Float64,Inf),n=25,pa=0.25, Tol=1.0e-5, max_iter = 1e5, timeout = Inf)
function cuckoo_search(f,X0, Lb,Ub;n=25,pa=0.25, Tol=1.0e-5, max_iter = 1e5, timeout = Inf)
X00 = deepcopy(X0)
nd=size(X0,1);
X0t = X0'
Lb = Lb'
......@@ -29,13 +30,18 @@ function cuckoo_search(f,X0;Lb=-convert(Float64,Inf),Ub=convert(Float64,Inf),n=2
# Random initial solutions
nest = zeros(n,nd)
nest[1,:] = X0
nest[1,:] = X0t
for i=2:n
nest[i,:]=Lb+(Ub-Lb).*rand(size(Lb));
DEBUG && @assert !any(nest[i,:] .> Ub)
DEBUG && @assert !any(nest[i,:] .< Lb)
end
# Get the current best
fitness=10^20*ones(n,1);
fmin,bestnest,nest,fitness=get_best_nest(f,nest,nest,fitness);
DEBUG && println("f(X0) = $(f(X00)), f(bestnest) = $(fmin)")
DEBUG && @assert X00 == X0
N_iter=0;
t0 = time()
## Starting iterations
......@@ -72,6 +78,7 @@ function cuckoo_search(f,X0;Lb=-convert(Float64,Inf),Ub=convert(Float64,Inf),n=2
## Post-optimization processing
## Display all the nests
println("Total number of iterations=",N_iter);
println("f(bestnest) = $(fmin)")
squeeze(bestnest',2),fmin
end
......@@ -106,8 +113,10 @@ function get_cuckoos(nest,best,Lb,Ub)
s=s+stepsize.*randn(size(s));
# Apply simple bounds/limits
nest[j,:]=simplebounds(s,Lb,Ub);
DEBUG && @assert !any(nest[j,:] .> Ub)
DEBUG && @assert !any(nest[j,:] .< Lb)
end
nest
return nest
end
## Find the current best nest
function get_best_nest(f,nest,newnest,fitness)
......@@ -123,7 +132,7 @@ function get_best_nest(f,nest,newnest,fitness)
# Find the current best
(fmin,K) = findmin(fitness) ;
best=nest[K,:];
fmin,best,nest,fitness
return fmin,best,nest,fitness
end
......@@ -140,19 +149,21 @@ function empty_nests(nest,Lb,Ub,pa)
## New solution by biased/selective random walks
stepsize=rand()*(nest[randperm(n),:]-nest[randperm(n),:]);
new_nest=nest+stepsize.*K;
for j = 1:size(nest,1)
new_nest[j,:]=simplebounds(new_nest[j,:],Lb,Ub);
end
return new_nest
end
# Application of simple constraints
function simplebounds(s,Lb,Ub)
# Apply the lower bound
ns_tmp=s;
I=ns_tmp.<Lb;
ns_tmp[I]=Lb[I];
I = s.<Lb;
s[I] = Lb[I];
# Apply the upper bounds
J=ns_tmp.>Ub;
ns_tmp[J]=Ub[J];
# Update this new move
s=ns_tmp;
J = s.>Ub;
s[J] = Ub[J];
return s
end
# # ## You can replace the following by your own functions
......
using Devectorize
using Clustering
using Debug
# using Debug
include("levenberg_marquardt.jl")
include("../cuckooSearch.jl")
type RbfNonlinearParameters
x::Vector{Float64}
......@@ -9,14 +10,6 @@ type RbfNonlinearParameters
n_centers::Integer
end
type RbfLinearParameters
x::Vector{Float64}
end
type RbfParameters
n::RbfNonlinearParameters
l::RbfLinearParameters
end
......@@ -51,6 +44,7 @@ function trainRBF_ARX(y, A, state, nc; liniters=3,nonliniters=50, normalized=fal
params[si:si+n_state-1,iter] = clusterresult.centers[:,i]
C = cov(state[clusterresult.assignments .== i,:])
params[si+n_state:si+2n_state-1,iter] = diag(inv(C))
@assert !any(diag(inv(C)) .< 0)
end
errorvec[iter] = rms(predictionerror(params[:,iter]))
end
......@@ -76,57 +70,12 @@ function trainRBF_ARX(y, A, state, nc; liniters=3,nonliniters=50, normalized=fal
newplot(X[:,1],X[:,2],"o"); title("Centers")
end
function getΨ(Znl)
RBF(x, Znl::VecOrMat,n_state::Integer) = exp(-(((x-Znl[1:n_state]).^2.*Znl[n_state+1:end])[1]))
if normalized
rowsum = ones(n_points)
for (j,Zi) in enumerate(Znl)
for i = n_state+1:2n_state
Zi[i] = Zi[i] <= 0 ? 1.0 : Zi[i] # Reset to 1 if precision became negative
end
for i = 1:n_points
statei = squeeze(state[i,:]',2)
a = RBF(statei, Zi, n_state)
Ψ[i,j] = a
rowsum[i] += a
end
end
for i = 1:n_points
if rowsum[i] <= 1e-10
continue
end
@devec Ψ[i,:] ./= rowsum[i]
end
else # Not normalized
for (j,Zi) in enumerate(Znl)
for i = n_state+1:2n_state
Zi[i] = Zi[i] <= 0 ? 1.0 : Zi[i] # Reset to 1 if precision became negative
end
for i = 1:n_points
statei = squeeze(state[i,:]',2)
# statei = slice(state,i,:)
Ψ[i,j] = RBF(statei, Zi, n_state)
if DEBUG && !isfinite(Ψ[i,j])
@show i,j,statei, Zi, n_state, Ψ[i,j]
@show (statei-Zi[1:n_state]).^2
@show Zi[n_state+1:end]
# @show exp(-(((statei-Zi[1:n_state]).^2.*Zi[n_state+1:end])[1]))
error("Stopping")
end
end
end
end
if DEBUG && sum(!isfinite(Ψ)) > 0
@show sum(!isfinite(Ψ))
end
return Ψ
end
function fitlinear(V)
try
assert(isa(V,Matrix))
assert(isa(y,Vector))
DEBUG && assert(isa(V,Matrix))
DEBUG && assert(isa(y,Vector))
DEBUG && assert(!any(!isfinite(V)))
DEBUG && assert(!any(!isfinite(y)))
return V\y
......@@ -170,42 +119,14 @@ function trainRBF_ARX(y, A, state, nc; liniters=3,nonliniters=50, normalized=fal
return J
end
function getLinearRegressor(Ψ)
if outputnet
ii = 1
for i = 1:na
for k = 1:n_centers+1
for j = 1:n_state
for l = 1:n_points
V[l,ii] = Ψ[l,k]*A[l,i]*state[l,j]
end
ii = ii+1
end
end
end
else
ii = 1
for i = 1:na
for k = 1:n_centers+1
for l = 1:n_points
V[l,ii] = Ψ[l,k]*A[l,i]
end
ii = ii+1
end
end
end
if DEBUG && sum(!isfinite(V)) > 0
@show sum(!isfinite(V))
end
return V
end
function predictionerror(z)
znl = RbfNonlinearParameters(z,n_state,n_centers)
getΨ(znl);
getLinearRegressor(Ψ);
zl = fitlinear(V);
prediction = V*zl
psi = getΨ(deepcopy(Ψ), znl, state, n_points, n_state, normalized)
v = getLinearRegressor(deepcopy(V),psi,A,state,outputnet,na,n_state,n_centers,n_points)
zl = fitlinear(v);
prediction = v*zl
error = prediction-y
return error
end
......@@ -243,9 +164,9 @@ function trainRBF_ARX(y, A, state, nc; liniters=3,nonliniters=50, normalized=fal
Znl = getcentersKmeans(state,nc); debug("gotcentersKmeans")
end
@ddshow Znl
getΨ(Znl); debug("Got Ψ")
getΨ(Ψ, Znl, state, n_points, n_state, normalized); debug("Got Ψ")
@ddshow sum(!isfinite(Ψ))
getLinearRegressor(Ψ); debug("Got linear regressor V")
getLinearRegressor(V,Ψ,A,state,outputnet,na,n_state,n_centers,n_points); debug("Got linear regressor V")
@ddshow size(V)
@ddshow sum(!isfinite(V))
Zl = fitlinear(V); debug("fitlinear")
......@@ -254,55 +175,80 @@ function trainRBF_ARX(y, A, state, nc; liniters=3,nonliniters=50, normalized=fal
error = y - prediction
errors = zeros(liniters+1)
Lb = zeros(Znl.x)
Ub = zeros(Znl.x)
mas = maximum(state,1)'
mis = minimum(state,1)'
for i = 1:2n_state:n_centers*2n_state
Lb[i:i+n_state-1] = mis
Ub[i:i+n_state-1] = mas
Lb[i+n_state:i+2n_state-1] = 0.000001
Ub[i+n_state:i+2n_state-1] = 10*Znl.x[n_state+1:2n_state]
end
@show Lb
@show Ub
# ============= Main loop ================================================
debug("Calculating initial error")
errors[1] = sse(predictionerror(Znl.x))
errors[1] = rms(predictionerror(Znl.x))
println("Training RBF_ARX Centers: $(Znl.n_centers), Nonlinear parameters: $(length(Znl.x)), Linear parameters: $(length(Zl))")
function g(z)
znl = RbfNonlinearParameters(z,n_state,n_centers)
w = fitlinear(V)
jacobian(znl,Ψ, w)
end
f(z) = predictionerror(z)
X0 = deepcopy(Znl.x)
for i = 1:liniters
function g(z)
znl = RbfNonlinearParameters(z,n_state,n_centers)
w = fitlinear(V)
jacobian(znl,Ψ, w)
end
f(z) = predictionerror(z)
X0 = Znl.x
if i%2 == 1 || !cuckoosearch
@time res = levenberg_marquardt(f, g, X0,
maxIter = nonliniters,
tolG = 1e-7,
tolX = 1e-10,
show_trace=true,
timeout = 60)
Znl = RbfNonlinearParameters(saturatePrecision(res.minimum,n_state),n_state,n_centers)
timeout = 60,
n_state = n_state)
X0 = deepcopy(res.minimum)
assert(X0 == res.minimum)
@show rms(f(X0))
if DEBUG
_V = deepcopy(V)
= deepcopy(Ψ)
end
@show rms(f(res.minimum))
if DEBUG
@show res.minimum == X0
@show _V == V
@show == Ψ
end
assert(X0 == res.minimum)
# Znl = RbfNonlinearParameters(saturatePrecision(copy(res.minimum),n_state),n_state,n_centers)
Znl = RbfNonlinearParameters(deepcopy(res.minimum),n_state,n_centers)
errors[i+1] = res.f_minimum
# show(res.trace)
else
display("Using cuckoo search to escape local minimum")
@time (bestnest,fmin) = cuckoo_search(x -> sum(f(x).^2),X0;
n=30,
@time (bestnest,fmin) = cuckoo_search(x -> rms(f(x)),X0, Lb, Ub;
n=50,
pa=0.25,
Tol=1.0e-5,
max_iter = i < liniters-1 ? 80 : 200,
timeout = 120)
debug("cuckoo_search done")
Znl = RbfNonlinearParameters(bestnest,n_state,n_centers)
X0 = deepcopy(bestnest)
@ddshow rms(f(X0))
Znl = RbfNonlinearParameters(deepcopy(bestnest),n_state,n_centers)
errors[i+1] = fmin
end
if abs(errors[i+1]-errors[i]) < 1e-10
display("No significant change in function value")
break
end
getΨ(Znl)
getLinearRegressor(Ψ)
fitlinear(V)
# Znl.x = res.minimum
end
# Test ===============================================
getΨ(Znl)
getLinearRegressor(Ψ)
getΨ(Ψ, Znl, state, n_points, n_state, normalized)
getLinearRegressor(V,Ψ,A,state,outputnet,na,n_state,n_centers,n_points)
Zl = fitlinear(V); debug("fitlinear")
prediction = V*Zl
error = y - prediction
......@@ -361,4 +307,85 @@ end
function getΨ(Ψ, Znl, state, n_points, n_state, normalized::Bool)
Ψ = normalized ? getΨnormalized(Ψ, Znl, state, n_points, n_state) : getΨnonnormalized(Ψ, Znl, state, n_points, n_state)
if DEBUG && sum(!isfinite(Ψ)) > 0
@show sum(!isfinite(Ψ))
end
return Ψ
end
function getΨnormalized(Ψ, Znl, state, n_points, n_state)
RBF(x, Znl::VecOrMat,n_state::Integer) = exp(-(((x-Znl[1:n_state]).^2.*Znl[n_state+1:end])[1]))
rowsum = ones(n_points)
for (j,Zin) in enumerate(Znl)
Zi = deepcopy(Zin)
# for i = n_state+1:2n_state
# Zi[i] = Zi[i] <= 0 ? 0.01 : Zi[i] # Reset to 1 if precision became negative
# end
for i = 1:n_points
statei = squeeze(state[i,:]',2)
a = RBF(statei, Zi, n_state)
Ψ[i,j] = a
rowsum[i] += a
end
end
for i = 1:n_points
if rowsum[i] <= 1e-10
continue
end
@devec Ψ[i,:] ./= rowsum[i]
end
return Ψ
end
function getΨnonnormalized(Ψ, Znl, state, n_points, n_state)
RBF(x, Znl::VecOrMat,n_state::Integer) = exp(-(((x-Znl[1:n_state]).^2.*Znl[n_state+1:end])[1]))
for (j,Zin) in enumerate(Znl)
Zi = deepcopy(Zin)
for i = 1:n_points
statei = squeeze(state[i,:]',2)
# statei = slice(state,i,:)
Ψ[i,j] = RBF(statei, Zi, n_state)
if DEBUG && !isfinite(Ψ[i,j])
@show i,j,statei, Zi, n_state, Ψ[i,j]
@show (statei-Zi[1:n_state]).^2
@show Zi[n_state+1:end]
# @show exp(-(((statei-Zi[1:n_state]).^2.*Zi[n_state+1:end])[1]))
error("Stopping")
end
end
end
return Ψ
end
function getLinearRegressor(V,Ψ,A,state,outputnet,na,n_state,n_centers,n_points)
if outputnet
ii = 1
for i = 1:na
for k = 1:n_centers+1
for j = 1:n_state
for l = 1:n_points
V[l,ii] = Ψ[l,k]*A[l,i]*state[l,j]
end
ii = ii+1
end
end
end
else
ii = 1
for i = 1:na
for k = 1:n_centers+1
for l = 1:n_points
V[l,ii] = Ψ[l,k]*A[l,i]
end
ii = ii+1
end
end
end
if DEBUG && sum(!isfinite(V)) > 0
@show sum(!isfinite(V))
end
return V
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment