1.模型的作用: 通过观察序列,找到最大可能的原始序列
2.大体流程图:
是观察序列,使我们已知的
是隐含序列,是我们需要猜测的
3.理论基础
求 对应的最大值 所对应的
根据贝叶斯定理
已经生成,所有的都是相同的,所以不需要关心, 我们需要计算 分子上的两项
自然地想法:
的计算:
这个计算的复杂度是巨大的
的计算:
这个计算量也很大
简化计算
1. 根据马尔可夫假设,当前的 只和 有关
2. 观察独立性假设, 任意时刻的观察值仅与当前的状态值有关
所以只需要计算 对应的最大的 序列即可
状态转移图:
注:yi表示观测到的序列
解决上述问题的维特比算法:
已知条件:
观测序列
初始状态概率向量
状态转移概率矩阵 A
观测概率矩阵 B
求最大概率对应的
代码实现:
#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