How to embed a CubicSpline in an RxInfer model #469
Replies: 2 comments 2 replies
-
Hi @joshualeond! Thanks for trying out RxInfer. Below is a functioning example. Not sure of the quality of estimates as that is for you to judge. The problem was the following. In RxInfer you can not use the random variables as indexes. Instead
|
Beta Was this translation helpful? Give feedback.
-
Hi @joshualeond! Thanks for checking out rxinfer! A quick solution would be: using RxInfer, CubicSplines, Distributions, Random, Plots
# Simulate some data
Random.seed!(42)
n = 100
I = randn(n) # Simulated current measurements
soc_true = cumsum(0.01 .+ 0.1 .* randn(n))
soc_true = clamp.(soc_true, 0, 1)
ocv_data = 3.0 .+ 0.8 .* soc_true .+ 0.02 .* randn(n)
y = ocv_data
# Fit the spline
soc_grid = 0:0.1:1
ocv_grid = 3.0 .+ 0.8 .* soc_grid .+ 0.01 .* randn(length(soc_grid))
spline = CubicSpline(soc_grid, ocv_grid, extrapl=[1,], extrapr=[1,])
my_spline(x) = spline(x)
@show my_spline(0.5)
# Model definition
@model function SoC_stream(y, I, B, αw, βw, αv, βv, spline)
λw ~ Gamma(shape = αw, rate = βw)
λv ~ Gamma(shape = αv, rate = βv)
SoC_prev ~ NormalMeanVariance(0.0, (0.01)^2)
for t in 1:length(y)
SoC_next[t] ~ NormalMeanPrecision(SoC_prev + B*I[t], λw)
tmp[t] := my_spline(SoC_next[t])
y[t] ~ NormalMeanPrecision(tmp[t], λv) # <---- Error happens here
SoC_prev = SoC_next[t]
end
end
spline_meta = @meta begin
my_spline() -> Unscented()
end
# Set parameters
B = 0.01
αw, βw = 2.0, 2.0
αv, βv = 2.0, 2.0
# Attempt inference
init = @initialization begin
# seed the plate’s marginals (same name as in @model)
μ(SoC_next) = NormalMeanVariance(0, (0.01)^2)
# seed the two precision priors
q(λw) = GammaShapeRate(αw, βw)
q(λv) = GammaShapeRate(αv, βv)
end
constraints = @constraints begin
# Group the entire SoC chain vs. the two precisions
q(SoC_prev, SoC_next, tmp, λw, λv) = q(SoC_prev, SoC_next)q(tmp)q(λw)q(λv)
end
model = SoC_stream(B = B, αw = αw, βw = βw, αv = αv, βv = βv, spline = spline)
result = infer(
model = model,
data = (y = y, I = I),
returnvars = ( SoC_next = KeepLast(),
tmp = KeepLast(),
λw = KeepLast(),
λv = KeepLast() ),
initialization = init,
meta = spline_meta,
constraints = constraints,
iterations = 100,
free_energy = true,
options = (limit_stack_depth = 300,)
)
plot(result.free_energy)
# Review results
margs = vcat(result.posteriors[:tmp]...) # flatten Vector{Marginal}
soc_mean = [ mean(m) for m in margs ]
soc_std = [ std(m) for m in margs ]
scatter(y, label="observed SoC", xlabel="Time", ylabel="SoC", title="SoC Estimation")
plot!(3.0 .+ 0.8 .* soc_true, label="True SoC")
plot!(soc_mean, ribbon=soc_std, label="SoC mean", xlabel="Time", ylabel="SoC", title="SoC Estimation") You need to do approximations around Please shoot any questions you might have. UPD: Did few changes in the plotting and posterior extraction (changed to |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi there, I've been working with the RxInfer.jl package and am really excited to see this work! I'm attempting to embed a fitted spline within a model like the following:
where the spline is fit like the following:
Indexing the fitted spline simply returns the result of
y
given inputx
:The error I'm seeing when I attempt to run
infer
on theSoC_stream
model shown above is the following:Using a fitted spline in
Turing.jl
seemed to work fine for the most part but I'm new toRxInfer.jl
and am not really sure how to resolve this. Any info would be appreciated.Here's the entire reproducible example:
Beta Was this translation helpful? Give feedback.
All reactions