-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add function for computing the KDE with boundary reflection * Fix issues with KDE grid padding * Add utility function for KDE bounds checking * Refactor kde_reflected into internal func * Document kde_reflected * Add improved Sheather-Jones bandwidth rule * Add missing imports * Add tests for reflected KDE and bandwidth * Fix variable name * Avoid internal KDE.jl functions * Fix silverman bandwidth * Define internal density estimation interface * Add missing include statement * Add multimodal HDI * Use range signatures present in Julia v1.6 * Bump FFTW version At least this version is required for downgrade CI * Fix doctest * Skip test on Julia v1.6 * Add tests for density estimation interface * Bump StatsBase lower bound So histrange works * Fix version check * Update other doctests * Update HDI doctests * Actually repair HDI docstrings * Restore type-inferrability for Symbol methods * Throw ArgumentrError for invalid prob To match behavior of quantile/eti * Make sure interval eltype matches sample eltype * Consistently handle NaNs * Update HDI tests * Use `Compat.@constprop` for old Julia versions * Define missing variable * Document KDE kwargs * Use ISJ bandwidth by default for KDE * Add kde_reflected to utility docs * Skip type inference tests for old Julia versions * Fix doctest * Give more details about HDI methods * Bump FFTW compat This version is required for multimodal HDI type inference
- Loading branch information
Showing
13 changed files
with
870 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,5 +61,6 @@ r2_score | |
### Utilities | ||
|
||
```@docs | ||
PosteriorStats.kde_reflected | ||
PosteriorStats.smooth_data | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# Density estimation methods and utilities | ||
|
||
""" | ||
DensityEstimationMethod | ||
Abstract type for density estimation methods. | ||
Densities are defined wrt the Lebesgue measure on subintervals of the real line for | ||
continuous data or the counting measure on unique values for discrete data. | ||
Each method should implement: | ||
- `bins_and_probs(::DensityEstimationMethod, x::AbstractVector{<:Real}) -> (bins, probs)` | ||
Returns the density evaluated at regularly spaced points, normalized to sum to 1. | ||
Empty bins may be omitted. | ||
- `density_at(::DensityEstimationMethod, x::AbstractVector{<:Real}) -> densities` | ||
Returns the density evaluated at the points in `x` | ||
""" | ||
abstract type DensityEstimationMethod end | ||
|
||
""" | ||
DefaultDensityEstimation <: DensityEstimationMethod | ||
Select density estimation method based on data type. | ||
""" | ||
struct DefaultDensityEstimation <: DensityEstimationMethod end | ||
|
||
""" | ||
DiscreteDensityEstimation <: DensityEstimationMethod | ||
Estimate density for integer-valued data using the counting measure. | ||
""" | ||
struct DiscreteDensityEstimation <: DensityEstimationMethod end | ||
|
||
function bins_and_probs(::DiscreteDensityEstimation, x::AbstractVector{<:Real}) | ||
prop_map = OrderedCollections.OrderedDict(StatsBase.proportionmap(x)) | ||
sort!(prop_map) | ||
bins = collect(keys(prop_map)) | ||
probs = collect(values(prop_map)) | ||
return bins, probs | ||
end | ||
|
||
""" | ||
HistogramEstimation{K} <: DensityEstimationMethod | ||
Estimate piecewise constant density using a histogram. | ||
""" | ||
struct HistogramEstimation{K} <: DensityEstimationMethod | ||
hist_kwargs::K | ||
end | ||
HistogramEstimation(; hist_kwargs...) = HistogramEstimation(hist_kwargs) | ||
|
||
function bins_and_probs(est::HistogramEstimation, x::AbstractVector{<:Real}) | ||
hist = StatsBase.fit(StatsBase.Histogram, x; est.hist_kwargs...) | ||
return StatsBase.midpoints(hist.edges[1]), normalize(hist; mode=:probability).weights | ||
end | ||
|
||
function density_at(est::HistogramEstimation, x::AbstractVector{<:Real}) | ||
hist = normalize( | ||
StatsBase.fit(StatsBase.Histogram, x; est.hist_kwargs...); mode=:density | ||
) | ||
return _histogram_density.(Ref(hist), x) | ||
end | ||
|
||
function _histogram_density(hist::StatsBase.Histogram, x::Real) | ||
edges = only(hist.edges) | ||
bin_index = _binindex(edges, hist.closed, x) | ||
weights = hist.weights | ||
return get(weights, bin_index, zero(eltype(weights))) | ||
end | ||
|
||
function _binindex(edges::AbstractVector, closed::Symbol, x::Real) | ||
if closed === :right | ||
return searchsortedfirst(edges, x) - 1 | ||
else | ||
return searchsortedlast(edges, x) | ||
end | ||
end | ||
|
||
""" | ||
KDEstimation{F,K} <: DensityEstimationMethod | ||
Estimate density as uniform mixture of identical data-centered kernels. | ||
""" | ||
struct KDEstimation{F,K} <: DensityEstimationMethod | ||
"""Function to use to compute the KDE, with signature | ||
`kde_func(x; kde_kwargs...) -> KernelDensity.UnivariateKDE`.""" | ||
kde_func::F | ||
"""Keyword arguments for `kde_func`.""" | ||
kde_kwargs::K | ||
end | ||
KDEstimation(kde_func=kde_reflected; kde_kwargs...) = KDEstimation(kde_func, kde_kwargs) | ||
|
||
function density_at(est::KDEstimation, x::AbstractVector{<:Real}) | ||
kde = est.kde_func(x; est.kde_kwargs...) | ||
return KernelDensity.pdf(kde, x) | ||
end | ||
|
||
function bins_and_probs(est::KDEstimation, x::AbstractVector{<:Real}) | ||
kde = est.kde_func(x; est.kde_kwargs...) | ||
bins = kde.x | ||
probs = kde.density * step(kde.x) | ||
return bins, probs | ||
end |
Oops, something went wrong.