I am taking the next step with Julia, and trying to learn more. Up to now, I have used it mostly just as a calculator, but I recently started to make my own modules and so on.
One thing I am having trouble understanding is how mutating functions work.
In the code below, I send in a mutable struct, GLMFit, and want to set some of its fields/attributes with this function (full code at the end).
If I do not include this part after the loop is finished, the \beta-, \mu-, and \eta-vectors have the same value as before the loop.
M.Fit.β = β
M.Fit.μ = μ
M.Fit.η = η
But the \beta is still changed inside the function, before the loop, since I set the first element equal to the mean of y, with this code:
if sum(β) == 0
β[1] = sum(y)/length(y)
end
It is just the changes to \beta that happen inside the loop which are not captured, unless I specifically include the M.Fit.β = β
after the loop.
Am I doing something wrong, or is the M.Fit.β = β
and same for the other vectors strictly necessary in these cases?
The full code for the function:
function FisherScoring!(M::GLMFit, maxiter=25, tol=1e-10)
dist, lp, link = M.Model.d, M.Model.lp, M.Model.g
X = lp.X
β = M.Fit.β
μ = M.Fit.μ
y = M.Fit.y
η = M.Fit.η
p = length(β)
local J, Jinv, w
if sum(β) == 0
β[1] = sum(y)/length(y)
end
for i in 1:maxiter
η = X * β
μ = InverseLinkFunction(link, η)
w = Var(dist, μ)
U = Score(X, y, μ, dist, link)
J = FisherInformation(X, w, dist, link)
Jinv = inv(J)
βtemp = β
β = β + Jinv * U
δ = β - βtemp
if sqrt(δ' * δ) < tol
println(@sprintf "Stopping after %d iterations" i)
M.Fit.SE = sqrt.(diag(Jinv))
break
else
L = Likelihood(dist, μ, y)
println(@sprintf "Fisher Iteration %d 𝐿(β) = %.12f" i L)
M.Fit.SE = sqrt.(diag(Jinv))
end
end
M.Fit.β = β
M.Fit.μ = μ
M.Fit.η = η
M.Fit.𝐃 = Deviance(dist, μ, y)
M.Fit.DoF = length(y) - length(β)
L = Likelihood(dist, μ, y)
M.Fit.AIC = AIC(length(β), L)
M.IsFitted = true
end