如何在R中实现分类时间序列预测?含穿衣序列预测场景
分类时间序列预测:穿衣序列的解决方案
你已经用ARIMA搞定了连续值的时序预测,但分类值的时序确实不一样——ARIMA是针对数值的,没法直接用在类别序列上。针对你说的穿衣训练序列预测,我给你几个实用的R实现方案,都是适合这种有序分类序列的方法:
一、最直观的方法:马尔可夫链(一阶/高阶)
穿衣步骤是典型的有顺序依赖的序列:下一步穿什么很大程度上取决于上一步穿了什么。马尔可夫链就是靠统计这种“状态转移概率”来做预测的。
步骤1:准备数据
先把5个人的序列整理好(我补充了你截断的部分,你可以根据实际数据调整):
person1 <- c("underwear", "socks", "pants", "shirt", "tie", "shoes", "jacket") person2 <- c("underwear", "pants", "shirt", "socks", "shoes", "jacket") person3 <- c("underwear", "shirt", "pants", "socks", "tie", "shoes", "jacket") person4 <- c("underwear", "socks", "shirt", "pants", "shoes", "jacket") person5 <- c("underwear", "pants", "shirt", "tie", "shoes", "jacket") dressing_sequences <- list(person1, person2, person3, person4, person5)
步骤2:一阶马尔可夫链实现
一阶就是只看当前最后一个步骤,统计它之后最常出现的下一个步骤:
library(dplyr) # 提取所有的"当前步骤→下一个步骤"转移对 transitions <- lapply(dressing_sequences, function(seq) { data.frame( current = seq[-length(seq)], next_step = seq[-1] ) }) %>% bind_rows() # 计算每个步骤的转移概率 transition_probs <- transitions %>% group_by(current) %>% count(next_step, name = "count") %>% mutate(prob = count / sum(count)) %>% arrange(desc(prob)) # 定义预测函数:给定最后一步,返回概率最高的下一步 predict_next <- function(last_step) { probs <- transition_probs %>% filter(current == last_step) if (nrow(probs) == 0) { # 如果没见过这个步骤,返回全局最常见的后续步骤 return(transitions %>% count(next_step, sort = TRUE) %>% slice(1) %>% pull(next_step)) } probs %>% slice(1) %>% pull(next_step) } # 假设person6当前的序列是c("underwear", "socks", "pants"),预测最后两个条目 person6_current <- c("underwear", "socks", "pants") next1 <- predict_next(last(person6_current)) next2 <- predict_next(next1) cat("一阶马尔可夫预测结果:", next1, "和", next2, "\n")
步骤3:高阶马尔可夫链(更准确)
如果穿衣步骤依赖前面多个步骤(比如穿了pants+shirt之后,下一步更可能是tie),可以用二阶马尔可夫链:
# 提取"前两个步骤→下一个步骤"的转移对 second_order_trans <- lapply(dressing_sequences, function(seq) { if (length(seq) < 3) return(NULL) data.frame( prev_two = paste(seq[-c(length(seq), length(seq)-1)], seq[-c(1, length(seq))], sep = "_"), next_step = seq[-c(1,2)] ) }) %>% bind_rows() # 计算二阶转移概率 second_order_probs <- second_order_trans %>% group_by(prev_two) %>% count(next_step, name = "count") %>% mutate(prob = count / sum(count)) %>% arrange(desc(prob)) # 二阶预测函数,没找到二阶模式就退回到一阶 predict_next_2nd <- function(last_two_steps) { prev_two_str <- paste(last_two_steps[1], last_two_steps[2], sep = "_") probs <- second_order_probs %>% filter(prev_two == prev_two_str) if (nrow(probs) == 0) { return(predict_next(last_two_steps[2])) } probs %>% slice(1) %>% pull(next_step) } # 预测person6的后续步骤 person6_current <- c("underwear", "socks", "pants") last_two <- tail(person6_current, 2) next1_2nd <- predict_next_2nd(last_two) next2_2nd <- predict_next_2nd(c(last_two[2], next1_2nd)) cat("二阶马尔可夫预测结果:", next1_2nd, "和", next2_2nd, "\n")
二、专业序列分析工具:traMineR包
如果你想更系统地分析序列模式,可以用traMineR——这是专门处理状态序列(分类时序)的R包,支持基于序列相似性的预测:
# install.packages("traMineR") library(traMineR) # 转换为traMineR的序列对象 dressing_seqs <- seqdef(dressing_sequences, alphabet = c("underwear", "socks", "pants", "shirt", "tie", "shoes", "jacket")) # 假设person6的初始序列是c("underwear", "socks", "pants") person6_init <- seqdef(list(c("underwear", "socks", "pants")), alphabet = alphabet(dressing_seqs)) # 找到和person6初始序列最相似的已有序列,用它的后续步骤做预测 dist_matrix <- seqdist(dressing_seqs, person6_init, method = "LCS") # LCS是最长公共子序列距离 most_similar_idx <- which.min(dist_matrix) most_similar_seq <- dressing_sequences[[most_similar_idx]] # 提取需要的后续步骤 init_len <- length(person6_init) predicted_steps <- most_similar_seq[(init_len+1):(init_len+2)] cat("基于序列相似性的预测结果:", predicted_steps[1], "和", predicted_steps[2], "\n")
总结建议
- 如果你的序列比较短、类别不多,一阶/二阶马尔可夫链足够用,代码简单,结果也容易解释。
- 如果序列有更复杂的模式,或者你需要做更深入的序列分析,
traMineR是更好的选择。 - 如果遇到罕见的步骤组合,可以加个“平滑”逻辑(比如给每个转移加1次计数,避免概率为0),或者退回到全局频率最高的步骤。
内容的提问来源于stack exchange,提问作者mowglis_diaper
相关产品推荐
相关产品推荐

