I’m a Julia newbie trying to switch over from Python! I’m trying to implement a bayes neural net. for some practice.
When trying to track gradients in my model I’m getting the following error: “Mutating arrays is not supported”. I think there’s something I’ve misunderstood with Zygote… Where in my model am I mutating arrays?
struct VariationalAffine{F<:Function,S<:AbstractArray,T<:AbstractArray,
U<:Array, V<:Array,I<:Integer}
W::S
logσW::S
b::T
logσb::T
Wsample::U
bsample::V
σ::F
η::I
end
function VariationalAffine(in::Integer, out::Integer, η::Integer,σ=identity)
W = glorot_uniform(out,in) .+ 0.0
logσW = -6.0 .+ glorot_uniform(out,in)#randn(out,in)
b = zeros(out)
logσb = -6.0 .+ glorot_uniform(out)
return VariationalAffine(W, logσW, b, logσb, reparamSample(W,logσW,η),
reparamSample(b,logσb,η), σ, η)
end
function (m::VariationalAffine)(x::Array)::Array
m.Wsample .= reparamSample(m.W, m.logσW, m.η)
m.bsample .= reparamSample(m.b, m.logσb, m.η)
linear = m.Wsample .* x
return σArray(((li, bi)-> li.+bi).(linear,m.bsample),m.σ)
end
"""
Draw a sample from weights using reparameterization trick
"""
function reparamSample(A::Array{<:Number}, logσA::Array{<:Number}, η::Integer)
return [A .+ randn(size(A)...) .* exp.(logσA) for i in 1:η]
end
"""
Apply activation function to array of arrays
"""
function σArray(A::Array, σ)::Array
return (Ai->σ.(Ai)).(A)
end
struct BayesNN{I<:Integer,L<:Array,P<:Flux.Zygote.Params}
in::I
out::I
layers::L
θ::P
end
function BayesNN(in::Integer, out::Integer, num_layers::Integer,
num_hidden::Integer, η::Integer, σ=relu)
# putting layers into array
layers = [VariationalAffine(in, num_hidden, η, σ),]
hidden_layers = [VariationalAffine(num_hidden, num_hidden, η, σ)
for i in 1:(num_layers-1)]
append!(layers, hidden_layers)
append!(layers, [VariationalAffine(num_hidden, out, η, σ),])
# collecting into parameter array
P=[layers[1].W, layers[1].b]
(L -> append!(P, [L.W, L.b])).(layers[2:end])
return BayesNN(in, out, layers, Flux.params(P))
end
(bm::BayesNN)(x) = foldl((x,bm)->bm(x), bm.layers, init=x)
"""
Mean squared loss for BayesNN
"""
function bnnLoss(y,ŷ)
sqrdiff = (d -> (d).^2).(ŷ .- [y])
return mean(mean.(sqrdiff))
end
bnn=BayesNN(in, out, 10, 50, η);
loss(x,y) = bnnLoss(y, bnn([x’])')
gradient(()->loss(x,y), bnn.θ)