HMM终极版

本文详细介绍了隐马尔科夫模型(HMM)的基本概念及其在语音识别等领域的应用。通过实例讲解了一阶马尔科夫过程,解释了状态转移矩阵、混淆矩阵的概念,并探讨了评估、解码和学习三个核心问题。


HMM 隐马尔科夫模型。这里面有一个马尔科夫过程,一个马尔科夫过程是状态间的转移仅依赖于前n 个状态的过程。这个过程被称之为n 阶马尔科夫模型,其中n 是影响下一个状态选择的(前)n 个状态。最简单 的马尔科夫过程是一阶模型,它的状态选择仅与前一个状态有关。这里要注意它与确定性系统并不相同,因为下一个状态的选择由相应的概率决定,并不是确定性的。这里的马尔科夫过程只是一个假设过程,在现实过程中很多情况都可以看做一个马尔科夫过程。

用一个例子来简单的理解一下最基本的HMM概念:

     考虑一个简单的例子,有人试图通过一片海藻推断天气——民间传说告诉我们‘湿透的’海藻意味着潮湿阴雨,而‘干燥的’海藻则意味着阳光灿烂。如果它处于一个中间状态(‘有湿气’),我们就无法确定天气如何。然而,天气的状态并没有受限于海藻的状态,所以我们可以在观察的基础上预测天气是雨天或晴天的可 能性。另一个有用的线索是前一天的天气状态(或者,至少是它的可能状态)——通过综合昨天的天气及相应观察到的海藻状态,我们有可能更好的预测今天的天气。【在这里,海藻的状态是可观测的,我们假设天气是一个马尔科夫过程,因此天气的状况只与前一天的天气相关,因此预测今天的天气我们就可以从1.昨天的天气2.观测状态海藻的状态来推断】。在这里,假设只有三种天气状态:多云;晴;雨。

下面的状态转移矩阵显示的是天气例子中可能的状态转移概率(每一行加和等于1):



用以下三个参数描述一个一阶马尔科夫过程

状态:三个状态——晴天,多云,雨天。

向量:定义系统初始化时每一个状态的概率。
状态转移矩阵:给定前一天天气情况下的当前天气概率。
任何一个可以用这种方式描述的系统都是一个马尔科夫过程。

描述这个过程我们有两个状态,观测状态(水藻的状态)和隐藏状态(天气的状态)。结合语音识别:我们听到的声音是来自于声带、喉咙大小、舌头位置以及其他一些东西的组合结果。所有这些因素相互作用产生一个单词的声音,一套语音识别系统检测的声音就是来自于个人发音时身体内部物理变化所引起的不断改变的声音。一些语音识别装置工作的原理是将内部的语音产出看作是隐藏的状态,而将声音结果作为一系列观察的状态,这些由语音过程生成并且最好的近似了实际(隐 藏)的状态【所以说在kaldi中一个音素由三个状态描述,这三个状态并没有什么实际的物理意义,是一个隐藏的状态】。在这两个例子中,需要着重指出的是,隐藏状态的数目与观察状态的数目可以是不同的。一个包含三个状态的天气系统(晴天、多云、雨天)中,可以观察到4 个等级的海藻湿润情况(干、稍干、潮湿、湿润);纯粹的语音可以由80 个音素描述,而身体的发音系统会产生出不同数目的声音,或者比80 多,或者比80 少。

      在这种情况下,观察到的状态序列与隐藏过程有一定的概率关系。我们使用隐马尔科夫模型对这样的过程建模,这个模型包含了一个底层隐藏的随时间改变的马尔科夫过程,以及一个与隐藏状态某种程度相关的可观察到的状态集合。

隐马尔科夫模型

为了定义一个隐马尔科夫模型,我们用以下几个参数:

隐藏状态:一个系统的(真实)状态,可以由一个马尔科夫过程进行描述(例如,天气)。
* 观察状态:在这个过程中‘可视’的状态(例如,海藻的湿度)。
* 向量:包含了(隐)模型在时间t=1 时一个特殊的隐藏状态的概率(初始概率)。
* 状态转移矩阵:包含了一个隐藏状态到另一个隐藏状态的概率
* 混淆矩阵:包含了给定隐马尔科夫模型的某一个特殊的隐藏状态,观察到的某个观察状态的概率。


1.定义。

一个隐马尔科夫模型是一个三元组( π, A, B)。
π=(πi):初始化概率向量;
A=(aij):状态转移矩阵;
B = (bij):混淆矩阵
2.应用

既然定义隐马尔科夫模型,我们需要知道怎么应用。

一旦一个系统可以作为HMM 被描述,就可以用来解决三个基本问题。其中前两个是模式识别问题:给定HMM 求一个观察序列的概率(评估);搜索最有可能生成一个观察序列的隐藏状态训练(解码)。第三个问题是给定观察序列生成一个HMM(学习)。

(a)评估

考虑这样的问题,我们有一些描述不同系统的隐马尔科夫模型(也就是一些( π,A,B)三元组的集合)及一个观察序列。我们想知道哪一个HMM 最有可能产生了这个给定的观察序列。例如,对于海藻来说,我们也许会有一个“夏季”模型和一个“冬季”模型,因为不同季节之间的情况是不同的——我们也许想根据海藻湿度的观察序列来确定当前的季节。
我们使用前向算法(forward algorithm)来计算给定隐马尔科夫模型。(HMM)后的一个观察序列的概率,并因此选择最合适的隐马尔科夫模型(HMM)。

在语音识别中这种类型的问题发生在当一大堆数目的马尔科夫模型被使用,并且每一个模型都对一个特殊的单词进行建模时。一个观察序列从一个发音单词中形成,并且通过寻找对于此观察序列最有可能的隐马尔科夫模型(HMM)识别这个单词。【这句话的意思就是在训练过程中,我们会对每一个音素进行HMM建模,每一个HMM都对应一个编号,所以说在识别的过程中,我们通过这样一个过程去找到音素所对应的HMM,那么我们也就能得到这样一个特征对应的HMM那么就能得到他所对应的音素】

b) 解码(Decoding)
给定观察序列搜索最可能的隐藏状态序列另一个相关问题,也是最感兴趣的一个,就是搜索生成输出序列的隐藏状态序列。在许多情况下我们对于模型中的隐藏状态更感兴趣,因为它们代表了一些更有价值的东西,而这些东西通常不能直接观察到。考虑海藻和天气这个例子,一个盲人隐士只能感觉到海藻的状态,但是他更想知道天气的情况,天气状态在这里就是隐藏状态。我们使用Viterbi 算法(Viterbi algorithm)确定(搜索)已知观察序列及HMM下最可能的隐藏状态序列。iterbi 算法(Viterbi algorithm)的另一广泛应用是自然语言处理中的词性标注。在词性标注中,句子中的单词是观察状态,词性(语法类别)是隐藏状态(注意对于许多单词,如wind,fish 拥有不止一个词性)。对于每句话中的单词,通过搜索其最可能的隐藏状态,我们就可以在给定的上下文中找到每个单词最可能的词性标注。

c)学习(Learning)
根据观察序列生成隐马尔科夫模型。第三个问题,也是与HMM 相关的问题中最难的,根据一个观察序列(来自于已知的集合),以及与其有关的一个隐藏状态集,估计一个最合适的隐马尔科夫模型(HMM),也就是确定对已知序列描述的最合适的(π ,A,B)三元组。当矩阵A和B不能够直接被(估计)测量时,前向-后向算法(forward-backwardalgorithm)被用来进行学习(参数估计),这也是实际应用中常见的情况。



# ============================================================================== # 终极兼容版:上证指数HMM分析(适配HiddenMarkov所有版本,包括最旧版) # 核心:放弃dthmm,直接使用initHMM+baumWelch+viterbi基础函数 # ============================================================================== # 1. 安装加载包(强制安装稳定版) install.packages("HiddenMarkov", version = "1.8", dependencies = TRUE) install.packages(c("dplyr", "ggplot2", "lubridate", "gridExtra", "moments", "zoo")) # 加载包 library(dplyr) library(ggplot2) library(lubridate) library(gridExtra) library(moments) library(zoo) library(HiddenMarkov) # 2. 数据读取与预处理 sz_data <- read.csv("C:/Users/DELL/Desktop/概率模型论文 马尔科夫/sj.csv", stringsAsFactors = FALSE, fileEncoding = "UTF-8") # 计算对数收益率(确保存在) if (!"Log_Return" %in% colnames(sz_data)) { sz_data <- sz_data %>% arrange(Trddt) %>% mutate(Log_Return = log(Clsindex / lag(Clsindex))) } # 数据清洗 sz_data <- sz_data %>% mutate(Trddt = as.Date(Trddt, format = "%Y/%m/%d")) %>% arrange(Trddt) %>% filter(!is.na(Log_Return)) # 核心变量(离散化处理,适配基础版HMM) returns_pct <- sz_data$Log_Return * 100 # 收益率离散化(解决连续型分布兼容问题) returns_discrete <- cut(returns_pct, breaks = c(-Inf, -0.5, 0.5, Inf), labels = c("下跌", "波动", "上涨")) n_obs <- length(returns_discrete) cat("有效观测数:", n_obs, "\n") # 3. 描述性统计 desc_stats <- sz_data %>% summarise( 总观测数 = n(), 日期范围 = paste(min(Trddt), "至", max(Trddt)), 收盘价均值 = round(mean(Clsindex), 2), 日收益率均值_百分比 = round(mean(Log_Return)*100, 4), 日收益率标准差_百分比 = round(sd(Log_Return)*100, 4), 年化收益率_百分比 = round(mean(Log_Return)*252*100, 4), 年化波动率_百分比 = round(sd(Log_Return)*sqrt(252)*100, 4) ) cat("=== 描述性统计 ===\n") print(desc_stats) # 4. HMM模型构建(完全兼容所有版本的基础方法) set.seed(1234) n_states <- 3 # 三状态 # 4.1 初始化HMM(基础函数,无参数兼容问题) # 定义隐藏状态和观测符号 hidden_states <- c("State1_波动", "State2_下跌", "State3_上涨") observation_symbols <- c("下跌", "波动", "上涨") # 初始化HMM(核心:使用initHMM,兼容所有版本) hmm_init <- initHMM( States = hidden_states, Symbols = observation_symbols, # 初始状态概率(均匀分布) startProbs = rep(1/n_states, n_states), # 初始转移矩阵 transProbs = matrix( c(0.9, 0.05, 0.05, 0.1, 0.85, 0.05, 0.1, 0.05, 0.85), nrow = n_states, byrow = TRUE, dimnames = list(hidden_states, hidden_states) ), # 初始发射概率 emissionProbs = matrix( c(0.1, 0.8, 0.1, # 波动状态→观测下跌/波动/上涨 0.8, 0.15, 0.05, # 下跌状态→观测下跌/波动/上涨 0.05, 0.15, 0.8), # 上涨状态→观测下跌/波动/上涨 nrow = n_states, byrow = TRUE, dimnames = list(hidden_states, observation_symbols) ) ) # 4.2 Baum-Welch算法训练模型(核心兼容) cat("\n=== 模型训练(Baum-Welch)===\n") bw_result <- baumWelch( hmm = hmm_init, observation = returns_discrete, maxIter = 200, # 迭代次数 delta = 1e-3 # 收敛阈值 ) # 输出训练后的参数 cat("1. 初始状态概率:\n") print(round(bw_result$hmm$startProbs, 4)) cat("\n2. 状态转移矩阵:\n") trans_matrix_final <- bw_result$hmm$transProbs rownames(trans_matrix_final) <- colnames(trans_matrix_final) <- c("波动状态", "下跌状态", "上涨状态") print(round(trans_matrix_final, 4)) cat("\n3. 发射概率矩阵:\n") emission_matrix_final <- bw_result$hmm$emissionProbs rownames(emission_matrix_final) <- c("波动状态", "下跌状态", "上涨状态") print(round(emission_matrix_final, 4)) # 4.3 Viterbi算法识别隐藏状态(核心兼容) cat("\n=== 状态识别(Viterbi)===\n") viterbi_states <- viterbi( hmm = bw_result$hmm, observation = returns_discrete ) # 状态标签映射 state_mapping <- c( "State1_波动" = "波动状态", "State2_下跌" = "下跌状态", "State3_上涨" = "上涨状态" ) sz_data <- sz_data %>% mutate( hmm_state_raw = viterbi_states, hmm_state = recode(hmm_state_raw, !!!state_mapping), obs_state = returns_discrete ) # 5. 状态统计分析 state_summary <- sz_data %>% group_by(hmm_state) %>% summarise( 天数 = n(), 占比_百分比 = round(n()/nrow(sz_data)*100, 2), 平均收益率_百分比 = round(mean(Log_Return)*100, 4), 收益率标准差_百分比 = round(sd(Log_Return)*100, 4), 胜率_百分比 = round(sum(Log_Return>0)/n()*100, 2) ) cat("=== 状态统计特征 ===\n") print(state_summary) # 6. 可视化(极简版,确保运行) # 6.1 收盘价+状态图 p1 <- ggplot(sz_data, aes(x = Trddt, y = Clsindex)) + geom_line(color = "black", linewidth = 1) + geom_point(aes(color = hmm_state), alpha = 0.7, size = 1) + scale_color_manual(values = c("波动状态" = "blue", "下跌状态" = "red", "上涨状态" = "orange")) + labs(title = "上证指数收盘价与HMM状态", x = "日期", y = "收盘价", color = "市场状态") + theme_bw() + theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold")) # 6.2 状态占比柱状图 p2 <- ggplot(state_summary, aes(x = hmm_state, y = 天数, fill = hmm_state)) + geom_bar(stat = "identity", alpha = 0.8) + geom_text(aes(label = paste0(占比_百分比, "%")), vjust = -0.3, size = 4) + scale_fill_manual(values = c("波动状态" = "blue", "下跌状态" = "red", "上涨状态" = "orange")) + labs(title = "各市场状态天数占比", x = "市场状态", y = "天数", fill = "市场状态") + theme_bw() + theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold")) # 6.3 收益率分布(按状态) p3 <- ggplot(sz_data, aes(x = Log_Return*100, fill = hmm_state)) + geom_histogram(bins = 30, alpha = 0.6, position = "dodge") + scale_fill_manual(values = c("波动状态" = "blue", "下跌状态" = "red", "上涨状态" = "orange")) + labs(title = "各状态收益率分布", x = "收益率(%)", y = "频次", fill = "市场状态") + theme_bw() + theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold")) # 6.4 状态转移矩阵热力图 trans_df <- as.data.frame(trans_matrix_final) trans_df$从状态 <- rownames(trans_df) trans_long <- tidyr::pivot_longer(trans_df, cols = -从状态, names_to = "到状态", values_to = "概率") p4 <- ggplot(trans_long, aes(x = 到状态, y = 从状态, fill = 概率)) + geom_tile(color = "white") + geom_text(aes(label = round(概率, 4)), size = 4) + scale_fill_gradient(low = "white", high = "blue") + labs(title = "状态转移概率矩阵", x = "转移到状态", y = "从状态转移") + theme_bw() + theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold")) # 组合图表并保存 grid.arrange(p1, p2, p3, p4, ncol = 2, nrow = 2) ggsave("sz_index_hmm_ultimate.png", width = 16, height = 12, dpi = 300, bg = "white") # 7. 结果保存 result_data <- sz_data %>% select(Trddt, Clsindex, Log_Return, hmm_state, obs_state) %>% rename( 日期 = Trddt, 收盘价 = Clsindex, 对数收益率 = Log_Return, HMM识别状态 = hmm_state, 观测状态 = obs_state ) write.csv(result_data, "sz_index_hmm_final_results.csv", row.names = FALSE, fileEncoding = "UTF-8") # 保存模型 save(bw_result, file = "sz_hmm_final_model.RData") cat("\n=== 分析完成 ===\n") cat("生成文件:\n") cat("1. sz_index_hmm_ultimate.png - 可视化结果\n") cat("2. sz_index_hmm_final_results.csv - 状态数据\n") cat("3. sz_hmm_final_model.RData - 模型对象\n") 代码报错
12-18
【激光质量检测】利用丝杆与步进电机的组合装置带动光源的移动,完成对光源使用切片法测量其光束质量的目的研究(Matlab代码实现)内容概要:本文研究了利用丝杆与步进电机的组合装置带动光源移动,结合切片法实现对激光光源光束质量的精确测量方法,并提供了基于Matlab的代码实现方案。该系统通过机械装置精确控制光源位置,采集不同截面的光强分布数据,进而分析光束的聚焦特性、发散角、光斑尺寸等关键质量参数,适用于高精度光学检测场景。研究重点在于硬件控制与图像处理算法的协同设计,实现了自动化、高重复性的光束质量评估流程。; 适合人群:具备一定光学基础知识和Matlab编程能力的科研人员或工程技术人员,尤其适合从事激光应用、光电检测、精密仪器开发等相关领域的研究生及研发工程师。; 使用场景及目标:①实现对连续或脉冲激光器输出光束的质量评估;②为激光加工、医疗激光、通信激光等应用场景提供可靠的光束分析手段;③通过Matlab仿真与实际控制对接,验证切片法测量方案的有效性与精度。; 阅读建议:建议读者结合机械控制原理与光学测量理论同步理解文档内容,重点关注步进电机控制逻辑与切片数据处理算法的衔接部分,实际应用时需校准装置并优化采样间距以提高测量精度。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值