Skip to content

Commit c1bd575

Browse files
committed
another potential solution for non-id gauss
1 parent 035b4a1 commit c1bd575

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

src/generalizedlinearmixedmodel.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,11 @@ is the squared length of the conditional modes, `u`, plus the determinant
8383
of `Λ'Z'WZΛ + I`, plus the sum of the squared deviance residuals.
8484
"""
8585
function StatsBase.deviance(m::GeneralizedLinearMixedModel{T}, nAGQ = 1) where {T}
86-
m.resp.d isa Normal && return -2 * loglikelihood(m)
87-
nAGQ == 1 && return T(sum(x -> x^2, m.resp.devresid) + logdet(m) + sum(u -> sum(abs2, u), m.u))
86+
dispersion_parameter(m) && nAGQ == 1 &&
87+
return T(2 * (-loglikelihood(m) + dof(m) - 1) + logdet(m) + sum(u -> sum(abs2, u), m.u))
88+
89+
nAGQ == 1 && return T(sum(m.resp.devresid) + logdet(m) + sum(u -> sum(abs2, u), m.u))
90+
8891
u = vec(first(m.u))
8992
u₀ = vec(first(m.u₀))
9093
copyto!(u₀, u)
@@ -529,7 +532,7 @@ function pirls!(
529532
end
530533
varyβ && map!(average, β, β, β₀)
531534
obj = deviance!(m)
532-
verbose && println(lpad(nhalf, 8), ", ", obj)
535+
verbose && println(lpad(nhalf, 8), ", ", obj, " ", β)
533536
end
534537
if isapprox(obj, obj₀; atol = 0.00001)
535538
break

test/pirls.jl

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using DataFrames
22
using Distributions
33
using MixedModels
4+
using PooledArrays
5+
using StableRNGs
46
using Tables
57
using Test
68

79
using MixedModels: dataset
10+
using GLM: linkinv
811

912
const gfms = Dict(
1013
:cbpp => [@formula((incid/hsz) ~ 1 + period + (1|herd))],
@@ -138,17 +141,28 @@ end
138141
@test only(m11.θ) 1.838245201739852 atol=1.e-5
139142
end
140143

144+
@testset "dispersion parameter" begin
141145

142-
# NB: "deviance" is complicated in lme4
143-
# there are several "deviances" defined:
144-
# https://github.com/lme4/lme4/issues/375#issuecomment-214494445
145-
# this is the way deviance(glmm) is computed in lme4
146-
# also called devianceCondRel in
147-
# https://github.com/lme4/lme4/blob/master/misc/logLikGLMM/logLikGLMM.R
148-
lme4deviance(x) = sum(x.resp.devresid)
149-
146+
# NB: "deviance" is complicated in lme4
147+
# there are several "deviances" defined:
148+
# https://github.com/lme4/lme4/issues/375#issuecomment-214494445
149+
# this is the way deviance(glmm) is computed in lme4
150+
# also called devianceCondRel in
151+
# https://github.com/lme4/lme4/blob/master/misc/logLikGLMM/logLikGLMM.R
152+
lme4deviance(x) = sum(x.resp.devresid)
153+
154+
## simulate some data ##
155+
rng = StableRNG(42)
156+
ng = 25
157+
ns = 500
158+
# random effect
159+
σ = 1
160+
σre = 0.5
161+
u = repeat(randn(rng, ns) .* σre, ng)
162+
id = PooledArray(string.(repeat(1:ns, ng)))
163+
# fixed effect
164+
x = rand(rng, ns*ng)
150165

151-
@testset "dispersion parameter" begin
152166
@testset "Gaussian with non identity link" begin
153167
dyestuff = MixedModels.dataset(:dyestuff)
154168
gauss = fit(MixedModel, only(gfms[:dyestuff]), dyestuff, Normal(), LogLink(), fast=true)
@@ -160,5 +174,18 @@ lme4deviance(x) = sum(x.resp.devresid)
160174
@test lme4deviance(gauss) 115187.5
161175
@test only(gauss.θ) 0.0
162176
@test only(gauss.beta) 7.331387691046023
177+
# this works, but starting from a clean fit doesn't
178+
# I'm not sure why the optimizer gets lost
179+
refit!(gauss, fast=false)
180+
181+
rng = StableRNG(42)
182+
link = InverseLink()
183+
offset = abs(minimum(u)) + 1
184+
y = map(d -> rand(rng, d), Normal.(linkinv.(link, u .+ offset), σ))
185+
dat = (u=u, id=id, x=x, y=y)
186+
gaussim = GeneralizedLinearMixedModel(@formula(y ~ 1 + (1|id)), dat,
187+
Normal(), InverseLink())
188+
fit!(gaussim, fast=true)
189+
@test only(gaussim.β) linkfun(link, mean(y))
163190
end
164191
end

0 commit comments

Comments
 (0)