第八周作业报告

来源:互联网 发布:淘宝店铺无线端网址 编辑:程序博客网 时间:2024/06/08 14:35

马尔科夫链模型

介绍


马尔科夫模型是一个用于预测的统计模型,在人口,股票等问题上有很多应用。
马尔科夫过程是一个离散随机过程,在这个过程中,过去的信息对于预测将来是无关的。即只与当前状态有关。(一阶模型,也有N阶马尔科夫模型,表示当前状态仅与之前的N个状态有关,跟再前面的无关。)
时间和状态都是离散的马尔科夫过程,称为马尔科夫链,记为:这里写图片描述
这样,我们根据上面介绍的,可以得出:马尔科夫性质

对于有N个状态的一阶马尔科夫模型,每个状态可以转移到另一个状态(包括自己),则共有N^2次状态转移,可以用状态转移矩阵表示。

Pij = P(Xn + 1 = i | Xn = j),其中Pij表示系统在时刻t处于状态j,在下一时刻t+l处于状态i的概率。


例如:一段文字中名词、动词、形容词出现的情况可以用有3个状态的y一阶马尔科夫模型M表示。状态s1:名词,状态s2:动词,状态s3:形容词。已知状态转移矩阵A,则状态序列O=“名动形名”
马尔科夫过程定义了以下三个部分:状态,初始向量,状态转移矩阵。

隐形马尔科夫模型


隐形马尔科夫模型(HMM)是一个用来描述含有隐含未知参数的马尔可夫过程的统计模型。其难点是从可观察的参数中确定该过程的隐含参数。然后利用这些参数来作进一步的分析。

隐性马尔科夫模型由初始概率分布,状态转移概率分布以及观测概率分布确定。

隐性马尔科夫模型作了两个基本假设
1 齐次马尔科夫假设,即假设因此的马尔科夫链在任意时刻t的状态只依赖于其前一时刻的状态,与其他时刻的状态以及观测无关。
2 观测独立性假设,即假设任意时刻的观测只依赖于该时刻的马尔科夫链的状态,与其他观测以及状态无关。

HMM是马尔科夫链中的一种,只是它的状态不能直接被观察到,但是可以通过观察向量间接的反映出来,即每一个观察向量由一个具有相应概率密度分布的状态序列产生,又由于每一个状态也是随机分布的,所以HMM是一个双重随机过程。


某地只有两种天气:雨天和晴天。某人只做3件事:散步,购物,打扫卫生。
做什么事,跟天气很有关系。
你知道这个地区的总的天气趋势,并且平时知道某人会做的事情。就是说这个隐马尔可夫模型的参数是已知的.

    states = Rainy,Sunny     observations =walk, shop, clean     start_probability =Rainy: 0.6, Sunny: 0.4     transition_probability = {          Rainy: {Rainy: 0.7, Sunny: 0.3},          Sunny : {Rainy: 0.4, Sunny: 0.6},      }<br>     emission_probability = {          Rainy : {walk: 0.1, shop: 0.4, clean: 0.5},          Sunny : {walk: 0.6, shop: 0.3, clean: 0.1},      }

可以观察到的状态序列和隐藏的状态序列是概率相关的。隐藏的状态和可观察到的状态之间有一种概率上的关系,也就是说某种隐藏状态 H 被认为是某个可以观察的状态 O1 是有概率的,假设为 P(O1 | H)。如果可以观察的状态有3种,那么很显然 P(O1 | H)+P(O2 | H)+ P(O3 | H) = 1。
HMM是语音识别,人体行为识别,文字识别等领域应用非常广泛。

HMM的3个基本问题
1 概率计算问题:根据模型计算制定序列O出现的概率。
2 学习问题:根据已知观测序列,估计模型的参数,使得在该模型观测序列概率最大。
3 预测问题:根据给定观测序列,求最有可能的对应的状态序列。
之前在交大做的情感计算就是上面第3个问题。


已知模型参数,计算某一特定输出序列的概率.通常使用forward算法解决.
已知模型参数,寻找最可能的能产生某一特定输出序列的隐含状态的序列.通常使用Viterbi算法解决.
已知输出序列,寻找最可能的状态转移以及输出概率.通常使用Baum-Welch算法以及Reversed Viterbi算法解决.

预测算法
1 近似算法:在每个t时刻,选择最有可能出现的状态i,从而得到一个状态序列,将它作为预测的结果。
这样做的缺点就是不能保证序列整体是最有可能的状态序列。

2 维特比算法:实际上是动态规划来解决预测模型。
根据动态规划原理,最优路径具有这样的特性:若是最优路径在时刻t通过节点i(t),那么这一路径从节点i(t)到终点i(T)的部分路径,对于所有节点i(t)到终点i(T)的路径必须是最优的。
从终点i(T)开始,由后向前逐步求得节点,得到最优路径。这就是维特比算法。

算法实践,实现单词联想

思路

  1. 对于给定训练文本,用分词器将每句话分为一个列表W={w1,w2,.........wn}
  2. 对于连续的两个wi以及wi+1,将前一个wi作为字典的key,字典的value作为一个list(因为要存储一定数量的后续word)
  3. 对于联想,随机产生前缀单词,然后在字典中查找该单词的value(这里为list),然后随机产生一个序号作为后一个词语或文字。

    ps:这里想法很简单,并没有去统计频率。可以从以下方面去改进:

    • 对于每句话的文字列表,将前一个词语wi与后一个词语wi+1写成w_i w_i+1 1,处理完之后再来统计w_i w_i+1的频率(类似于mapreduce
    • 考虑P(wn|wn+1)

实现及运行

参考https://www.shiyanlou.com/courses/678/labs/2204/document

训练文本: 最近的新闻
运行结果:

这里写图片描述

Viterbi算法

前面简单介绍了一下该算法,这里就不多赘述了。

输入

  • 观测空间O={o1,o2.....,on}
  • 状态序列S={S1,S2.....,Sk}
  • 初始状态Π={π1,π2.....,πk}
  • 观察序列Y={y1,y2.....,yT}
  • 状态转移矩阵A (K*K),Aij存储状态从sisj的概率
  • 矩阵B,存储观察的概率从Si到Oj。

输出

  • 最可能的隐藏状态X={x1,x2,.......,xN}

示例

参考https://en.wikipedia.org/wiki/Viterbi_algorithm
由于wiki中已经用Python实现了该算法,下面用java试着去实现以下

1.输入数据

//观测状态int [] obs = new int[]{Feel.Normal.ordinal(),        Feel.Cold.ordinal(),        Feel.Dizzy.ordinal()};//隐藏的状态int [] states = new int[]{BodyState.Healthy.ordinal(),        BodyState.Fever.ordinal()};//初始概率double[] start_p = new double[]{0.6,0.4};//状态转换矩阵double[][] trans_p = {{0.7,0.3},{0.4,0.6}};//每种状态对应的各种观测概率double[][] emit_p = {{0.5,0.4,0.1},{0.1,0.3,0.6}};

2.状态转换图
这里写图片描述

3.伪代码
这里写图片描述

4.算法实现

 protected int[] getViterbiPath()  {      double[][] V = new double[obs.length][states.length];      int[][] path = new int[states.length][obs.length];      for (int y : states)      {          V[0][y] = start_p[y] * emit_p[y][obs[0]];          path[y][0] = y;      }      for (int t = 1; t < obs.length; ++t)      {          int[][] newpath = new int[states.length][obs.length];          for (int y : states)          {              double prob = -1;              int state;              for (int y0 : states)              {                  double nprob = V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]];                  if (nprob > prob)                  {                      prob = nprob;                      state = y0;                      // 记录最大概率                      V[t][y] = prob;                      // 记录路径                      System.arraycopy(path[state], 0, newpath[y], 0, t);                      newpath[y][t] = y;                  }              }          }          path = newpath;      }      double prob = -1;      int state = 0;      for (int y : states)      {          if (V[obs.length - 1][y] > prob)          {              prob = V[obs.length - 1][y];              state = y;          }      }      return path[state];  }

5.运行结果
对于给定的观察序列: normal cold dizzy
运行结果为:
这里写图片描述

参考:

隐马尔可夫模型(HMM)攻略
MangoLiu
wiki
github Viterbi java

0 0
原创粉丝点击