当参数类型依赖时如何在 Julia 中编写函数
How to write a function in Julia when the type the arguments are dependent
首先我要承认我是 Julia 的初学者,所以很可能存在针对我的问题的更好的体系结构。所以,也请考虑一下!不管怎样,问题来了。
我正在开发贝叶斯数据包 analysis.I 从最简单的模型开始,贝叶斯有限混合模型。我们假设数据是由有限数量的概率分布生成的。在贝叶斯分析中,我们将先验放在可能性上,并将其称为贝叶斯成分。
我已经为每个组件定义了一个新类型。例如 Gaussian1DGaussian1D, MultinomialDirichlet, ....
type Gaussian1DGaussian1D
μ0::Float64 # mean hyper-parameter
σ20::Float64 # variance hyper-parameter
μ::Float64 # mean of the Gaussian1D likelihood
σ2::Float64 # fixed variance of the Gaussian1D likelihood
nn::Int64 # number of data points the component contains
Gaussian1DGaussian1D(μ0::Real, σ20::Real, μ::Real, σ2::Real, nn::Real) = new(μ0, σ20, μ, σ2, nn)
end
Gaussian1DGaussian1D(μ0::Real, σ20::Real, σ2::Real) = Gaussian1DGaussian1D(μ0, σ20, μ0, σ2, 0)
Base.deepcopy(me::Gaussian1DGaussian1D) = Gaussian1DGaussian1D(me.μ0, me.σ20, me.μ, me.σ2, me.nn)
function logpredictive(me::Gaussian1DGaussian1D, xx::Real)
# returns the log-predictive of xx given the observed data
# i.e. log p(xx|x1,...,xn)
μ, σ2 = posterior(me)
ll = exp(-(xx - μ)^2 / (2*(σ2 + me.σ2))) / sqrt(2*pi * (σ2 + me.σ2))
return log(ll)
end
以及每种类型的许多其他功能。
现在我定义了一个参数化的 FiniteMixtureModel:
type FiniteMixtureModel{T}
bayesian_component::Vector{T}
K::Int64
FiniteMixtureModel{T}(c::T, K::Int64) = new([deepcopy(c) for k = 1:K], K)
end
FiniteMixtureModel{T}(c::T, K) = FiniteMixtureModel{eltype(c)}(c, K)
这使我能够定义先前定义的贝叶斯组件的 FiniteMixtureModel。例如,myFMM 将是 5 个高斯似然与高斯先验的混合模型。
myFMM = FiniteMixtureModel(Gaussian1DGaussian1D(1, 1, 1), 5)
现在为了推理,我定义了一个 Gibbs 采样器。
function gibbs_sampler(fmm::FiniteMixtureModel, xx::Vector{???}, ...)
# TO BE IMPLEMENTED!
println("Hi")
end
xx 的类型取决于 fmm 的元素类型。例如,如果 fmm 是 Gaussian1DGaussian1D 的 FMM,则 xx 将是浮点向量。如果 fmm 是 MultinomialDirichlet 的 FMM,则 xx 将是整数向量。函数的主体对于任何类型 (xx) 都是完全相同的。我如何编写一个函数来考虑其参数类型之间的这种依赖性?
xx
的类型应该和bayesian_component
的类型一样吧?
如果你不想让 xx
成为 FiniteMixtureModel
的组成部分(这似乎混淆了你的类型层次结构),你可以显式转换 xx
作为解决方法:
function gibbs_sampler(fmm::FiniteMixtureModel, xx::Vector, ...)
xx = oftype(fmm.bayesian_component,xx)
# TO BE IMPLEMENTED!
println("Hi")
end
然而,这可能会导致一些 InexactError
s:
例如当 eltype(xx)=Float64
, eltype(bayesian_component)=Int64
您可以编写多个具有 julia 的 多重分派 功能的函数。在这种情况下,你可以这样写:
function gibbs_sampler(fmm::FiniteMixtureModel{Gaussian1DGaussian1D}, xx::Vector{Float64}, ...)
# TO BE IMPLEMENTED!
println("Hi")
end
function gibbs_sampler(fmm::FiniteMixtureModel{MultinomialDirichlet}, xx::Vector{Int64}, ...)
# TO BE IMPLEMENTED!
println("Hi")
end
...
...
但这看起来多余。这就是 parameterised function 出现的地方,这是@ColinTBowers 推荐的。
或者您可以使用 fill
函数来减少冗余:
function fill(fmm, xx, ...)
#TO BE IMPLEMENTED!
println("Hi")
end
function gibbs_sampler(fmm::FiniteMixtureModel{Gaussian1DGaussian1D}, xx::Vector{Float64}, ...)
fill(fmm, xx, ...)
end
function gibbs_sampler(fmm::FiniteMixtureModel{MultinomialDirichlet}, xx::Vector{Int64}, ...)
fill(fmm, xx, ...)
end
...
...
首先我要承认我是 Julia 的初学者,所以很可能存在针对我的问题的更好的体系结构。所以,也请考虑一下!不管怎样,问题来了。
我正在开发贝叶斯数据包 analysis.I 从最简单的模型开始,贝叶斯有限混合模型。我们假设数据是由有限数量的概率分布生成的。在贝叶斯分析中,我们将先验放在可能性上,并将其称为贝叶斯成分。
我已经为每个组件定义了一个新类型。例如 Gaussian1DGaussian1D, MultinomialDirichlet, ....
type Gaussian1DGaussian1D
μ0::Float64 # mean hyper-parameter
σ20::Float64 # variance hyper-parameter
μ::Float64 # mean of the Gaussian1D likelihood
σ2::Float64 # fixed variance of the Gaussian1D likelihood
nn::Int64 # number of data points the component contains
Gaussian1DGaussian1D(μ0::Real, σ20::Real, μ::Real, σ2::Real, nn::Real) = new(μ0, σ20, μ, σ2, nn)
end
Gaussian1DGaussian1D(μ0::Real, σ20::Real, σ2::Real) = Gaussian1DGaussian1D(μ0, σ20, μ0, σ2, 0)
Base.deepcopy(me::Gaussian1DGaussian1D) = Gaussian1DGaussian1D(me.μ0, me.σ20, me.μ, me.σ2, me.nn)
function logpredictive(me::Gaussian1DGaussian1D, xx::Real)
# returns the log-predictive of xx given the observed data
# i.e. log p(xx|x1,...,xn)
μ, σ2 = posterior(me)
ll = exp(-(xx - μ)^2 / (2*(σ2 + me.σ2))) / sqrt(2*pi * (σ2 + me.σ2))
return log(ll)
end
以及每种类型的许多其他功能。
现在我定义了一个参数化的 FiniteMixtureModel:
type FiniteMixtureModel{T}
bayesian_component::Vector{T}
K::Int64
FiniteMixtureModel{T}(c::T, K::Int64) = new([deepcopy(c) for k = 1:K], K)
end
FiniteMixtureModel{T}(c::T, K) = FiniteMixtureModel{eltype(c)}(c, K)
这使我能够定义先前定义的贝叶斯组件的 FiniteMixtureModel。例如,myFMM 将是 5 个高斯似然与高斯先验的混合模型。
myFMM = FiniteMixtureModel(Gaussian1DGaussian1D(1, 1, 1), 5)
现在为了推理,我定义了一个 Gibbs 采样器。
function gibbs_sampler(fmm::FiniteMixtureModel, xx::Vector{???}, ...)
# TO BE IMPLEMENTED!
println("Hi")
end
xx 的类型取决于 fmm 的元素类型。例如,如果 fmm 是 Gaussian1DGaussian1D 的 FMM,则 xx 将是浮点向量。如果 fmm 是 MultinomialDirichlet 的 FMM,则 xx 将是整数向量。函数的主体对于任何类型 (xx) 都是完全相同的。我如何编写一个函数来考虑其参数类型之间的这种依赖性?
xx
的类型应该和bayesian_component
的类型一样吧?
如果你不想让 xx
成为 FiniteMixtureModel
的组成部分(这似乎混淆了你的类型层次结构),你可以显式转换 xx
作为解决方法:
function gibbs_sampler(fmm::FiniteMixtureModel, xx::Vector, ...)
xx = oftype(fmm.bayesian_component,xx)
# TO BE IMPLEMENTED!
println("Hi")
end
然而,这可能会导致一些 InexactError
s:
例如当 eltype(xx)=Float64
, eltype(bayesian_component)=Int64
您可以编写多个具有 julia 的 多重分派 功能的函数。在这种情况下,你可以这样写:
function gibbs_sampler(fmm::FiniteMixtureModel{Gaussian1DGaussian1D}, xx::Vector{Float64}, ...)
# TO BE IMPLEMENTED!
println("Hi")
end
function gibbs_sampler(fmm::FiniteMixtureModel{MultinomialDirichlet}, xx::Vector{Int64}, ...)
# TO BE IMPLEMENTED!
println("Hi")
end
...
...
但这看起来多余。这就是 parameterised function 出现的地方,这是@ColinTBowers 推荐的。
或者您可以使用 fill
函数来减少冗余:
function fill(fmm, xx, ...)
#TO BE IMPLEMENTED!
println("Hi")
end
function gibbs_sampler(fmm::FiniteMixtureModel{Gaussian1DGaussian1D}, xx::Vector{Float64}, ...)
fill(fmm, xx, ...)
end
function gibbs_sampler(fmm::FiniteMixtureModel{MultinomialDirichlet}, xx::Vector{Int64}, ...)
fill(fmm, xx, ...)
end
...
...