
版权声明:本文为博主原创文章,未经博主允许不得转载。
看完第六章开始后悔之前花那么多时间看前四章内容了。。看了也忘掉了。。什么困惑度啊什么的一堆概念还是要翻一翻。。之前总怕不仔细看后面的看不懂。。结果重要的第五章第六章反而看的比前面愉快了许多~主要还是概率的知识,几乎都是条件概率,条件概率公式、全概率公式和贝叶斯公式用的挺多,当然还有独立性。。下面不废话了。。具体说一下。。
【心得及问题】
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了一天啊有木有!!):
- #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;
- }
后向算法(感觉书上算法第三步写错了。。害我苦思冥想到底和第一个状态有什么关系想了好久。。。):
- #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;
- }