统计自然语言处理——n元语法(马尔可夫模型)小结

news/2024/5/19 1:49:40 标签: 自然语言处理, signal, 算法, float, system, ini
终于把书看到传说中重要的第六章了。。。

看完第六章开始后悔之前花那么多时间看前四章内容了。。看了也忘掉了。。什么困惑度啊什么的一堆概念还是要翻一翻。。之前总怕不仔细看后面的看不懂。。结果重要的第五章第六章反而看的比前面愉快了许多~主要还是概率的知识,几乎都是条件概率,条件概率公式、全概率公式和贝叶斯公式用的挺多,当然还有独立性。。下面不废话了。。具体说一下。。


【心得及问题】

1、N元语法的n体现了该词间的独立性,n越小独立性越强。则可根据不同语料的独立性特点选择不同的模型了。通常n=3。直观上讲,第i位置的词与前面多少个词的相关性并不一定,另外,“词”是一个笼统的概念(可以代表字、词短语等),它的选取也不确定,而一个模型直接赋予n一个确定的值,这本身是一种近似。所以说,模型不可能精确表达,根据这种局限性,一个好的模型的重要性就可想而知了。模型提出后也要检验,至少要满足已知定理,比如n元语法模型就加上了<BOS> 和<EOS>,以使i-1有意义并满足概率的归一性。
2、P75:刚开始没看懂计算P(Wi|Wi-1)的公式。是因为求和符号下面的Wi理解为施加给i了,思维定势,而Wi-1是不变的。其实就是条件概率公式P(A|B) = P(AB)/P(B)约掉了样本空间里元素的个数而已。
3、P77:之前看平滑方法的时候想比较一下,看看优缺点,但是一堆公式看起来很费劲。计算了一下,发现使用加法平滑算法时,概率的变大还是变小取决于(b-a|V|)的正负(a为原来概率的分子,b为原来概率的分母)。感觉词汇表的容量|V|通常应该很大,即使a比b小也有可能大多数情况该值为负,即概率变小,那么概率的归一性怎么保证?这点没有想明白。另外关于平滑还有一个问题,说平滑的基本思想是“劫富济贫”,不明白为什么。不让概率为零的实际意义书上有解释,而为什么要让概率分布均匀就不晓得了,没百度出来。。后面的平滑方法看不懂也看不下去了,想着将来用到再看,毕竟我发现纯理论的东西看了跟没看一样,知道有这么回事就行了。况且最后有人做过实验比较,具有指导意义。
4、P95:P(q1,q2,……,qt)的第二个等式刚开始感觉应该用约等。后来想想,感觉它的意思应该是基于马尔可夫模型吧,模型已经是近似了,而在该模型中就是假定该模型是准确的吧,然后与前面其他的状态无关,所以就写等号了。
5、隐马尔可夫模型不过是一个双重的随机过程,书上小球的例子举得很直观,理解没有困难,将马尔可夫模型的应用范围扩大到潜在事件随即生成表面时间的情况。
6、前向、后向(这个还要实现以下,之后附上代码。。)包括维特比算法,个人认为关键是动态规划的思想,所以总结在下面。之前连动态规划是什么都不知道。。汗颜。。这也体现了算法的重要性啊!


【思想小结】

1、动态规划:就是为了避免重复计算浪费时间,通常把计算过的量给保留起来,下次则直接查找,无需计算。就是一种空间换时间的感觉。。当然计算量要是很小就不必要这样啦。。那个维特比算法让我想起来Dijkstra的单源最短路径那个算法,有点像呢。而且都是设了一个变量来进行路径的记录。(而路径记录要是我刚开始肯定会想到链表或者数组。。效率啊。。人家一个变量就解决了,最后递归输出一个逆序就行了~)所以说,算法有很多,也有很多是相通的,算法思想才是最重要的。

2、模型思想:呵呵,刚才正好说到算法思想,模型思想也是如此,感觉这是一种抽象的能力。这世界上万事万物那么多,谁有时间和精力都去研究一遍呢,况且研究难度也很大。而模型的思想就是一种抽象思想,把一个问题抽象成一类问题,一个好的模型就能解决一系列问题了,也是一种对一系列问题的归类和总结,是透过现象看本质的能力。咦。。扯到哲学了。。言归正传,这同时也是理论与实际的完美结合。一个模型建立的时候,你不能不考虑理论因素,比如不能与公理定理等客观真理相违背(感受第一点加<EOS>就是这样)。而建立之后,又要经得起检验,不能与人的基本常识(当然是可证明的客观常识)或者实际经验和需求等相违背(比如平滑方法的提出,概率为零导致语音识别错误)。所以提出和提出之后都要经过检验和优化,提出新的方法甚至新的模型,这便是研究一个模型的价值吧。


附前向算法(注意代码风格呀!!那个*写成+让我Debug了一天啊有木有!!):

[cpp] view plain copy print ?
  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3.   
  4. int main()  
  5. {  
  6.     int i, n, j;  
  7.     int array[100]= {0};  
  8.     double result=0;  
  9.     float init[5] = {0.1,0.3,0.2,0.2,0.2};  
  10.     float state[5][5] = { {0,0.2,0.4,0.1,0.3}, {0.2,0.8,0,0,0}, {0.5,0.1,0.1,0.2,0.1}, \  
  11.         {0.2,0.3,0.1,0.3,0.1}, {0,0.1,0.2,0.4,0.3}  
  12.     };  
  13.     double forward[100][5];  
  14.     float signal[5][3] = { {0.5,0.3,0.2}, {0.1,0.1,0.8}, {0,0,1}, {0.4,0.5,0.1}, {0.7,0,0.3}};  
  15.     printf("请输入观察序列的长度:\n");  
  16.     scanf("%d", &n);  
  17.     for(i=0; i<n; i++)  
  18.     {  
  19.         printf("请输入第%d个观察到的颜色序号并按回车结束\n", i+1);  
  20.         scanf("%d", &array[i]);  
  21.         if(array[i]<1 || array[i]>3)  
  22.         {  
  23.             printf("颜色只有1、2、3!请重新输入!\n\n");  
  24.             i--;  
  25.         }  
  26.     }  
  27.     system("cls");  
  28.     printf("您输入的序列为:\n");  
  29.     for(i=0; i<n; i++)  
  30.     {  
  31.         printf("%d  ", array[i]);  
  32.     }  
  33.     for(i=0; i<5; i++)  
  34.     {  
  35.         forward[0][i] = init[i]*signal[i][array[0]-1];  
  36.         printf("forward[0][%d]: %lf  ", i, forward[0][i]);  
  37.     }  
  38.     for(i=1; i<n; i++)  
  39.     {  
  40.         for(j=0; j<5; j++)  
  41.         {  
  42.             forward[i][j] = (forward[i-1][0]*state[0][j]+forward[i-1][1]*state[1][j]+ \  
  43.                              forward[i-1][2]*state[2][j]+forward[i-1][3]*state[3][j]+ \  
  44.                              forward[i-1][4]|*state[4][j])*signal[j][array[i]-1];  
  45. //            printf("\nforward[%d][%d]: %lf\n", i, j, forward[i][j]);   
  46.         }  
  47.     }  
  48.     for(i=0; i<5; i++)  
  49.     {  
  50. //        printf("%lf  ", forward[n-1][i]);   
  51.         result += forward[n-1][i];  
  52.     }  
  53.     printf("\n该观察序列的概率为:%lf\n", result);  
  54.     return 0;  
  55. }  
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i, n, j;
    int array[100]= {0};
    double result=0;
    float init[5] = {0.1,0.3,0.2,0.2,0.2};
    float state[5][5] = { {0,0.2,0.4,0.1,0.3}, {0.2,0.8,0,0,0}, {0.5,0.1,0.1,0.2,0.1}, \
        {0.2,0.3,0.1,0.3,0.1}, {0,0.1,0.2,0.4,0.3}
    };
    double forward[100][5];
    float signal[5][3] = { {0.5,0.3,0.2}, {0.1,0.1,0.8}, {0,0,1}, {0.4,0.5,0.1}, {0.7,0,0.3}};
    printf("请输入观察序列的长度:\n");
    scanf("%d", &n);
    for(i=0; i<n; i++)
    {
        printf("请输入第%d个观察到的颜色序号并按回车结束\n", i+1);
        scanf("%d", &array[i]);
        if(array[i]<1 || array[i]>3)
        {
            printf("颜色只有1、2、3!请重新输入!\n\n");
            i--;
        }
    }
    system("cls");
    printf("您输入的序列为:\n");
    for(i=0; i<n; i++)
    {
        printf("%d  ", array[i]);
    }
    for(i=0; i<5; i++)
    {
        forward[0][i] = init[i]*signal[i][array[0]-1];
        printf("forward[0][%d]: %lf  ", i, forward[0][i]);
    }
    for(i=1; i<n; i++)
    {
        for(j=0; j<5; j++)
        {
            forward[i][j] = (forward[i-1][0]*state[0][j]+forward[i-1][1]*state[1][j]+ \
                             forward[i-1][2]*state[2][j]+forward[i-1][3]*state[3][j]+ \
                             forward[i-1][4]|*state[4][j])*signal[j][array[i]-1];
//            printf("\nforward[%d][%d]: %lf\n", i, j, forward[i][j]);
        }
    }
    for(i=0; i<5; i++)
    {
//        printf("%lf  ", forward[n-1][i]);
        result += forward[n-1][i];
    }
    printf("\n该观察序列的概率为:%lf\n", result);
    return 0;
}

后向算法(感觉书上算法第三步写错了。。害我苦思冥想到底和第一个状态有什么关系想了好久。。。):

[cpp] view plain copy print ?
  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3.   
  4. int main()  
  5. {  
  6.     int i, j, n;  
  7.     int array[100] = {0};  
  8.     double result=0;  
  9.     float init[5] = {0.1,0.3,0.2,0.2,0.2};  
  10.     float state[5][5] = { {0,0.2,0.4,0.1,0.3}, {0.2,0.8,0,0,0}, {0.5,0.1,0.1,0.2,0.1}, \  
  11.         {0.2,0.3,0.1,0.3,0.1}, {0,0.1,0.2,0.4,0.3}  
  12.     };  
  13.     double back[100][5];  
  14.     float signal[5][3] = { {0.5,0.3,0.2}, {0.1,0.1,0.8}, {0,0,1}, {0.4,0.5,0.1}, {0.7,0,0.3}};  
  15.     printf("请输入观察序列的长度:\n");  
  16.     scanf("%d", &n);  
  17.     for(i=0; i<n; i++)  
  18.     {  
  19.         printf("请输入第%d个观察到的颜色序号并按回车结束\n", i+1);  
  20.         scanf("%d", &array[i]);  
  21.         if(array[i]<1 || array[i]>3)  
  22.         {  
  23.             printf("颜色只有1、2、3!请重新输入!\n\n");  
  24.             i--;  
  25.         }  
  26.     }  
  27.     system("cls");  
  28.     printf("您输入的序列为:\n");  
  29.     for(i=0; i<n; i++)  
  30.     {  
  31.         printf("%d  ", array[i]);  
  32.     }  
  33.     for(i=0; i<5; i++)  
  34.     {  
  35.         back[n][i] = 1;  
  36.     }  
  37.     for(i=n-1; i>0; i--)  
  38.     {  
  39.         for(j=0; j<5; j++)  
  40.         {  
  41.             back[i][j] = state[j][0]*signal[0][array[i]-1]*back[i+1][0] + \  
  42.             state[j][1]*signal[1][array[i]-1]*back[i+1][1] + \  
  43.             state[j][2]*signal[2][array[i]-1]*back[i+1][2] + \  
  44.             state[j][3]*signal[3][array[i]-1]*back[i+1][3] + \  
  45.             state[j][4]*signal[4][array[i]-1]*back[i+1][4];  
  46.         }  
  47.     }  
  48.     for(i=0; i<5; i++)  
  49.     {  
  50.         result += back[1][i]*init[i]*signal[i][array[0]-1];  
  51.     }  
  52.         printf("\n该观察序列的概率为:%lf\n", result);  
  53.     return 0;  
  54. }  
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i, j, n;
    int array[100] = {0};
    double result=0;
    float init[5] = {0.1,0.3,0.2,0.2,0.2};
    float state[5][5] = { {0,0.2,0.4,0.1,0.3}, {0.2,0.8,0,0,0}, {0.5,0.1,0.1,0.2,0.1}, \
        {0.2,0.3,0.1,0.3,0.1}, {0,0.1,0.2,0.4,0.3}
    };
    double back[100][5];
    float signal[5][3] = { {0.5,0.3,0.2}, {0.1,0.1,0.8}, {0,0,1}, {0.4,0.5,0.1}, {0.7,0,0.3}};
    printf("请输入观察序列的长度:\n");
    scanf("%d", &n);
    for(i=0; i<n; i++)
    {
        printf("请输入第%d个观察到的颜色序号并按回车结束\n", i+1);
        scanf("%d", &array[i]);
        if(array[i]<1 || array[i]>3)
        {
            printf("颜色只有1、2、3!请重新输入!\n\n");
            i--;
        }
    }
    system("cls");
    printf("您输入的序列为:\n");
    for(i=0; i<n; i++)
    {
        printf("%d  ", array[i]);
    }
    for(i=0; i<5; i++)
    {
        back[n][i] = 1;
    }
    for(i=n-1; i>0; i--)
    {
        for(j=0; j<5; j++)
        {
            back[i][j] = state[j][0]*signal[0][array[i]-1]*back[i+1][0] + \
            state[j][1]*signal[1][array[i]-1]*back[i+1][1] + \
            state[j][2]*signal[2][array[i]-1]*back[i+1][2] + \
            state[j][3]*signal[3][array[i]-1]*back[i+1][3] + \
            state[j][4]*signal[4][array[i]-1]*back[i+1][4];
        }
    }
    for(i=0; i<5; i++)
    {
        result += back[1][i]*init[i]*signal[i][array[0]-1];
    }
        printf("\n该观察序列的概率为:%lf\n", result);
    return 0;
}



http://www.niftyadmin.cn/n/1534724.html

相关文章

筛素数

// 1&#xff1a;这是最原始的筛法&#xff0c;还有待优化 #define Max 1000000 bool prime[Max]; void IsPrime(){ prime[0]prime[1]0;prime[2]1; for(int i3;i<max;i) prime[i]i%20?0:1; int t(int)sqrt(Max*1.0); for(int i3;i<t;i) if(prime…

6、iptables之RAW表和MANGLE表

文章目录1.说明2.raw表3.Mangle表1.说明 RAW表 和 MANGLE 表 实事求是的说 在⼯工作中 ⼀一般⽤用到的确实⽐比较少,⽬前更更多的 还是处在⼀一个 探索和实验的阶段 后期 随着IPTABLES的发展更更新 可能这两个表 也会加⼊入到 主流⽤用法当中 2.raw表 RAW表 是IPTABLES中 第⼀一…

如何成为一名Quant,金融工程师和My Life as a Quant书评

quant是做什么的&#xff1f; quant的工作就是设计并实现金融的数学模型&#xff08;主要采用计算机编程&#xff09;&#xff0c;包括衍生物定价&#xff0c;风险估价或预测市场行为等。所以quant更多可看为工程师&#xff0c;按中国的习惯性分类方法就是理工类人才&#xff…

7、iptables之四表优先级以及完整的流程图

比较常用的就是&#xff1a; FILTER INPUT NAT PREROUTHING NAT POSTROUTHING

标注偏置问题(Label Bias Problem)和HMM、MEMM、CRF模型比较

路径1-1-1-1的概率&#xff1a;0.4*0.45*0.50.09 路径2-2-2-2的概率:0.018 路径1-2-1-2:0.06 路径1-1-2-2:0.066 由此可得最优路径为 1-1-1-1 而实际上&#xff0c;在上图中&#xff0c;状态1偏向于转移到状态2&#xff0c;而状态2总倾向于停留在状态2&#xff0c;这就是所谓的…

listview崩溃问题

放很小的图标没关系 每一项加上800x800的图片就在我机子上跑不动了闪退 然后在模拟器上一切正常 把图片全部压缩成100x100就ok了 大概是朱哥说的渲染过度问题&#xff1f; 反正以后别放大图片了OTZ转载于:https://www.cnblogs.com/hishark/p/7896180.html

8、iptables 语法规则

文章目录1.语法构成2.常见的动作类型3.添加新的规则4.查看规则列表5.删除清空规则6.设置默认策略7.通用匹配8.隐含匹配9.显示匹配10.SNAT11.DNAT开启IPV4转发功能12.备份和还原1.语法构成 iptables [-t 表名] 选项 [链名] [条件] [-j 控制类型] 注意事项&#xff1a; 不指定表名…

中国版Office 365 应用程序注册

作者&#xff1a;陈希章 发表于 2017年3月23日中国版Office 365是由世纪互联进行运营的一个云服务&#xff0c;单纯从技术角度来看的话&#xff0c;它基本保持了与国际版的同步。但是由于两个版本本质上是完全独立的&#xff0c;其中最关键的就是账号系统是分开的&#xff0c;所…