隐含马尔可夫模型

1.模型的作用: 通过观察序列O,找到最大可能的原始序列S

 

2.大体流程图:

O=(O_{1},O_{2},...,O_{n}) 是观察序列,使我们已知的

S=(S_{1},S_{2},...,S_{n})  是隐含序列,是我们需要猜测的

 

3.理论基础

P(S|O) 对应的最大值 所对应的 S

根据贝叶斯定理  P(S|O)=\frac{P(O|S)P(S)}{P(O)}

P(O)已经生成,所有的都是相同的,所以不需要关心, 我们需要计算 分子上的两项

 

 

自然地想法:

P(S)的计算:      P(S)=P(S_{1})P(S_{2}|S_{1})P(S_{3}|S_{1}S_{2})...P(S_{n}|S_{1}S_{2}..S_{n-1})

这个计算的复杂度是巨大的

 

P(O|S) 的计算:   P(O|S)=P(O_{1}O_{2}...O_{n}|S_{1}S_{2}...S_{n})=P(O_{1}|S_{1})P(O_{2}|S_{1}S_{2}O_{1})...P(O_{n}|S_{1}S_{2}...S_{n}O_{1}O_{2}...O_{n-1})

这个计算量也很大

 

简化计算

1. 根据马尔可夫假设,当前的 S_{i} 只和 S_{i-1} 有关

  P(S)=P(S_{1}S_{2}...S_{n})=P(S_{1})P(S_{2}|S_{1})P(S_{3}|S_{2})...P(S_{n}|S_{n-1})

2. 观察独立性假设,  任意时刻的观察值仅与当前的状态值有关

  P(O|S)=P(O_{1}|S_{1})P(O_{2}|S_{2})...P(O_{n}|S_{n})

 

所以只需要计算  \prod P(O_{i}|S_{i})*P(S_{i}|S_{i-1}) 对应的最大的S 序列即可

 

 

状态转移图:

注:yi表示观测到的序列

 

 

解决上述问题的维特比算法:

 

已知条件:

观测序列 O

初始状态概率向量 \Pi

状态转移概率矩阵 A

观测概率矩阵 B

 

求最大概率对应的S

 

 

 

代码实现:

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
#define rep(i,a,b) for(int i=a;i<b;++i)

const int N=100;
struct Matrix {
	int r,c;
	double mat[N][N];

	Matrix(int _r=0,int _c=0) {
		r=_r,c=_c;
		rep(i,0,r)rep(j,0,c)mat[i][j]=0;
	}

	Matrix operator* (Matrix B) {
		Matrix ans=Matrix(r, B.c);
		for(int i=0; i<r; i++) {
			for(int j=0; j<B.c; j++) {
				ans.mat[i][j]=0;
				for(int k=0; k<c; k++) {
					ans.mat[i][j]+=mat[i][k]*B.mat[k][j];
				}
			}
		}
		return ans;
	}
	void show() {
		rep(i,0,r) {
			rep(j,0,c) {
				printf("%d ",mat[i][j]);
			}
			printf("\n");
		}
	}
};


int Obs[N]= {0,1,0};

double graph[N][N];
double mat1[N][N]= {{0.2},{0.4},{0.4}}, mat2[N][N]= {{0.5,0.2,0.3},{0.3,0.5,0.2},{0.2,0.3,0.5}}, mat3[N][N]= {{0.5,0.5},{0.4,0.6},{0.7,0.3}};

double weight[N][N];
int path[N][N];

void tracer_back(int now,int id)
{
	if(now==0){
		printf("%d ",id);
		return;
	}
	
	tracer_back(now-1,path[now][id]);
	printf("%d ",id);
}


void show(double (*grap)[100],int n,int m){
	
	rep(i,0,n) {
		rep(j,0,m) {
	     	printf("%.2f ",grap[i][j]);
			
		}
		printf("\n");
	}
}


/*
1.类型错误
2.指代错误
3.图的结构不清晰 
*/
int main()
{
	Matrix pi=Matrix(3,1);
	rep(i,0,pi.r)rep(j,0,pi.c) pi.mat[i][j]=mat1[i][j];


	Matrix A=Matrix(3,3);
	rep(i,0,A.r)rep(j,0,A.c) A.mat[i][j]=mat2[i][j];

	Matrix B=Matrix(3,2);
	rep(i,0,B.r)rep(j,0,B.c) B.mat[i][j]=mat3[i][j];


	int len=3,size=3;
	
	for(int i=0; i<size; i++) {
		graph[0][i]=pi.mat[i][0]*B.mat[i][0];
	//	printf("%.2f %.2f\n",pi.mat[i][0],B.mat[i][0]) ;
	}

	for(int i=1; i<len; i++) {
		for(int j=0; j<size; j++) {
			double tmp_max=0;
			for(int k=0; k<size; k++) {
				double tmp=graph[i-1][k]*A.mat[k][j]*B.mat[j][Obs[i]];
				if(tmp>tmp_max) {
					tmp_max=tmp;
					path[i][j]=k;
				}
			}
			graph[i][j]=tmp_max;
		}
	}

	show(graph,len,size);


	double mx=0;int id=0;
	for(int i=0;i<size;i++){
		if(graph[len-1][i]>mx){
			mx=graph[len-1][i];
			id=i;
		}
	}
	tracer_back(len-1,id);
	return 0;
}

 

 

改成分词识别,只需要将四种状态 替代上面的三种状态,然后统计 A矩阵 和 B矩阵

B(每个词的开始) M(每个词的中间位置) E(每个词的结束位置) S(单独的词是一个)

 

参考文献:

数学之美

简书: https://www.jianshu.com/p/f140c3a44ab6

博客:https://blog.csdn.net/songbinxu/article/details/80209197

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值