-
Notifications
You must be signed in to change notification settings - Fork 430
Ekdist -- exponentiated Kumaraswamy #1951
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
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1951 +/- ##
==========================================
- Coverage 86.19% 85.29% -0.91%
==========================================
Files 146 147 +1
Lines 8768 8861 +93
==========================================
Hits 7558 7558
- Misses 1210 1303 +93 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some preliminary suggestions and comments, haven't reviewed everything at the moment.
""" | ||
kumaraswamy(α,β,γ,l,u) | ||
The exponentiated (scaled) kumaraswamy (EK) distribution is 5 paramter two of which are normalizing constants (l,u) to a range. | ||
``` | ||
```julia | ||
kumaraswamy() # distribution with zero log-mean and unit scale | ||
params(d) # Get the parameters, | ||
``` | ||
External links | ||
* [Wikipedia](https://en.wikipedia.org/wiki/Kumaraswamy_distribution | ||
* The exponentiated Kumaraswamy Distribution and its log-transform: Lemonte et al https://www.jstor.org/stable/43601233 | ||
|
||
""" | ||
## NEED TO ACCOMONDATE LOG(1 -1) when x hits the upper bound of support | ||
## I get errors in trying to extend Distiributions functions in the script because I don't understand modules lol | ||
using Distributions | ||
import Distributions: @check_args, @distr_support, params, convert, partype, beta, gamma | ||
import Distributions: AbstractRNG, maximum, minimum, convert | ||
import Distributions: pdf, logpdf, gradlogpdf, cdf, ccdf, logcdf, logccdf, quantile, cquantile, median, mean, var, skewness, kurtosis, mode | ||
import Distributions: fit_mle | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation can be extended later to include scaling without being a breaking change, so let's keep it simpler for the time being and use the unit interval.
Also, there's no need to load those various symbols from the Distributions
namespace given that this file is included within that namespace; it can already access the symbols unqualified.
The suggestion here makes the docstring content consistent with that of Kumaraswamy
.
""" | |
kumaraswamy(α,β,γ,l,u) | |
The exponentiated (scaled) kumaraswamy (EK) distribution is 5 paramter two of which are normalizing constants (l,u) to a range. | |
``` | |
```julia | |
kumaraswamy() # distribution with zero log-mean and unit scale | |
params(d) # Get the parameters, | |
``` | |
External links | |
* [Wikipedia](https://en.wikipedia.org/wiki/Kumaraswamy_distribution | |
* The exponentiated Kumaraswamy Distribution and its log-transform: Lemonte et al https://www.jstor.org/stable/43601233 | |
""" | |
## NEED TO ACCOMONDATE LOG(1 -1) when x hits the upper bound of support | |
## I get errors in trying to extend Distiributions functions in the script because I don't understand modules lol | |
using Distributions | |
import Distributions: @check_args, @distr_support, params, convert, partype, beta, gamma | |
import Distributions: AbstractRNG, maximum, minimum, convert | |
import Distributions: pdf, logpdf, gradlogpdf, cdf, ccdf, logcdf, logccdf, quantile, cquantile, median, mean, var, skewness, kurtosis, mode | |
import Distributions: fit_mle | |
""" | |
EKDist(α, β, γ) | |
The *exponentiated Kumaraswamy (EK) distribution* with shape parameters `α > 0`, `β > 0`, | |
and `γ > 0` has probability density function | |
```math | |
f(x; α, β, γ) = α β γ x^{α - 1} (x - x^α)^{β - 1} (1 - (1 - x^α)^β)^{γ - 1}, \\quad 0 < x < 1 | |
``` | |
When `γ == 1`, this reduces to the [Kumaraswamy distribution](@ref Kumaraswamy). | |
References | |
- Lemonte, A. J., Barreto-Souza, W., & Cordeiro, G. M. (2013). The exponentiated Kumaraswamy | |
distribution and its log-transform. Brazilian Journal of Probability and Statistics, 27(1), | |
31–53. http://www.jstor.org/stable/43601233 | |
""" |
l::T | ||
u::T | ||
EKDist{T}(α, β, γ, l, u) where {T} = new{T}(α, β, γ, l, u) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
l::T | |
u::T | |
EKDist{T}(α, β, γ, l, u) where {T} = new{T}(α, β, γ, l, u) | |
EKDist{T}(α, β, γ) where {T} = new{T}(α, β, γ) |
Removing the bounds as noted in the previous comment.
function EKDist(α::T, β::T, γ::T, l::T, u::T; check_args::Bool=true) where {T <: Real} | ||
@check_args EKDist (α, α ≥ zero(α)) (β, β ≥ zero(β)) (γ, γ ≥ zero(γ)) (l < u) | ||
return EKDist{T}(α, β, γ, l, u) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function EKDist(α::T, β::T, γ::T, l::T, u::T; check_args::Bool=true) where {T <: Real} | |
@check_args EKDist (α, α ≥ zero(α)) (β, β ≥ zero(β)) (γ, γ ≥ zero(γ)) (l < u) | |
return EKDist{T}(α, β, γ, l, u) | |
function EKDist(α::T, β::T, γ::T; check_args::Bool=true) where {T<:Real} | |
@check_args EKDist (α, α > zero(α)) (β, β > zero(β)) (γ, γ > zero(γ)) | |
return EKDist{T}(α, β, γ) |
Lemonte et al. define the parameters to be strictly positive, not non-negative. That's noted for γ
at the beginning of section 2, and for α
and β
immediately following equation 2.1. (That also follows from the definition of the Kumaraswamy distribution, for which the shape parameters are positive.)
EKDist(α::Real, β::Real, γ::Real, l::Real, u::Real; check_args::Bool=true) = | ||
EKDist(promote(α, β, γ, l, u)...; check_args=check_args) | ||
|
||
EKDist(α::Integer, β::Integer, γ::Integer, l::Integer, u::Integer ; check_args::Bool=true) = | ||
EKDist(float(α), float(β), float(γ), float(l), float(u); check_args=check_args) | ||
|
||
EKDist(α::Real, β::Real, γ::Real; check_args::Bool=true) = EKDist(promote(α, β, γ, 0.0, 1.0)...; check_args=check_args) | ||
EKDist(α::Real, β::Real; check_args::Bool=true) = EKDist(promote(α, β, 1.0, 0.0, 1.0)...; check_args=check_args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can combine this with the method for integer arguments by adding a call to float
in this method, which will just be a no-op for when the arguments are already promoted to a float type.
I've also replaced here the methods that set default values with a single method that takes no arguments. This is for consistency with other distributions, e.g. Kumaraswamy. I think all arguments should be required to be supplied when any are supplied; if someone is relying on a default of γ == 1
, they should just use Kumaraswamy
directly instead.
EKDist(α::Real, β::Real, γ::Real, l::Real, u::Real; check_args::Bool=true) = | |
EKDist(promote(α, β, γ, l, u)...; check_args=check_args) | |
EKDist(α::Integer, β::Integer, γ::Integer, l::Integer, u::Integer ; check_args::Bool=true) = | |
EKDist(float(α), float(β), float(γ), float(l), float(u); check_args=check_args) | |
EKDist(α::Real, β::Real, γ::Real; check_args::Bool=true) = EKDist(promote(α, β, γ, 0.0, 1.0)...; check_args=check_args) | |
EKDist(α::Real, β::Real; check_args::Bool=true) = EKDist(promote(α, β, 1.0, 0.0, 1.0)...; check_args=check_args) | |
EKDist(α::Real, β::Real, γ::Real; check_args::Bool=true) = | |
EKDist(float.(promote(α, β, γ))...; check_args=check_args) | |
EKDist() = EKDist{Float64}(1.0, 1.0, 1.0) |
# @distr_support macro would set constant bounds but we need to take bounds from input | ||
# so we will just define them ourselves | ||
maximum(d::EKDist) = d.u | ||
minimum(d::EKDist) = d.l |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# @distr_support macro would set constant bounds but we need to take bounds from input | |
# so we will just define them ourselves | |
maximum(d::EKDist) = d.u | |
minimum(d::EKDist) = d.l | |
@distr_support EKDist 0 1 |
Also note that you can use parameters as distribution support limits with this macro, see e.g. Cosine
.
function ccdf(d::EKDist, x::Real) | ||
xs = (x - d.l) / (d.u - d.l) | ||
α = d.α | ||
β = d.β | ||
γ = d.γ | ||
|
||
return 1 - (1 - ( 1 - xs^α)^β)^γ | ||
end | ||
|
||
function logcdf(d::EKDist, x::Real) | ||
return log(cdf(d, x)) | ||
end | ||
|
||
function logccdf(d::EKDist, x::Real) | ||
return log(ccdf(d, x)) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These methods aren't necessary, as they're identical to the fallback methods.
function ccdf(d::EKDist, x::Real) | |
xs = (x - d.l) / (d.u - d.l) | |
α = d.α | |
β = d.β | |
γ = d.γ | |
return 1 - (1 - ( 1 - xs^α)^β)^γ | |
end | |
function logcdf(d::EKDist, x::Real) | |
return log(cdf(d, x)) | |
end | |
function logccdf(d::EKDist, x::Real) | |
return log(ccdf(d, x)) | |
end |
xs = (x - d.l) / (d.u - d.l) | ||
α = d.α | ||
β = d.β | ||
γ = d.γ | ||
return (1 - ( 1 - xs^α)^β)^γ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
xs = (x - d.l) / (d.u - d.l) | |
α = d.α | |
β = d.β | |
γ = d.γ | |
return (1 - ( 1 - xs^α)^β)^γ | |
α, β, γ = params(d) | |
y = (1 - (1 - clamp(x, 0, 1)^α)^β)^γ | |
return x < 0 ? zero(y) : (x > 1 ? one(y) : y) |
function fit_mle(::Type{<:EKDist}, x::AbstractArray{T}) where T<:Real | ||
#incomplete | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to not define the method at all than to have it return nothing
.
function fit_mle(::Type{<:EKDist}, x::AbstractArray{T}) where T<:Real | |
#incomplete | |
end | |
# `fit_mle` not yet implemented |
|
||
|
||
#### Statistics | ||
median(d::EKDist) = quantile(d, .5) # right? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is identical to the fallback definition.
median(d::EKDist) = quantile(d, .5) # right? |
β = d.β | ||
γ = d.γ | ||
|
||
# can't tell from paper if its infinite sum or stops at the floor of γ -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which part of the paper are you looking at? They looked like infinite sums to me, but maybe I missed something.
I believe my functions are accurate; however in testing the mean of the current kumaraswamy.jl the did not match in some cases. I believe this to be an error in the kumaraswamy.jl in the version I was using. The EK distribution has the Kumaraswamy as a special case, so it is easy to test keeping gamma = 1.