ArgumentError: New columns must have the same length as old columns - julia

I have a problem in the simulation loop. The problem is that new matrices don't have the same length as old variables. I'm not sure if the problem comes from the initial values of the variables or from the simulation loop.
I'm using julia v1.0.3
using Distributions
using DataFrames
n=5000
t=15000
gamma = 2;
delta = 0.057;
betta = 0.99;
alfa = 0.47;
miz = 1;
roz = 0.75;
sigmaz = 0.013;
phi = 0.05;
rok = 0.7;
mie = 1;
roe = 0.7;
sigmae1 = 0.05;
sigmae2 = 0.1;
roez = 0.3;
lambda = 0.8;
tau = 0;
ass = 31.7838916986589918973;
kss = lambda*ass;
vtheta1 =0.1;
vtheta2 =0.2;
vtheta3 =0.3;
vtheta4 =0.4;
vtheta5 =0.5;
n_lambda = trunc(Int, lambda * n)
eshocks1= rand(Normal(0.0,sigmae1),n_lambda ,t);
eshocks2= rand(Normal(0.0,sigmae2),n-n_lambda,t);
zshocks1= rand(Normal(0.0, sigmaz),1 , t);
# Variables:
a=ones(t,n);
c=ones(t,n);
y= ones(t,n);
k=ones(t);
w=ones(t);
r=ones(t);
z=ones(t);
l=ones(t);
e=ones(t,n);
Initial values of the variables:
a[1:2,1:n_lambda].=ass;
a[1:t,(n_lambda+1):n].=0;
k[1:2].=lambda*ass;
c[1:n_lambda,1].=(ass^alfa)*(1-tau*alfa)-delta*ass;
Loop of simulation
for i = 2:(t-1)
k[i]=lambda*mean(a[i,1:n_lambda]);
z[i]=(1-roz)+roz*z[i-1]+zshocks1[i];
l[i]=1+(1-lambda)*roez*(z[i]-1)/(1-roe);
w[i]=(1-alfa)*z[i]*((k[i])^(alfa))*l[i]^(-alfa);
r[i]=alfa*z[i]*((k[i])^(alfa-1))*l[i]^(1-alfa);
for j=1:n_lambda
e[i,j]=(1-roe)+roe*e[i-1,j]+eshocks1[j,i];
a[i+1,j]=(vtheta1)+(vtheta2)*a[i,j]+(vtheta3)*e[i,j]+(vtheta4)*z[i]+(vtheta5)*k[i];
y[i,j]=(1-tau)*r[i]*a[i,j]+w[i]*e[i,j];
end
for m=1:(n-n_lambda)
e[i,m+n_lambda]=(1-roe)+roe*e[i-1,m+n_lambda]+roez*(z[i]-1)+eshocks2[m,i];
c[i,m+n_lambda]=w[i]*e[i,m+n_lambda]+tau*r[i]*k[i]/(1-lambda);
y[i,m+n_lambda]=c[i,m+n_lambda];
end
end
Preparing the variables for the calculation of the Gini index
ysort = ones(t,n);
for i = 1:(t-1)
ysort[i,:]=sort(y[i,:]);
end
Calculation of the Gini index of income
giniY=ones(t);
for i=1:(t-1)
sum1=0;
sum2=0;
for j=1:n
sum1=(n+1-j)*ysort[i,j]+sum1;
sum2=ysort[i,j]+sum2;
end
giniY[i]=(n+1-2*(sum1/sum2))/n;
end
tab = DataFrame()
tab[ :periodos] = 15000
tab[ :familias] = 5000
tab[ :giniY]= giniY
return tab
ArgumentError: New columns must have the same length as old columns
Stacktrace:
[1] insert_single_column!(::DataFrame, ::Array{Float64,1}, ::Symbol) at /home/jrun/.julia/packages/DataFrames/IKMvt/src/dataframe/dataframe.jl:366
[2] setindex!(::DataFrame, ::Array{Float64,1}, ::Symbol) at /home/jrun/.julia/packages/DataFrames/IKMvt/src/dataframe/dataframe.jl:420
[3] top-level scope at In[1]:104

This is the way to create tab DataFrame you want (assuming you want periodos and familias columns to contain constant values):
tab = DataFrame(periodos=15000, familias=5000, giniY=giniY)

Related

Error when calculating RHS of ode "no method matching Float64(::Num)"

I have some code that uses a function to calculate some changes in concentration, but I get an error of:
ERROR: LoadError: MethodError: no method matching Float64(::Num)
Closest candidates are:
(::Type{T})(::Real, ::RoundingMode) where T<:AbstractFloat at rounding.jl:200
(::Type{T})(::T) where T<:Number at boot.jl:760
(::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number} at char.jl:50
I have attached a MWE below.
The code initializes some parameters, and uses the initialized parameters to calculate additional parameters (Ke and kb), then inputs these parameters into my function oderhs(c,Ke,kb,aw,aw²,aw³,ρζ,ρζ²,ρζ³,γ,γ²) which should return dc which is my solution vector that I require.
using DifferentialEquations
#parameters t c0[1:4] Ke[1:2] kb[1:2] aw aw² aw³ ρ ζ ρζ ρζ² γ γ² T
# Calculate parameters
ρ = 0.592
ζ = 1.0
ρζ = ρ*ζ
ρζ² = ρζ*ρζ
ρζ³ = ρζ*ρζ²
aw = 0.995
aw² = aw*aw
aw³ = aw*aw²
γ = 1.08
γ² = γ*γ
T = 590.0
# calculate equilibrium constants
Ke[01] = (1.0E-06)*10.0^(-4.098 + (-3245.2/T) + (2.2362E+05/(T^2)) + (-3.9984E+07/(T^3)) + (log10(ρ) * (13.957 + (-1262.3/T) + (8.5641E+05/(T^2)))) )
Ke[02] = 10^(28.6059+0.012078*T+(1573.21/T)-13.2258*log10(T))
# calculate backward rate constants
kb[01] = Ke[01]*ρζ²/γ²
kb[02] = Ke[02]*γ/ρζ
# set initial concentrations
c0 = [0.09897, 0.01186, 2.94e-5, 4.17e-8]
function oderhs(c,Ke,kb,aw,aw²,aw³,ρζ,ρζ²,ρζ³,γ,γ²)
# rename c to their corresponding species
H₃BO₃ = c[1]; H₄BO₄⁻ = c[2]; OH⁻ = c[3]; H⁺ = c[4];
# rename Ke to their corresponding reactions
Ke_iw1 = Ke[1]; Ke_ba1 = Ke[2];
# rename kb to their corresponding reactions
kb_iw1 = kb[1]; kb_ba1 = kb[2];
# determine the rate of reaction for each reaction
r_iw1 = kb_iw1*(H⁺*OH⁻ - Ke_iw1*ρζ²*aw/γ²)
r_ba1 = kb_ba1*(H₄BO₄⁻ - H₃BO₃*OH⁻*Ke_ba1*γ/ρζ)
dc = zeros(eltype(c),4)
# calculate the change in species concentration
dc[1] = r_ba1
dc[2] = r_ba1
dc[3] = r_iw1 + r_ba1
dc[4] = r_iw1
return dc
end
dc = oderhs(c0,Ke,kb,aw,aw²,aw³,ρζ,ρζ²,ρζ³,γ,γ²)
zeros(eltype(c),4) creates an Array of Float64, which isn't what you want because you're trying to create a symbolic version of the ODE equations (right? otherwise this doesn't make sense). Thus you want to this be like zeros(Num,4), so that the return is the symbolic equations, and then you'd generate the actual code for DifferentialEquations.jl from the ModelingToolkit.jl ODESystem.

Unable to understand dimension mismatch error in Julia

I’m a beginner with Julia and ML. I’m attempting to re-use code from the Flux Model Zoo, specifically this, to classify images from this dataset. Below is my version of the code - I modified the data load and the params in the build_model to account for the difference in image size and the number of character types to be classified. The original had 28x28 and 10 digits, the arabic character set had 32x32 images and 28 characters.
function getimages(filename)
filepath = pwd() * "/images/" * filename
mtrx = Matrix(DataFrame(CSV.File(filepath)))
r, _ = size(mtrx)
v = Vector{Matrix{Int64}}()
for i = 1:r
push!(v, reshape(m[i, :], 32, 32))
end
v
end
function getlabels(filename)
filepath = pwd() * "/images/" * filename
vec(Matrix(DataFrame(CSV.File(filepath))))
end
function load_data(args)
train_data_file = "csvTrainImages.csv"
test_data_file = "csvTestImages.csv"
train_label_file = "csvTrainLabel.csv"
test_label_file = "csvTestLabel.csv"
train_data = getimages(train_data_file)
test_data = getimages(test_data_file)
train_labels = getlabels(train_label_file)
test_labels = getlabels(test_label_file)
xtrain = Flux.flatten(train_data)
xtest = Flux.flatten(test_data)
ytrain, ytest = onehotbatch(train_labels, 1:28), onehotbatch(test_labels, 1:28)
train_loader = DataLoader((xtrain, ytrain), batchsize=args.batchsize, shuffle=true)
test_loader = DataLoader((xtest, ytest), batchsize=args.batchsize)
return train_loader, test_loader
end
function build_model(; imgsize=(32,32,1), nclasses=28)
return Chain(
Dense(prod(imgsize), 32, relu),
Dense(32, nclasses))
end
function loss_and_accuracy(data_loader, model, device)
acc = 0
ls = 0.0f0
num = 0
for (x, y) in data_loader
x, y = device(x), device(y)
ŷ = model(x)
ls += logitcrossentropy(model(x), y, agg=sum)
acc += sum(onecold(cpu(model(x))) .== onecold(cpu(y)))
num += size(x, 2)
end
return ls / num, acc / num
end
#kwdef mutable struct Args
η::Float64 = 3e-4 # learning rate
batchsize::Int = 256 # batch size
epochs::Int = 10 # number of epochs
use_cuda::Bool = true # use gpu (if cuda available)
end
function train(; kws...)
args = Args(; kws...) # collect options in a struct for convenience
if CUDA.functional() && args.use_cuda
#info "Training on CUDA GPU"
CUDA.allowscalar(false)
device = gpu
else
#info "Training on CPU"
device = cpu
end
# Create test and train dataloaders
train_loader, test_loader = load_data(args)
# Construct model
model = build_model() |> device
ps = Flux.params(model) # model's trainable parameters
## Optimizer
opt = ADAM(args.η)
## Training
for epoch in 1:args.epochs
for (x, y) in train_loader
x, y = device(x), device(y) # transfer data to device
gs = gradient(() -> logitcrossentropy(model(x), y), ps) # compute gradient
Flux.Optimise.update!(opt, ps, gs) # update parameters
end
# Report on train and test
train_loss, train_acc = loss_and_accuracy(train_loader, model, device)
test_loss, test_acc = loss_and_accuracy(test_loader, model, device)
println("Epoch=$epoch")
println(" train_loss = $train_loss, train_accuracy = $train_acc")
println(" test_loss = $test_loss, test_accuracy = $test_acc")
end
end
I get the following error when I train the model. Specifically, during the gradient computation. Could you help me understand which two matrices the error refers to and point me towards a solution? My guess is that it has to do with the build_model params, but I’m not quite sure what needs to change and how.
DimensionMismatch("matrix A has dimensions (32,1024), matrix B has dimensions (1,256)")
macro expansion#interface2.jl:0[inlined]
_pullback(::Zygote.Context, ::typeof(throw), ::DimensionMismatch)#interface2.jl:9
_pullback#matmul.jl:814[inlined]
_pullback(::Zygote.Context, ::typeof(LinearAlgebra._generic_matmatmul!), ::Matrix{Matrix{Float32}}, ::Char, ::Char, ::Matrix{Float32}, ::Matrix{Matrix{Int64}}, ::LinearAlgebra.MulAddMul{true, true, Bool, Bool})#interface2.jl:0
_pullback#matmul.jl:802[inlined]
_pullback(::Zygote.Context, ::typeof(LinearAlgebra.generic_matmatmul!), ::Matrix{Matrix{Float32}}, ::Char, ::Char, ::Matrix{Float32}, ::Matrix{Matrix{Int64}}, ::LinearAlgebra.MulAddMul{true, true, Bool, Bool})#interface2.jl:0
_pullback#matmul.jl:302[inlined]
_pullback#matmul.jl:275[inlined]
_pullback(::Zygote.Context, ::typeof(LinearAlgebra.mul!), ::Matrix{Matrix{Float32}}, ::Matrix{Float32}, ::Matrix{Matrix{Int64}})#interface2.jl:0
_pullback#matmul.jl:153[inlined]
_pullback(::Zygote.Context, ::typeof(*), ::Matrix{Float32}, ::Matrix{Matrix{Int64}})#interface2.jl:0
_pullback#basic.jl:147[inlined] ....
Solved by fixing the get images method as below.
function getimages(filename)
filepath = pwd() * "/images/" * filename
mtrx = Matrix(DataFrame(CSV.File(filepath)))
return mtrx'
end

ST-HOSVD in Julia

I am trying to implement ST-HOSVD algorithm in Julia because I could not found library which contains ST-HOSVD.
See this paper in Algorithm 1 in page7.
https://people.cs.kuleuven.be/~nick.vannieuwenhoven/papers/01-STHOSVD.pdf
I cannot reproduce input (4,4,4,4) tensor by approximated tensor whose tucker rank is (2,2,2,2).
I think I have some mistake in indexes of matrix or tensor elements, but I could not locate it.
How to fix it?
If you know library of ST-HOSVD, let me know.
ST-HOSVD is really common way to reduce information. I hope the question helps many Julia user.
using TensorToolbox
function STHOSVD(A, reqrank)
N = ndims(A)
S = copy(A)
Sk = undef
Uk = []
for k = 1:N
if k == 1
Sk = tenmat(S, k)
end
Sk_svd = svd(Sk)
U1 = Sk_svd.U[ :, 1:reqrank[k] ]
V1t = Sk_svd.V[1:reqrank[k], : ]
Sigma1 = diagm( Sk_svd.S[1:reqrank[k]] )
Sk = Sigma1 * V1t
push!(Uk, U1)
end
X = ttm(Sk, Uk[1], 1)
for k=2:N
X = ttm(X, Uk[k], k)
end
return X
end
A = rand(4,4,4,4)
X = X_STHOSVD(A, [2,2,2,2])
EDIT
Here, Sk = tenmat(S, k) is mode n matricization of tensor S.
S∈R^{I_1×I_2×…×I_N}, S_k∈R^{I_k×(Π_{m≠k}^{N} I_m)}
The function is contained in TensorToolbox.jl. See "Basis" in Readme.
The definition of mode-k Matricization can be seen the paper in page 460.
It works.
I have seen 26 page in this slide
using TensorToolbox
using LinearAlgebra
using Arpack
function STHOSVD(T, reqrank)
N = ndims(T)
tensor_shape = size(T)
for i = 1 : N
T_i = tenmat(T, i)
if reqrank[i] == tensor_shape[i]
USV = svd(T_i)
else
USV = svds(T_i; nsv=reqrank[i] )[1]
end
T = ttm( T, USV.U * USV.U', i)
end
return T
end

What is a proper way to get a Jacobian matrix in Zygote (Julia)?

I'm trying to get a Jacobian matrix for L, with a vector q and q^dot, but couldn't get a proper matrix. Could anyone help me to get the matrix by using this Zygote package correctly? FYI, I'm totally noob to this differentiable programming world. Any references to study DP or AD from scratch would be also welcomed. Thank you :)
using LinearAlgebra
using Zygote
using DifferentialEquations
## CONSTANTS
g = 9.81;
## PARAMS
m₁ = 1;
m₂ = 1;
l₁ = 1;
l₂ = 1;
## TEST SAMPLE
θ₁=30*pi/180;
θ₂=15*pi/180;
ω₁=2.;
ω₂=1.;
q1 = [θ₁;θ₂]
q̇1 = [ω₁;ω₂]
##
M(q)=[(m₁+m₂)*l₁^2 l₁*l₂*m₂*cos(q[1]-q[2]);
l₁*l₂*m₂*cos(q[1]-q[2]) m₂*l₂^2];
U(q) = g*(m₁*(-l₁*cos(q[1])) +
m₂*(-l₁*cos(q[1])-l₂*cos(q[2])));
T(q,q̇) = ((1/2).*q̇'*M(q)*q̇)[1]
V(q,q̇) = U(q)
L(q,q̇) = T(q,q̇) - V(q,q̇);
## gradient((a, b) -> a*b, 2, 3)
∂L_∂q(f,q,q̇) = gradient(f,q,q̇)[1]; #Partial Diff. w/ q Vector
∂L_∂q̇(f,q,q̇) = gradient(f,q,q̇)[2]; #Partial Diff. w/ q̇ Vector
∂L_∂q(L,q1,q̇1) #OKAY
∂L_∂q̇(L,q1,q̇1) #OKAY
∂∂L_∂q∂q̇(f,q,q̇) = gradient(((q, q̇) -> ∂L_∂q(f,q,q̇)),q,q̇)[2];
∂∂L_∂q∂q̇(L,q1,q̇1) #ERROR
Zygote over Zygote won't currently work, so I would recommend Tracker over Zygote for this:
using LinearAlgebra
using Zygote
using DifferentialEquations
import Tracker
## CONSTANTS
g = 9.81;
## PARAMS
m₁ = 1;
m₂ = 1;
l₁ = 1;
l₂ = 1;
## TEST SAMPLE
θ₁=30*pi/180;
θ₂=15*pi/180;
ω₁=2.;
ω₂=1.;
q1 = [θ₁;θ₂]
q̇1 = [ω₁;ω₂]
##
M(q)=[(m₁+m₂)*l₁^2 l₁*l₂*m₂*cos(q[1]-q[2]);
l₁*l₂*m₂*cos(q[1]-q[2]) m₂*l₂^2];
U(q) = g*(m₁*(-l₁*cos(q[1])) +
m₂*(-l₁*cos(q[1])-l₂*cos(q[2])));
T(q,q̇) = ((1/2).*q̇'*M(q)*q̇)[1]
V(q,q̇) = U(q)
L(q,q̇) = T(q,q̇) - V(q,q̇);
## gradient((a, b) -> a*b, 2, 3)
∂L_∂q(f,q,q̇) = gradient(f,q,q̇)[1]; #Partial Diff. w/ q Vector
∂L_∂q̇(f,q,q̇) = gradient(f,q,q̇)[2]; #Partial Diff. w/ q̇ Vector
∂L_∂q(L,q1,q̇1) #OKAY
∂L_∂q̇(L,q1,q̇1) #OKAY
∂∂L_∂q∂q̇(f,q,q̇) = Tracker.gradient(((q, q̇) -> ∂L_∂q(f,q,q̇)),q,q̇)[2];
∂∂L_∂q∂q̇(L,q1,q̇1)

How can I access the trained parameters of a Neural ODE in Julia?

I'm trying to fit one Neural ODE to a time series usind Julia's DiffEqFlux. Here my code:
u0 = Float32[2.;0]
train_size = 15
tspan_train = (0.0f0,0.75f0)
function trueODEfunc(du,u,p,t)
true_A = [-0.1 2.0; -2.0 -0.1]
du .= ((u.^3)'true_A)'
end
t_train = range(tspan_train[1],tspan_train[2],length = train_size)
prob = ODEProblem(trueODEfunc, u0, tspan_train)
ode_data_train = Array(solve(prob, Tsit5(),saveat=t_train))
dudt = Chain(
Dense(2,50,tanh),
Dense(50,2))
ps = Flux.params(dudt)
n_ode = NeuralODE(dudt, tspan_train, Tsit5(), saveat = t_train, reltol=1e-7, abstol=1e-9)
**n_ode.p**
function predict_n_ode(p)
n_ode(u0,p)
end
function loss_n_ode(p)
pred = predict_n_ode(p)
loss = sum(abs2, ode_data_train .- pred)
loss,pred
end
final_p = []
losses = []
cb = function(p,l,pred)
display(l)
display(p)
push!(final_p, p)
push!(losses,l)
pl = scatter(t_train, ode_data_train[1,:],label="data")
scatter!(pl,t_train,pred[1,:],label="prediction")
display(plot(pl))
end
DiffEqFlux.sciml_train!(loss_n_ode, n_ode.p, ADAM(0.05), cb = cb, maxiters = 100)
**n_ode.p**
The problem is that calling n_ode.p (or Flux.params(dudt)) before and after the train function gives me back the save values. I would have expected to receive the latest updated values from the training. That's why I've created an array to gather all parameter values during the training and then access it to get the updated parameters.
Am I doing something wrong in the code? Does the train function automatically update the parameters? If not how to enforce it?
Thanks in advance!
The result is an object that holds the best parameters. Here's a complete example:
using DiffEqFlux, OrdinaryDiffEq, Flux, Optim, Plots
u0 = Float32[2.; 0.]
datasize = 30
tspan = (0.0f0,1.5f0)
function trueODEfunc(du,u,p,t)
true_A = [-0.1 2.0; -2.0 -0.1]
du .= ((u.^3)'true_A)'
end
t = range(tspan[1],tspan[2],length=datasize)
prob = ODEProblem(trueODEfunc,u0,tspan)
ode_data = Array(solve(prob,Tsit5(),saveat=t))
dudt2 = FastChain((x,p) -> x.^3,
FastDense(2,50,tanh),
FastDense(50,2))
n_ode = NeuralODE(dudt2,tspan,Tsit5(),saveat=t)
function predict_n_ode(p)
n_ode(u0,p)
end
function loss_n_ode(p)
pred = predict_n_ode(p)
loss = sum(abs2,ode_data .- pred)
loss,pred
end
loss_n_ode(n_ode.p) # n_ode.p stores the initial parameters of the neural ODE
cb = function (p,l,pred;doplot=false) #callback function to observe training
display(l)
# plot current prediction against data
if doplot
pl = scatter(t,ode_data[1,:],label="data")
scatter!(pl,t,pred[1,:],label="prediction")
display(plot(pl))
end
return false
end
# Display the ODE with the initial parameter values.
cb(n_ode.p,loss_n_ode(n_ode.p)...)
res1 = DiffEqFlux.sciml_train(loss_n_ode, n_ode.p, ADAM(0.05), cb = cb, maxiters = 300)
cb(res1.minimizer,loss_n_ode(res1.minimizer)...;doplot=true)
res2 = DiffEqFlux.sciml_train(loss_n_ode, res1.minimizer, LBFGS(), cb = cb)
cb(res2.minimizer,loss_n_ode(res2.minimizer)...;doplot=true)
# result is res2 as an Optim.jl object
# res2.minimizer are the best parameters
# res2.minimum is the best loss
At the end, the sciml_train function returns a result object that holds information about the optimization, including the final parameters as .minimizer.

Resources