自然语言处理——隐马尔可夫模型

序列标注问题

给定一个序列x1x2x3....xn,列出序列中每个元素对应的标签y1y2y3.....yn问题。

应用场景:中文分词,词性标注,命名实体识别

中文分词:{B,M,E,S}:将一句话的每个字打上一个标签,B代表词首,M代表词中, E代表词尾,S代表单字

词性标注:给每个词语标注一个词性,比如:小明打篮球,小明代表名词,打是动词,篮球是物品名。需要考虑前后词的词性决定当前词性的关系。这个时候就需要用到概率模型去预测。

命名实体识别:现实中存在的实体名,比如人名、地名和机构名。同样可以使用打标签的思路。B代表词首,E代表词尾,O代表不构成命名实体的单词。

HMM(Hidden Markov Model 隐马尔科夫模型)

隐马尔科夫为何叫“隐”,因为预测的序列我们看不见,比如我们要猜测一句话的每个单词的词性。

它是基于马尔科夫假设:

1.每一个yi仅仅依赖于前一个状态yi-1。

2.任意时刻xi只依赖于yi,这就好比小明打篮球,这句话,'打'字出现取决于前面的“小明”是什么词性。

HMM模拟时序序列的发生过程:

1.初始状态概率向量:

y1的取值分布,比如,中文分词问题采用{B,M,E,S}标注集时,y1=B、M、E、S的概率

2.状态转移概率矩阵:

yt转移yt+1,假设t时与t+1时都有N种状态,则从状态yt到yt+1的概率就构成了N×N的方阵

比如,中文分词中,如果一个字被打上标签B,则说明他是一个词语的开头,故其后面不可能是S,则矩阵该位置的元素为0。

或者像“副词”后接“动词”的规律可以由状态转移概率来表示。

3.发射概率矩阵:

假设x有M种取值,由于y有N种,根据前面的马尔科夫假设2,我们又可以得到一个N×M的矩阵。

比如在词语“现象”,赋予p(x1='象'|y1=B)较低的概率,防止“现象”被分开。

案例分析

自定义身体状态(发病、健康)与身体感受(头晕、体寒、正常)事件之间发生的概率,通过隐马尔科夫模型为病人N天的身体感受的序列,预测这个N天身体状态。

/**生成样本序列**/
public int[][] generate(int length)
{
  int xy[][]=new int[2][length]; //一个二维数组 2×N
  xy[1][0]=drawFrom(pi); //为y0 赋一个 初始值
  xy[0][0]=drawFrom(B[xy[1][0]]);  //由y0经过发射概率矩阵生成x0
  for (int t=1;t<length;t++)
 {
   xy[1][t]=drawFrom(A[xy[1][t-1]]);//生成yt
   xy[0][t]=drawFrom(B[xy[1][t]]);//生成xt
 }
 return xy      
}

结果

cold/Healthy normal/Healthy dizzy/fever dizzy/Fever

训练HMM模型

前面的例子相当于,三个矩阵已经有了。我们可以反过来分析:如果我们有这样一批标注的训练数据,采用监督学习,就可以估计出这个三个矩阵。

一:转移概率矩阵的估计:

我们自己有一堆样本,我们此时需要统计状态yt到yt+1的概率。我们就可以统计这样的转移频次,然后矩阵的第i行做一个概率的归一化。

二:初始状态概率向量的估计

与一类似。统计y1所有取值的频次

三:发射概率矩阵的估计。统计样本中观测为xt,状态为yt的频次。

使用HMM预测

 给定一组观测序列,求解最可能的状态和概率。

问题转化为求观测序列x,状态序列y,p(x,y)联合概率最大的y

p(x,y)=p(y)p(x|y),将其中的值转化成三个矩阵的相应元素,就能求得任意序列的概率了。

 总结

目前市面上的开源分词器依然停留在一阶隐马尔科夫水平。

隐马尔科夫模型是一种生成式模型,因为假设过于强烈、简单,与实际情况不符。所以分词准确率不会很高。

参考网址:viterbi算法:https://www.zhihu.com/question/20136144

posted @ 2020-09-20 12:43  猫七的blog  阅读(261)  评论(0编辑  收藏  举报