init_fn <- function(num_particles) rnorm(num_particles, 0, 1)
transition_fn <- function(particles) particles + rnorm(length(particles))
log_likelihood_fn <- function(y, particles) {
dnorm(y, mean = particles, sd = 1, log = TRUE)
}
aux_log_likelihood_fn <- function(y, particles) {
# Predict next state (mean stays same) and compute log p(y | x)
mean_forecast <- particles # since E[x'] = x in this model
dnorm(y, mean = mean_forecast, sd = 1, log = TRUE)
}
y <- cumsum(rnorm(50)) # dummy data
num_particles <- 100
result <- auxiliary_filter(
y = y,
num_particles = num_particles,
init_fn = init_fn,
transition_fn = transition_fn,
log_likelihood_fn = log_likelihood_fn,
aux_log_likelihood_fn = aux_log_likelihood_fn
)
plot(result$state_est,
type = "l", col = "blue", main = "APF: State Estimates",
ylim = range(c(result$state_est, y))
)
points(y, col = "red", pch = 20)
# ---- With parameters ----
init_fn <- function(num_particles) rnorm(num_particles, 0, 1)
transition_fn <- function(particles, mu) {
particles + rnorm(length(particles), mean = mu)
}
log_likelihood_fn <- function(y, particles, sigma) {
dnorm(y, mean = particles, sd = sigma, log = TRUE)
}
aux_log_likelihood_fn <- function(y, particles, mu, sigma) {
# Forecast mean of x' given x, then evaluate p(y | forecast)
forecast <- particles + mu
dnorm(y, mean = forecast, sd = sigma, log = TRUE)
}
y <- cumsum(rnorm(50)) # dummy data
num_particles <- 100
result <- auxiliary_filter(
y = y,
num_particles = num_particles,
init_fn = init_fn,
transition_fn = transition_fn,
log_likelihood_fn = log_likelihood_fn,
aux_log_likelihood_fn = aux_log_likelihood_fn,
mu = 1,
sigma = 1
)
plot(result$state_est,
type = "l", col = "blue", main = "APF with Parameters",
ylim = range(c(result$state_est, y))
)
points(y, col = "red", pch = 20)
# ---- With observation gaps ----
simulate_ssm <- function(num_steps, mu, sigma) {
x <- numeric(num_steps)
y <- numeric(num_steps)
x[1] <- rnorm(1, mean = 0, sd = sigma)
y[1] <- rnorm(1, mean = x[1], sd = sigma)
for (t in 2:num_steps) {
x[t] <- mu * x[t - 1] + sin(x[t - 1]) + rnorm(1, mean = 0, sd = sigma)
y[t] <- x[t] + rnorm(1, mean = 0, sd = sigma)
}
y
}
data <- simulate_ssm(10, mu = 1, sigma = 1)
obs_times <- c(1, 2, 3, 5, 6, 7, 8, 9, 10) # Missing at t = 4
data_obs <- data[obs_times]
init_fn <- function(num_particles) rnorm(num_particles, 0, 1)
transition_fn <- function(particles, mu) {
particles + rnorm(length(particles), mean = mu)
}
log_likelihood_fn <- function(y, particles, sigma) {
dnorm(y, mean = particles, sd = sigma, log = TRUE)
}
aux_log_likelihood_fn <- function(y, particles, mu, sigma) {
forecast <- particles + mu
dnorm(y, mean = forecast, sd = sigma, log = TRUE)
}
num_particles <- 100
result <- auxiliary_filter(
y = data_obs,
num_particles = num_particles,
init_fn = init_fn,
transition_fn = transition_fn,
log_likelihood_fn = log_likelihood_fn,
aux_log_likelihood_fn = aux_log_likelihood_fn,
obs_times = obs_times,
mu = 1,
sigma = 1
)
plot(result$state_est,
type = "l", col = "blue", main = "APF with Observation Gaps",
ylim = range(c(result$state_est, data))
)
points(data_obs, col = "red", pch = 20)
Run the code above in your browser using DataLab