Replies: 2 comments 9 replies
-
Hello @juliohm, thanks for the question. As far as I understand you are trying to create a discrete Markov random field. Technically, RxInfer can handle the problem of obtaining the associated Markov random process with few hacks. Once the posterior is obtained sampling should not be an issue. However, in order to scale this problem you would need proprietary algorithms that are in RxInferPro. |
Beta Was this translation helpful? Give feedback.
-
Hi @juliohm , thanks for trying out RxInfer! Let's start with the model structure, the model structure relies on the using RxInfer
n = 10
@model function markov_random_field(y, B, n)
for i in 1:n
for j in 1:n
x[i, j] ~ DiscreteTransition(y[i, j], diageye(3)) # Identity likelihood, can always be changed
end
end
for i in 1:n
for j in 1:n
# Handle edges and corners
if i == 1 && j == 1 # Top-left corner
x[i, j] ~ DiscreteTransition(x[i+1, j], B[i, j], x[i, j+1], x[i+1, j+1])
elseif i == 1 && j == n # Top-right corner
x[i, j] ~ DiscreteTransition(x[i+1, j], B[i, j], x[i, j-1], x[i+1, j-1])
elseif i == n && j == 1 # Bottom-left corner
x[i, j] ~ DiscreteTransition(x[i-1, j], B[i, j], x[i, j+1], x[i-1, j+1])
elseif i == n && j == n # Bottom-right corner
x[i, j] ~ DiscreteTransition(x[i-1, j], B[i, j], x[i, j-1], x[i-1, j-1])
elseif i == 1 # Top edge
x[i, j] ~ DiscreteTransition(x[i, j-1], B[i, j], x[i+1, j], x[i, j+1], x[i+1, j-1], x[i+1, j+1])
elseif i == n # Bottom edge
x[i, j] ~ DiscreteTransition(x[i, j-1], B[i, j], x[i-1, j], x[i, j+1], x[i-1, j-1], x[i-1, j+1])
elseif j == 1 # Left edge
x[i, j] ~ DiscreteTransition(x[i-1, j], B[i, j], x[i, j+1], x[i+1, j], x[i-1, j+1], x[i+1, j+1])
elseif j == n # Right edge
x[i, j] ~ DiscreteTransition(x[i-1, j], B[i, j], x[i, j-1], x[i+1, j], x[i-1, j-1], x[i+1, j-1])
else # Interior points
x[i, j] ~ DiscreteTransition(x[i-1, j-1], B[i, j], x[i-1, j], x[i, j-1], x[i+1, j], x[i, j+1], x[i-1, j+1], x[i+1, j-1], x[i+1, j+1])
end
end
end
end This model definition is quite big, and we can probably come up with something smarter, but I'm shooting from the hip here. The main point is that the
# Generate random transition matrices, doesn't really matter now
B = Matrix{Array{Float64}}(undef, n, n)
for i in 1:n
for j in 1:n
# Determine number of connections based on position
if i == 1 && j == 1 # Top-left corner
B[i, j] = rand(3, 3, 3, 3) # Self + right + bottom + diagonal
elseif i == 1 && j == n # Top-right corner
B[i, j] = rand(3, 3, 3, 3) # Self + left + bottom + diagonal
elseif i == n && j == 1 # Bottom-left corner
B[i, j] = rand(3, 3, 3, 3) # Self + top + right + diagonal
elseif i == n && j == n # Bottom-right corner
B[i, j] = rand(3, 3, 3, 3) # Self + top + left + diagonal
elseif i == 1 # Top edge
B[i, j] = rand(3, 3, 3, 3, 3, 3) # Self + left + right + bottom + 2 diagonals
elseif i == n # Bottom edge
B[i, j] = rand(3, 3, 3, 3, 3, 3) # Self + left + right + top + 2 diagonals
elseif j == 1 # Left edge
B[i, j] = rand(3, 3, 3, 3, 3, 3) # Self + top + bottom + right + 2 diagonals
elseif j == n # Right edge
B[i, j] = rand(3, 3, 3, 3, 3, 3) # Self + top + bottom + left + 2 diagonals
else # Interior points
B[i, j] = rand(3, 3, 3, 3, 3, 3, 3, 3, 3) # Self + 8 neighbors
end
B[i, j] ./= sum(B[i, j]) # Normalize
end
end
# Generate some data, a 50% chance of a datapoint being missing
y = Matrix{Union{Missing, Vector{Float64}}}(undef, n, n)
for i in 1:n
for j in 1:n
if rand() < 0.5
y[i, j] = zeros(3)
y[i, j][rand(1:3)] = 1
else
y[i, j] = missing
end
end
end Note that we inject Now on to the actual inference. Now that we've setup this model and data, we can do inference with just a couple of lines: initialization = @initialization begin
μ(x) = vague(Categorical, 3)
end
result = infer(model = markov_random_field(B=B, n=n), data=(y=y,), initialization=initialization, iterations=10, options = (limit_stack_depth=500,)) Which gives us a posterior probability distribution over all missing values. Then, we can use either the Gibbs sampling algorithm, or sequential sampling with message passing to obtain samples out of this MRF. Let's benchmark our solution: callbacks = RxInferBenchmarkCallbacks()
for i in 1:10
result = infer(model = markov_random_field(B=B, n=n), data=(y=y,), initialization=initialization, iterations=10, callbacks=callbacks, options = (limit_stack_depth=500,))
end Which (on my machine) gives:
I think that, when writing this model down this naively, about 99% of all computations done are entirely redundant, and I'm more than comfortable that with both a smarter model structure and a specialized inference algorithm (the DiscreteTransition is a general implementation that can definitely be made 10x faster in high-dimensional environments) this inference can be 100+ times faster. Let me know if you have any additional questions! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Suppose I have a function
p(i, j)
that returns the conditional probabilities ofk
categorical values at a grid cell(i, j)
given its 8 neighboring cells:Additionally, suppose I have observed values in
n
cells of the gridz(i1, j1), z(i2, j2), ..., z(in, jn)
. Is there an efficient method in RxInfer.jl to sample the associated Markov random processZ(i, j)
given the conditional probability function and observed values? Each sample is a full image where observed values are honored and where the conditional probability function is utilized to build the full distribution over all cells of the grid.Beta Was this translation helpful? Give feedback.
All reactions