机器学习时间序列模型:隐马尔可夫模型HMM(3)

一、HMM模型的学习问题(Baum-Welch算法)

(1) Baum-Welch算法介绍

HMM的学习算法Baum-Welch(也称为EM算法)是一种无监督学习算法,用于从观测序列中估计HMM模型的参数,包括初始概率向量、状态转移概率矩阵和观测概率矩阵。

Baum-Welch算法的主要步骤如下:

【1】初始化:随机初始化HMM模型的参数,包括初始概率向量、状态转移概率矩阵和发射概率矩阵(即观测矩阵B)。

【2】E步骤(Expectation):对于每个观测序列,使用前向-后向算法计算前向概率矩阵alpha和后向概率矩阵beta。

【3】M步骤(Maximization):利用E步骤中计算得到的前向概率矩阵alpha、后向概率矩阵beta以及观测序列,更新HMM模型的参数。

   – 更新初始概率向量pi:根据alpha和beta计算得到的gamma矩阵。

   – 更新状态转移概率矩阵A:根据alpha、beta和观测序列计算得到的xi矩阵。

   – 更新发射概率矩阵B:根据alpha、beta和观测序列计算得到的gamma矩阵。

【4】重复步骤2和3,直到收敛或达到最大迭代次数。

在E步骤中,利用前向-后向算法计算前向概率矩阵alpha和后向概率矩阵beta。前向概率alpha表示在给定模型参数和观测序列的条件下,到达每个时间步和隐藏状态的路径的概率。后向概率beta表示在给定模型参数和观测序列的条件下,从每个时间步和隐藏状态出发,到达观测序列结束的路径的概率。

在M步骤中,根据E步骤中计算得到的前向概率矩阵alpha、后向概率矩阵beta以及观测序列,利用各种计算公式更新HMM模型的参数。通过不断迭代E步骤和M步骤,逐渐优化模型参数,使得模型能够更好地解释观测序列。

Baum-Welch算法是一种经典的HMM学习算法,它利用了观测序列中的信息来估计模型参数,从而提高了HMM模型的拟合能力。然而,Baum-Welch算法可能会陷入局部最优解,并且对于有多个局部最优解的情况,无法保证找到全局最优解。因此,在实际应用中,可能需要多次运行Baum-Welch算法以选择最优的模型参数。

(2) Baum-Welch算法推导过程介绍

为了让有基础的读者进一步了解Baum-Welch算法,为了他们的学术研究乃至创新需要,笔者给大家查找了该算法推导过程的资料,以方便读者参考。

输入:给定训练数据只包含观测序列,而没有对应的状态序列

输出:学习HMM模型λ = (π, A, B)的参数

学习方法:参数的学习可以由EM算法来实现

步骤-1:确定对数似然函数

步骤-2:EM算法的E步

步骤-3:EM算法的M步

步骤4:求初始概率向量π

步骤-5:求状态转移矩阵A

步骤-6:求观测概率分布矩阵B

(3) Baum-Welch算法案例-天气预测

我们以天气预报案例为例,假设有三种天气状态:晴天(Sunny)、多云(Cloudy)和雨天(Rainy),以及两种观测结果:干燥(Dry)和湿润(Wet)。我们收集了7天的天气数据,如下所示:

天气状态:Sunny, Sunny, Cloudy, Rainy, Rainy, Cloudy, Sunny

观测结果:Dry, Wet, Wet, Dry, Wet, Wet, Dry

注释:S表示晴天,C表示多云,R表示雨天;D表示干燥,W表示湿润。

代码实现:

import numpy as np

def baum_welch(obs, n_states, n_obs):

    # 初始化参数

    start_prob = np.ones(n_states) / n_states  # 初始状态概率

    trans_prob = np.ones((n_states, n_states)) / n_states  # 状态转移概率

    obs_prob = np.ones((n_states, n_obs)) / n_obs  # 观测概率

    # 迭代次数

    n_iter = 100

    # 迭代更新模型参数

    for _ in range(n_iter):

        # E步:计算前向概率和后向概率

        alpha = np.zeros((len(obs), n_states))  # 前向概率

        beta = np.zeros((len(obs), n_states))  # 后向概率

        # 计算前向概率

        alpha[0] = start_prob * obs_prob[:, obs[0]]

        for t in range(1, len(obs)):

            alpha[t] = np.dot(alpha[t-1], trans_prob) * obs_prob[:, obs[t]]

        # 计算后向概率

        beta[-1] = 1

        for t in reversed(range(len(obs)-1)):

            beta[t] = np.dot(trans_prob, obs_prob[:, obs[t+1]] * beta[t+1])

        # M步:更新模型参数

        # 更新初始状态概率

        start_prob = alpha[0] * beta[0] / np.sum(alpha[0] * beta[0])

        # 更新状态转移概率

        for i in range(n_states):

            for j in range(n_states):

                numer = np.sum(alpha[t, i] * trans_prob[i, j] * obs_prob[j, obs[t+1]] * beta[t+1, j] for t in range(len(obs)-1))

                denom = np.sum(alpha[t, i] * beta[t, i] for t in range(len(obs)-1))

                trans_prob[i, j] = numer / denom

        # 更新观测概率矩阵

        for j in range(n_states):

            for k in range(n_obs):

                numer = np.sum(alpha[t, j] * beta[t, j] for t in range(len(obs)) if obs[t] == k)

                denom = np.sum(alpha[t, j] * beta[t, j] for t in range(len(obs)))

                obs_prob[j, k] = numer / denom

    return start_prob, trans_prob, obs_prob

# 定义天气状态和观测结果的编码

state2idx = {'S': 0, 'C': 1, 'R': 2}

obs2idx = {'D': 0, 'W': 1}

# 定义观测数据

obs = [state2idx[s] for s in ['S', 'S', 'C', 'R', 'R', 'C', 'S']]

obs = [obs2idx[o] for o in ['D', 'W', 'W', 'D', 'W', 'W', 'D']]

# 学习HMM模型参数

start_prob, trans_prob, obs_prob = baum_welch(obs, 3, 2)

# 打印结果

print(“初始状态概率:”, start_prob)

print(“状态转移概率:”, trans_prob)

print(“观测概率矩阵:”, obs_prob)

结果:

初始状态概率: [1.72987913e-08 2.86102186e-15 9.99999983e-01]

状态转移概率: [[5.49789253e-05 1.08844210e-09 9.99945021e-01]

 [4.99999985e-01 5.00000001e-01 4.99999985e-01]

 [4.99999985e-01 4.99999983e-01 5.00000002e-01]]

观测概率矩阵: [[1. 0.]

 [0. 1.]

 [0. 1.]]

初始状态概率表示开始天气状态的概率分布,状态转移概率表示天气状态之间的转移概率,观测概率矩阵表示观测结果在每个天气状态下的概率分布。根据结果可以看出,模型学习到的参数能够较好地描述观测数据的分布。

(4) Baum-Welch算法的应用场景

Baum-Welch算法是隐马尔可夫模型(HMM)参数估计的经典算法,属于无监督学习的一种方法,主要应用于需要从观测序列中学习模型参数的场景。

算法特点与适用条件:

【1】无监督学习:仅需观测序列,无需标注隐藏状态。

【2】局部最优:结果依赖初始参数,可能需多次随机初始化。

【3】时序数据:适合具有时间依赖性的序列数据。

对比其他方法:

【1】与Viterbi算法区别:Viterbi用于解码最可能的状态序列,而Baum-Welch用于参数学习。

【2】与监督学习对比:若数据已标注,可直接用最大似然估计,无需Baum-Welch。

Baum-Welch算法在数据标注成本高或隐藏状态难以直接观测的场景中尤为重要,是时序数据分析的核心工具之一。以下是其典型应用领域:

【1】语音识别

    应用:训练HMM模型以识别语音信号中的音素或单词。

    场景:从大量未标注的语音数据中自动学习声学模型的参数(如状态转移概率、观测概率)。

    示例:将语音信号分段建模为HMM的状态(如“开始-中间-结束”),通过Baum-Welch算法优化模型。

【2】 生物信息学

    DNA/RNA序列分析:预测基因编码区(如CpG岛检测);建模蛋白质二级结构或序列比对。

    示例:将DNA碱基序列作为观测值,隐藏状态可能代表不同的功能区域(如外显子、内含子)。

【3】自然语言处理(NLP)

    词性标注:将隐藏状态映射到词性标签(如名词、动词),通过观测单词序列学习状态转移规律。

    命名实体识别:识别文本中的人名、地名等实体。

【4】金融时间序列分析

    股票价格建模:将市场隐藏状态(如“牛市”“熊市”)与观测价格关联,预测趋势。

    风险检测:通过异常观测序列识别潜在金融风险。

【5】手势识别与运动分析

    动作捕捉:从传感器数据中识别人体动作(如 walking、running)。

    示例:将传感器信号作为观测值,隐藏状态对应不同动作阶段。

【6】故障诊断与预测性维护

    工业设备监测:通过振动、温度等观测数据学习设备的隐藏状态(如“正常”“故障”)。

    示例:HMM模型可预警潜在故障。

【7】气象预测

    天气模式建模:隐藏状态表示真实天气(如晴、雨),观测值可能是传感器数据或历史记录。

二、HMM模型的预测问题

(1) Viterbi算法简介

HMM主要用来预测每个时刻t在该时刻最有可能出现的状态,从而得到一个状态序列{i1,i2,…in},将它作为预测结果。下面主要介绍下维特比算法(Viterbi  Algorithm)。

维特比算法(Viterbi Algorithm)是一种常用的动态规划算法,用于解决HMM模型中的状态序列问题,即根据观测序列推断出最可能的隐藏状态序列。

维特比算法的步骤如下:

【1】初始化:设置初始概率为起始状态的概率,将路径概率初始化为1。

【2】递推:从第一个时间步开始,对于每个时间步和每个可能的隐藏状态,计算当前状态的最大路径概率和对应路径,以及当前状态的概率。

【3】回溯:找到最后一个时间步中具有最大路径概率的状态,然后根据每个时间步的最优路径回溯,得到最可能的隐藏状态序列。

维特比算法的优点是在时间复杂度上有很好的优化,因为它避免了对所有可能的状态序列进行遍历。它的计算复杂度为O(T * N^2),其中T是时间步数,N是状态数。因此,它在实际问题中可以高效地求解HMM模型的状态序列问题。

(2) Viterbi算法的主要推导步骤

下面介绍下维特比算法的主要推导过程。

输入:模型λ = (π, A, B)和观测O = {O1,O2…OT}

输出:最优路径I = { i1,i2 … iT }

(3) 使用Viterbi进行天气预测

示例:

考虑天气预报模型 λ=(π,A,B);假设每天天气受气压的因素影响,状态集合Q = {1,2,3}其中1代表高气压,2代表中气压,3代表低气压;观测集合V ={晴天,雨天},

初始状态矩阵 π = {0.5,0.3,0.2},

状态转移矩阵 A = [[0.2,0.3,0.5] ,

[0.3,0.5,0.2] ,

[0.1,0.3,0.6] ]

观测矩阵B = [ [0.3,0.7],

[0.2,0.8] ,

[0.5,0.5]]

已知观测序列 O =(晴天,雨天,晴天),试使用维特比算法(Viterbi Algorithm)求最优状体序列,即最优路径I =(i1,i2,i3)。

解:

步骤-1:t1时刻

初始化过程。在t = 1时,对于每个状态i,i=1、2、3,求状态i观测O[1]=“晴天”的概率,计算过程如下所示。

由 P1[ i ] = π[i] * b[i][o1] ,i = 1、2、3 可得:

P1[1] = π[1] * b[1][o1] = 0.5 X 0.3 = 0.15

P1[2] = π[2] * b[2][o1] = 0.3 X 0.2 = 0.06

P1[3 ] = π[3] * b[3][o1] = 0.2 X 0.5 = 0.10

t1时刻对应的每种路径表示为  path1[i] ,i = 1、2、3 ,则有:

path1[1] = path1[2] = path1[3] = 0

步骤-2:t2时刻

在t = 2时,对于每个状态i,i=1、2、3,求 {在t=1状态j观测O[1]=“晴天” &&  t=2状态i观测O[2]=“雨天”} 的路径的最大概率,计算过程如下所示。

P2[ i ] = MAX { P1[ j ] * a[ j ][ i ] } * b[i][o2]   , 其中 j >=1 &&  j<=3

【1】当为状态为1时

P2[1] = MAX { P1[1 ] * a[ 1 ][1 ] , P1[2 ] * a[ 2 ][1 ] , P1[3]*a[3][1]  } * b[1][o2]

= MAX { 0.15* 0.2 ,  0.06 *0.3,  0.10*0.1  } * 0.7

= MAX {0.03 ,  0.018,  0.01  } * 0.7

    = 0.03 * 0.7

= 0.021

因为P1[1 ] * a[ 1 ][1 ]最大,所以 从t2时刻往t1时刻看,t2时刻的状态1àt1时刻的状态1之间最大记作:

Path2[1] = 1

画出这条路径,如下所示:

【2】当为状态 为2时

P2[2] = MAX { P1[1 ] * a[ 1 ][2 ] , P1[2 ] * a[ 2 ][2 ] , P1[3]*a[3][2]  } * b[2][o2]

= MAX { 0.15* 0.3 ,  0.06 *0.5,  0.10*0.3  } * 0.8

= MAX {0.045 ,  0.03,  0.03  } * 0.8

    = 0.045 * 0.8

= 0.036

因为PP1[1 ] * a[ 1 ][2 ]最大,,所以 从t2时刻往t1时刻看,t2时刻的状态2àt1时刻的状态1之间最大记作:

Path2[2] = 1

画出这条路径,如下所示:

【3】当为状态 为3时

P2[3] = MAX { P1[1 ] * a[ 1 ][3 ] ,P1[2 ] * a[ 2 ][3 ] ,P1[3]*a[3][3]  } * b[3][o2]

= MAX { 0.15* 0.5 ,  0.06 *0.2,  0.10*0.6  } * 0.5

= MAX {0.075 ,  0.012,  0.06 } * 0.5

    = 0.075 * 0.5

= 0.0375

因为P1[1 ] * a[ 1 ][3 ]最大,所以 从t2时刻往t1时刻看,t2时刻的状态3àt1时刻的状态1之间最大记作:

Path2[3] =1

画出这条路径,如下所示:

步骤-3:t3时刻

类似t2时刻,t3时刻计算如下:

【1】当为状态为1时

P3[1] = MAX { P2[1 ] * a[ 1 ][1 ] , P2[2 ] * a[ 2 ][1 ] , P2[3]*a[3][1]  } * b[1][o1]

= MAX { 0.021* 0.2 ,  0.036 *0.3,  0.0375*0.1  } * 0.3

= MAX {0.0042 ,  0.0108,  0.00375  } * 0.3

    = 0.0108 * 0.3

= 0.00324

因为P2[2 ] * a[ 2 ][1 ]最大,所以 从t3时刻往t2时刻看,t3时刻的状态1àt2时刻的状态2之间最大记作:

Path3[1] = 2

画出这条路径,如下所示:

【2】当为状态 为2时

P2[2] = MAX { P2[1 ] * a[ 1 ][2 ] , P2[2 ] * a[ 2 ][2 ] , P2[3]*a[3][2]  } * b[2][o1]

= MAX { 0.021* 0.3 ,  0.036 *0.5,  0.0375*0.3  } * 0.2

= MAX {0.0063 ,  0.018,  0.01125  } * 0.2

    = 0.018 * 0.2

= 0.0036

因为P2[2 ] * a[ 2 ][2 ]最大,所以 从t3时刻往t2时刻看,t3时刻的状态2àt2时刻的状态2之间最大记作:

Path3[2] = 2

【3】当为状态 为3时

P3[3] = MAX { P2[1 ] * a[ 1 ][3 ] ,P2[2 ] * a[ 2 ][3 ] ,P2[3]*a[3][3]  } * b[3][o1]

= MAX { 0.021* 0.5 ,  0.036 *0.2,  0.0375*0.6  } * 0.5

= MAX {0.0105 ,  0.0072,  0.0225 } * 0.5

    = 0.0225* 0.5

= 0.01125

因为P2[2 ] * a[ 2 ][2 ]最大,所以 从t3时刻往t2时刻看,t3时刻的状态3àt2时刻的状态3之间最大记作:

Path3[3] = 3

最优路径为【1,3,3】

(4) Viterbi算法的应用场景

Viterbi算法是隐马尔可夫模型(HMM)中最经典的解码算法,用于在给定观测序列和模型参数的情况下,找到最可能的隐藏状态序列。其核心思想是动态规划,通过递推高效地求解全局最优路径(即最大后验概率路径)。

Viterbi算法的核心优势:

【1】全局最优解:保证找到概率最大的状态路径,而非贪心算法的局部最优。

【2】高效性:通过动态规划避免穷举,时间复杂度为 O(N⋅T)O(N⋅T)(NN为状态数,TT为序列长度)。

【3】时序建模:适合处理具有时间依赖性的序列数据。

对比Baum-Welch算法:

【1】Baum-Welch:用于无监督学习,从观测数据中估计HMM参数(训练阶段)。

【2】Viterbi:用于推断,在已知模型下解码最优状态序列(预测阶段)。

Viterbi算法是任何需要从观测序列反推隐藏状态序列的场景的首选工具,尤其在语音、文本、生物序列和通信领域不可或缺。其高效性和数学严谨性使其成为时序数据分析的基石算法之一。以下是其典型应用场景:

【1】语音识别

  任务:将语音信号(观测序列)转换为对应的文本或音素序列(隐藏状态序列)。

  应用:识别单词或音素(如HMM状态对应音素,观测值为MFCC特征); 结合语言模型提升识别准确率。

  示例:在“你好”的语音信号中,Viterbi算法解码出最可能的音素序列 /n/ /i/ /h/ /a/ /o/。

【2】自然语言处理(NLP)

  词性标注(POS Tagging):

        观测序列:句子中的单词序列(如“I love NLP”);

        隐藏状态:词性标签(如代词、动词、名词);

        输出:最可能的词性序列 [Pronoun, Verb, Noun]。

  命名实体识别(NER):识别文本中的人名、地名等实体。

【3】生物信息学

  基因序列分析:

        预测DNA中的编码区(如外显子/内含子)。

        隐藏状态:基因功能区域;观测值:碱基(A/T/C/G)。
  
 蛋白质结构预测:从氨基酸序列推断二级结构(α螺旋、β折叠等)。

【4】通信与错误校正

  卷积码解码:

        在数字通信中,Viterbi算法用于解码信道编码(如卷积码)的传输序列。

        观测序列:接收到的含噪声信号。

        隐藏状态:编码器的可能状态。

  示例:卫星通信、Wi-Fi信号解码。

【5】金融时间序列分析

  市场状态识别:

        隐藏状态:市场 regime(如“牛市”“熊市”“震荡”)。

        观测序列:股价或收益率数据。

        输出:推断历史市场状态的切换路径。

【6】计算机视觉与手势识别

  动作识别:

        从视频帧序列(观测值)推断人体动作(如“挥手”“走路”)。

  手写识别:将笔画轨迹转换为字符序列。

【7】故障诊断

  工业设备监测:

        观测序列:传感器数据(振动、温度等)。

        隐藏状态:设备健康状态(正常、磨损、故障)。

        输出:故障发生的可能时间点。

【8】气象预测

  天气状态推断:

        隐藏状态:实际天气(晴、雨、雪)。

        观测序列:气象站数据或卫星云图。

        示例:根据历史数据推测过去一周的真实天气序列。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容