I’m diving into Flux.jl
for my research. My objective is to define a loss function that would measure, so to speak, the convergence of the model towards a uniform data distribution.
I generate K
random fictitious observations and compare how many of them are smaller than the true data in the training set. In other words, the model generates K
simulations, and we determine the number of simulations where the generated data is smaller than the actual data. If the model is well trained, this distribution should converge to a uniform distribution.
However, since the resulting histogram is not differentiable, I needed to approximate this idea using compositions of continuous differentiable functions.
η = 0.1; num_epochs = 100; n_samples = 1000
optim = Flux.setup(Flux.Adam(η), model)
losses = []
l = CustomLoss(2)
for epoch in 1:num_epochs
loss, grads = Flux.withgradient(model) do m
aₖ = zeros(l.K+1)
for _ in 1:n_samples
x = rand(Normal(μ, stddev), l.K)
yₖ = m(x')
y = target(rand(Normal(μ, stddev)))
aₖ += generate_aₖ(l, yₖ, y)
end
scalar_diff(l, aₖ ./ sum(aₖ))
end
Flux.update!(optim, model, grads[1])
push!(losses, loss)
end
So, generate_aₖ(l, yₖ, y)
would return a vector of size K+1
, where the element at index k
is close to 1
if y
is greater than k
elements of the vector yₖ
.
Finally, scalar_diff
calculates the squared difference between the calculated aₖ
and the uniform distribution.
However, this code is not functioning correctly, and I am encountering the following issue due to the line aₖ += generate_aₖ(l, yₖ, y)
,
Mutating arrays is not supported -- called copyto!(Vector{Float64}, ...)
This error occurs when you ask Zygote to differentiate operations that change
the elements of arrays in place (e.g. setting values with x .= ...)
I’m not sure how to solve this problem. Does anyone have any ideas for a workaround? I need to differentiate it against aₖ
.