Skip to content

Commit 0c05716

Browse files
paldaykleinschmidtararslannalimilan
authored
safer int for binomial loglik (#504)
* safer Int in Binomial log likelihood * patch bump * fallback method * drop extra tests * s/_safer/_safe/ Co-authored-by: Dave Kleinschmidt <[email protected]> Co-authored-by: Alex Arslan <[email protected]> Co-authored-by: Milan Bouchet-Valat <[email protected]>
1 parent 1459737 commit 0c05716

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "GLM"
22
uuid = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
3-
version = "1.8.0"
3+
version = "1.8.1"
44

55
[deps]
66
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"

src/glmtools.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,19 @@ false
499499
dispersion_parameter(D) = true
500500
dispersion_parameter(::Union{Bernoulli, Binomial, Poisson}) = false
501501

502+
"""
503+
_safe_int(x::T)
504+
505+
Convert to Int, when `x` is within 1 eps of an integer.
506+
"""
507+
function _safe_int(x::T) where {T<:AbstractFloat}
508+
r = round(Int, x)
509+
abs(x - r) <= eps(x) && return r
510+
throw(InexactError(nameof(T), T, x))
511+
end
512+
513+
_safe_int(x) = Int(x)
514+
502515
"""
503516
GLM.loglik_obs(D, y, μ, wt, ϕ)
504517
@@ -512,7 +525,7 @@ The loglikelihood of a fitted model is the sum of these values over all the obse
512525
function loglik_obs end
513526

514527
loglik_obs(::Bernoulli, y, μ, wt, ϕ) = wt*logpdf(Bernoulli(μ), y)
515-
loglik_obs(::Binomial, y, μ, wt, ϕ) = logpdf(Binomial(Int(wt), μ), Int(y*wt))
528+
loglik_obs(::Binomial, y, μ, wt, ϕ) = logpdf(Binomial(Int(wt), μ), _safe_int(y*wt))
516529
loglik_obs(::Gamma, y, μ, wt, ϕ) = wt*logpdf(Gamma(inv(ϕ), μ*ϕ), y)
517530
# In Distributions.jl, a Geometric distribution characterizes the number of failures before
518531
# the first success in a sequence of independent Bernoulli trials with success rate p.

test/runtests.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,3 +1591,15 @@ end
15911591
end
15921592
end
15931593

1594+
1595+
@testset "Floating point error in Binomial loglik" begin
1596+
@test_throws InexactError GLM._safe_int(1.3)
1597+
@test GLM._safe_int(1) === 1
1598+
# see issue 503
1599+
y, μ, wt, ϕ = 0.6376811594202898, 0.8492925285671102, 69.0, NaN
1600+
# due to floating point:
1601+
# 1. y * wt == 43.99999999999999
1602+
# 2. 44 / y == wt
1603+
# 3. 44 / wt == y
1604+
@test GLM.loglik_obs(Binomial(), y, μ, wt, ϕ) GLM.logpdf(Binomial(Int(wt), μ), 44)
1605+
end

0 commit comments

Comments
 (0)