You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用R语言hmmTMB包对观测状态做一步超前预测?

使用hmmTMB实现HMM模型的一步超前油价预测

问题背景

基于训练好的hmmTMB隐马尔可夫模型,对测试集的油价进行一步超前预测,核心是利用模型的状态转移规律和观测分布参数,结合滤波后的状态概率生成预测值。

完整代码示例(含预测部分)

# Load necessary libraries
library(hmmTMB)
library(tidyverse)

# Set seed for reproducibility
set.seed(123)

# Example dataset preparation (extended for 1 year)
df <- data.frame(
    day = seq.Date(from = as.Date("2020-01-01"), to = as.Date("2020-12-31"), by = "day"),
    OILPRICE = rnorm(366, 100, 10)
    ) %>%
    as_tibble()

# Splitting into training and test sets
split_index <- round(nrow(df) * 0.8)
training_set <- df[1:split_index, ] %>% as.data.frame()
testing_set <- df[(split_index + 1):nrow(df), ] %>% as.data.frame()

# Define a hidden Markov model with 2 states for the training set
hid1 <- MarkovChain$new(data = training_set, n_states = 2)
dists <- list(OILPRICE = "norm")
par0 <- list(OILPRICE = list(mean = c(110, 90), sd = c(1, 1)))
obs1 <- Observation$new(data = training_set, n_states = 2, dists = dists, par = par0)
par0 <- obs1$suggest_initial()
obs1 <- Observation$new(data = training_set, n_states = 2, dists = dists, par = par0)
hmm1 <- HMM$new(obs = obs1, hid = hid1)
hmm1$fit(silent = TRUE)

# Rename and prepare visualization data
data_plot <- training_set
pal <- c("#1f77b4", "#ff7f0e") # 定义状态颜色
data_plot$state <- factor(paste0("State ", hmm1$viterbi()))

# Plot training data with Viterbi states
ggplot(data_plot, aes(day, OILPRICE, col = state)) +
    geom_point() +
    scale_color_manual(values = pal, name = NULL) +
    theme_minimal()

# --------------------------
# 方法1:手动计算一步超前预测
# --------------------------
# 获取训练好的模型参数
trans_mat <- hmm1$hid$par$transition # 状态转移矩阵
obs_params <- hmm1$obs$par$OILPRICE # 观测分布的均值和标准差
mean_vec <- obs_params$mean
sd_vec <- obs_params$sd

# 获取训练集最后时刻的滤波状态概率(作为预测的初始状态)
train_filter <- hmm1$filter()
initial_state_probs <- train_filter$alpha[nrow(train_filter$alpha), ]

# 初始化存储变量
testing_set$predicted_price_manual <- NA
current_state_probs <- initial_state_probs

# 逐步计算预测值
for (i in 1:nrow(testing_set)) {
  # 预测下一时刻的状态概率
  next_state_probs <- current_state_probs %*% trans_mat
  # 计算油价预测值(基于状态概率的加权期望)
  predicted_val <- sum(next_state_probs * mean_vec)
  testing_set$predicted_price_manual[i] <- predicted_val
  
  # 更新状态概率:用当前观测值滤波
  obs_probs <- dnorm(testing_set$OILPRICE[i], mean = mean_vec, sd = sd_vec)
  updated_probs <- next_state_probs * obs_probs
  current_state_probs <- updated_probs / sum(updated_probs)
}

# --------------------------
# 方法2:使用hmmTMB内置predict函数
# --------------------------
# 合并训练与测试数据,让模型从训练数据结尾开始预测
full_data <- rbind(training_set, testing_set)
# 生成一步超前预测
predictions <- predict(hmm1, newdata = full_data, type = "response", one_step_ahead = TRUE)
# 提取测试集对应的预测值
testing_set$predicted_price_auto <- predictions$OILPRICE[(split_index + 1):nrow(full_data)]

# --------------------------
# 可视化预测结果
# --------------------------
ggplot(testing_set, aes(x = day)) +
  geom_point(aes(y = OILPRICE, color = "实际油价"), size = 2) +
  geom_point(aes(y = predicted_price_manual, color = "手动预测"), size = 2, shape = 17) +
  geom_point(aes(y = predicted_price_auto, color = "内置函数预测"), size = 2, shape = 15) +
  scale_color_manual(values = c("实际油价" = "black", "手动预测" = "#ff7f0e", "内置函数预测" = "#1f77b4")) +
  labs(title = "油价一步超前预测对比", x = "日期", y = "油价", color = NULL) +
  theme_minimal()

关键说明

  • 手动计算逻辑:先通过训练集最后一步的滤波状态概率,结合转移矩阵得到下一状态概率,再用状态概率加权观测分布的均值得到预测值,之后用当前观测值更新状态概率,循环处理整个测试集。
  • 内置函数预测:predict方法的one_step_ahead=TRUE参数会生成每个时间步的一步超前预测,需要将训练集和测试集合并,确保模型从训练数据的状态延续过来。

内容的提问来源于stack exchange,提问作者witek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 21:20:27