Skip to content

Remove median(::MvLogNormal) #1966

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions docs/src/multivariate.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,10 @@ In addition to the methods listed in the common interface above, we also provide
```@docs
location(::MvLogNormal)
scale(::MvLogNormal)
median(::MvLogNormal)
mode(::MvLogNormal)
```

It can be necessary to calculate the parameters of the lognormal (location vector and scale matrix) from a given covariance and mean, median or mode. To that end, the following functions are provided.
It can be necessary to calculate the parameters of the lognormal (location vector and scale matrix) from a given covariance and mean or mode. To that end, the following functions are provided.

```@docs
location{D<:Distributions.AbstractMvLogNormal}(::Type{D},s::Symbol,m::AbstractVector,S::AbstractMatrix)
Expand Down
24 changes: 4 additions & 20 deletions src/multivariate/mvlognormal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# - _logpdf(d,x) Evaluate logarithm of pdf
# - _pdf(d,x) Evaluate the pdf
# - mean(d) Mean of the distribution
# - median(d) Median of the distribution
# - mode(d) Mode of the distribution
# - var(d) Vector of element-wise variance
# - cov(d) Covariance matrix
Expand Down Expand Up @@ -58,21 +57,14 @@ function _location!(::Type{D},::Type{Val{:mean}},mn::AbstractVector,S::AbstractM
μ
end

function _location!(::Type{D},::Type{Val{:median}},md::AbstractVector,S::AbstractMatrix,μ::AbstractVector) where D<:AbstractMvLogNormal
@simd for i=1:length(md)
@inbounds μ[i] = log(md[i])
end
μ
end

function _location!(::Type{D},::Type{Val{:mode}},mo::AbstractVector,S::AbstractMatrix,μ::AbstractVector) where D<:AbstractMvLogNormal
@simd for i=1:length(mo)
@inbounds μ[i] = log(mo[i]) + S[i,i]
end
μ
end

###Functions to calculate location and scale for a distribution with desired :mean, :median or :mode and covariance
###Functions to calculate location and scale for a distribution with desired :mean or :mode and covariance
"""
location!{D<:AbstractMvLogNormal}(::Type{D},s::Symbol,m::AbstractVector,S::AbstractMatrix,μ::AbstractVector)

Expand All @@ -91,12 +83,11 @@ Calculate the location vector (the mean of the underlying normal distribution).

- If `s == :meancov`, then m is taken as the mean, and S the covariance matrix of a
lognormal distribution.
- If `s == :mean | :median | :mode`, then m is taken as the mean, median or
- If `s == :mean | :mode`, then m is taken as the mean or
mode of the lognormal respectively, and S is interpreted as the scale matrix
(the covariance of the underlying normal distribution).

It is not possible to analytically calculate the location vector from e.g., median + covariance,
or from mode + covariance.
It is not possible to analytically calculate the location vector from e.g. from mode + covariance.
"""
function location(::Type{D},s::Symbol,m::AbstractVector,S::AbstractMatrix) where D<:AbstractMvLogNormal
@assert size(S) == (length(m),length(m))
Expand Down Expand Up @@ -209,17 +200,10 @@ scale(d::MvLogNormal) = cov(d.normal)
#See https://en.wikipedia.org/wiki/Log-normal_distribution
mean(d::MvLogNormal) = exp.(mean(d.normal) .+ var(d.normal)/2)

"""
median(d::MvLogNormal)

Return the median vector of the lognormal distribution. which is strictly smaller than the mean.
"""
median(d::MvLogNormal) = exp.(mean(d.normal))

"""
mode(d::MvLogNormal)

Return the mode vector of the lognormal distribution, which is strictly smaller than the mean and median.
Return the mode vector of the lognormal distribution, which is strictly smaller than the mean.
"""
mode(d::MvLogNormal) = exp.(mean(d.normal) .- var(d.normal))
function cov(d::MvLogNormal)
Expand Down
15 changes: 0 additions & 15 deletions test/multivariate/mvlognormal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,21 @@ function test_mvlognormal(g::MvLogNormal, n_tsamples::Int=10^6,
rng::Union{AbstractRNG, Missing} = missing)
d = length(g)
mn = mean(g)
md = median(g)
mo = mode(g)
S = cov(g)
s = var(g)
e = entropy(g)
@test partype(g) == Float64
@test isa(mn, Vector{Float64})
if g.normal.μ isa Zeros{Float64,1}
@test md isa FillArrays.AbstractFill{Float64,1}
else
@test md isa Vector{Float64}
end
@test isa(mo, Vector{Float64})
@test isa(s, Vector{Float64})
@test isa(S, Matrix{Float64})
@test length(mn) == d
@test length(md) == d
@test length(mo) == d
@test length(s) == d
@test size(S) == (d, d)
@test s ≈ diag(S)
@test std(g) ≈ sqrt.(diag(S))
@test md ≈ exp.(mean(g.normal))
@test mn ≈ exp.(mean(g.normal) .+ var(g.normal)/2)
@test mo ≈ exp.(mean(g.normal) .- var(g.normal))
@test entropy(g) ≈ d*(1 + Distributions.log2π)/2 + logdetcov(g.normal)/2 + sum(mean(g.normal))
Expand All @@ -51,15 +43,11 @@ function test_mvlognormal(g::MvLogNormal, n_tsamples::Int=10^6,
X = rand(rng, g, n_tsamples)
end
emp_mn = vec(mean(X, dims=2))
emp_md = vec(median(X, dims=2))
Z = X .- emp_mn
emp_cov = (Z * Z') ./ n_tsamples
for i = 1:d
@test isapprox(emp_mn[i] , mn[i] , atol=(sqrt(s[i] / n_tsamples) * 8.0))
end
for i = 1:d
@test isapprox(emp_md[i] , md[i] , atol=(sqrt(s[i] / n_tsamples) * 8.0))
end
for i = 1:d, j = 1:d
@test isapprox(emp_cov[i,j], S[i,j], atol=(sqrt(s[i] * s[j]) * 20.0) / sqrt(n_tsamples))
end
Expand All @@ -77,13 +65,11 @@ function test_mvlognormal(g::MvLogNormal, n_tsamples::Int=10^6,
# test the location and scale functions
@test isapprox(location(g), location(MvLogNormal,:meancov,mean(g),cov(g)) , atol=1e-8)
@test isapprox(location(g), location(MvLogNormal,:mean,mean(g),scale(g)) , atol=1e-8)
@test isapprox(location(g), location(MvLogNormal,:median,median(g),scale(g)), atol=1e-8)
@test isapprox(location(g), location(MvLogNormal,:mode,mode(g),scale(g)) , atol=1e-8)
@test isapprox(scale(g) , scale(MvLogNormal,:meancov,mean(g),cov(g)) , atol=1e-8)

@test isapprox(location(g), location!(MvLogNormal,:meancov,mean(g),cov(g),zero(mn)) , atol=1e-8)
@test isapprox(location(g), location!(MvLogNormal,:mean,mean(g),scale(g),zero(mn)) , atol=1e-8)
@test isapprox(location(g), location!(MvLogNormal,:median,median(g),scale(g),zero(mn)), atol=1e-8)
@test isapprox(location(g), location!(MvLogNormal,:mode,mode(g),scale(g),zero(mn)) , atol=1e-8)
@test isapprox(scale(g) , Distributions.scale!(MvLogNormal,:meancov,mean(g),cov(g),zero(S)), atol=1e-8)

Expand All @@ -100,7 +86,6 @@ end
l1 = LogNormal(0.1, 0.4)
l2 = MvLogNormal([0.1], 0.16 * I)
@test [mean(l1)] ≈ mean(l2)
@test [median(l1)] ≈ median(l2)
@test [mode(l1)] ≈ mode(l2)
@test [var(l1)] ≈ var(l2)
@test entropy(l1) ≈ entropy(l2)
Expand Down
Loading