Документация Engee

Создание сэмплеров и распределений

Хотя данный пакет уже содержит большую коллекцию готовых распределений, возможны ситуации, когда необходимо создать собственное распределение (например, если в приложении требуется распределение особого типа или вы хотите внести свой вклад в пакет).

Как правило, не требуется реализовывать каждый метод API, описанный в документации. Данный пакет предоставляет ряд универсальных функций, которые превращают небольшой набор внутренних методов в доступные пользователям методы API. Достаточно реализовать этот ограниченный набор внутренних методов для своих распределений.

По умолчанию поддерживающие выборку объекты Discrete поддерживают тип Int, а поддерживающие выборку объекты Continuous — тип Float64. Если это допущение не соблюдается для вашего нового распределения или сэмплера либо если его тип ValueSupport отличен от Discrete и Continuous, в дополнение к перечисленным ниже методам следует также реализовать метод eltype.

Примечание. Методы, требующие реализации, различаются в зависимости от размерности распределения.

Создание сэмплера

В отличие от полноценных распределений, сэмплер, как правило, предоставляет ограниченные возможности, в первую очередь связанные с выборкой.

Одномерный сэмплер

Чтобы реализовать одномерный сэмплер, можно определить подтип (например, Spl) типа Sampleable{Univariate,S} (где S может быть Discrete или Continuous) и предоставить метод rand:

function rand(rng::AbstractRNG, s::Spl)
    # ... генерируем одну выборку из s
end

В пакете уже реализована векторизированная версия функций rand! и rand, которая многократно вызывает скалярную версию для генерирования нескольких выборок, а также версия с одним аргументом, которая использует генератор случайных чисел по умолчанию.

Многомерный сэмплер

Чтобы реализовать многомерный сэмплер, можно определить подтип типа Sampleable{Multivariate,S} и предоставить методы length и _rand!:

Base.length(s::Spl) = ... # возвращаем длину каждой выборки

function _rand!(rng::AbstractRNG, s::Spl, x::AbstractVector{T}) where T<:Real
    # ... генерируем одну векторную выборку из x
end

Эта функция может предполагать, что измерение x верное и выполнять проверку измерений не нужно.

В пакете функции rand и rand! реализованы следующим образом (в общем случае реализовывать их самостоятельно не нужно):

function _rand!(rng::AbstractRNG, s::Sampleable{Multivariate}, A::DenseMatrix)
    for i = 1:size(A,2)
        _rand!(rng, s, view(A,:,i))
    end
    return A
end

function rand!(rng::AbstractRNG, s::Sampleable{Multivariate}, A::AbstractVector)
    length(A) == length(s) ||
        throw(DimensionMismatch("Output size inconsistent with sample length."))
    _rand!(rng, s, A)
end

function rand!(rng::AbstractRNG, s::Sampleable{Multivariate}, A::DenseMatrix)
    size(A,1) == length(s) ||
        throw(DimensionMismatch("Output size inconsistent with sample length."))
    _rand!(rng, s, A)
end

rand(rng::AbstractRNG, s::Sampleable{Multivariate,S}) where {S<:ValueSupport} =
    _rand!(rng, s, Vector{eltype(S)}(length(s)))

rand(rng::AbstractRNG, s::Sampleable{Multivariate,S}, n::Int) where {S<:ValueSupport} =
    _rand!(rng, s, Matrix{eltype(S)}(length(s), n))

Если есть более эффективный способ генерирования нескольких векторных выборок за один раз, следует предоставить следующий метод:

function _rand!(rng::AbstractRNG, s::Spl, A::DenseMatrix{T}) where T<:Real
    # ... генерируем несколько векторных выборок за один раз
end

Напомним, что каждый столбец A — это выборка.

Сэмплер матричной размерности

Чтобы реализовать многомерный сэмплер, можно определить подтип типа Sampleable{Multivariate,S} и предоставить методы size и _rand!:

Base.size(s::Spl) = ... # размер каждой матричной выборки

function _rand!(rng::AbstractRNG, s::Spl, x::DenseMatrix{T}) where T<:Real
    # ... генерируем одну матричную выборку из x
end

Обратите внимание: в _rand! может предполагаться, что x имеет правильные измерения и что выполнять проверку измерений не нужно. Универсальные функции rand и rand! будут автоматически выполнять проверку измерений и выделение памяти для массивов.

Создание распределения

Большинство распределений должны реализовывать метод sampler для повышения эффективности пакетной выборки.

# Distributions.samplerMethod

sampler(d::Distribution) -> Sampleable
sampler(s::Sampleable) -> s

Сэмплеры часто используют предварительно вычисленные значения (сами по себе не являющиеся параметрами) для повышения эффективности. Для такого сэмплера можно предоставить метод sampler, который будет использоваться для пакетной выборки. Общий резервный метод — sampler(d::Distribution) = d.

Одномерное распределение

Тип одномерного распределения должен определяться как подтип типа DiscreteUnivarateDistribution или ContinuousUnivariateDistribution.

Для каждого типа одномерного распределения необходимо реализовать следующие методы:

Кроме того, рекомендуется реализовать следующие статистические функции.

Узнать в подробностях, как реализованы универсальные функции для одномерных распределений, можно в файле исходного кода src/univariates.jl.

Создание многомерного распределения

Тип многомерного распределения должен определяться как подтип типа DiscreteMultivarateDistribution или ContinuousMultivariateDistribution.

Для каждого типа многомерного распределения необходимо реализовать следующие методы:

Обратите внимание: если существуют более быстрые методы пакетных вычислений, следует переопределить _logpdf! и _pdf!.

Кроме того, универсальная функция loglikelihood многократно вызывает _logpdf. Если есть более эффективный способ вычисления логарифмического правдоподобия, следует переопределить loglikelihood.

Кроме того, рекомендуется реализовать следующие статистические функции.

Создание распределения матричной размерности

Тип распределения матричной размерности должен определяться как подтип типа DiscreteMatrixDistribution или ContinuousMatrixDistribution.

Для каждого типа распределения матричной размерности необходимо реализовать следующие методы.