一、生成模型和判别模型
1.什么是生成模型和判别模型
从本质上讲,生成模型和判别模型是解决分类问题的两类基本思路。
分类问题,就是给定一个数据x,要判断它对应的标签y。判别模型就是直接学习条件概率分布P(y|x)。
生成模型就是要学习x和y的联合概率分布P(x,y),然后根据贝叶斯公式来求得条件概率P(y|x),预测条件概率最大的y。
2.贝叶斯定理: p(xy)=p(y|x)*p(x)
P(Y|X)是条件概率,在已知X发生概率下,Y发生的概率.
P(x,y)=P(X=x and Y=y)是联合分布概率,其联合分布就是同时对于X和Y的概率分布,这个概率P同时受到x,y的约束
例子1:假设你从来没有见过大象和猫,只看过大象和猫的照片。然后牵来一只大象,让你判断这是大象还是猫。
(1)大概记起来,大象和猫比起来,有个长鼻子,而眼前这个家伙也有个长鼻子
第一个解决问题的思路就是判别模型,因为你只记住了大象和猫之间的不同之处
(2)回想刚才的两张照片,然后用笔把它们画在了纸上,拿着纸和大象做比较,发现眼前的动物更像是大象
第二个解决问题的思路就是生成模型,因为你实际上学习了什么是大象,什么是猫。
例子2:四个形式为(x,y)的样本。(1,0), (1,0), (2,0), (2, 1)。假设从这四个样本中,学习到如何通过x判断y的模型
生成模型要学习P(x,y):
P(x=1,y=0) = 1/2 P(x=1,y=1) = 0
我们发现P(x=1,y=0)的概率要比P(x=1,y=1)的概率大,所以,我们判断:x=1时,y=0。
//结合例子1就是:有长鼻子并且是大象的概率是1,有长鼻子并且是猫的概率是1,面前的动物有长鼻子,所以是大象。
判别模型要学习P(y|x):
P(y=0|x=1) = 1 P(y=1|x=1) = 0
同样,P(y=0|x=1)要比P(y=1|x=1)大,所以,我们判断:x=1时,y=0。
我们看到,虽然最后预测的结果一样,但是得出结果的逻辑却是完全不同的。
//结合例子1就是:有长鼻子并且是大象的概率是1,有长鼻子并且是猫的概率是1,面前的动物有长鼻子,所以是大象。
3.为啥叫生成模型?
因为背后的思想是,x是特征,y是标签,什么样的标签就会生成什么样的特征。比如标签是大象,可能生成的特征有大耳朵,长鼻子等等。
当我们来根据x来判断y时,我们实际上是在比较,什么样的y标签更可能生成特征x,我们预测的结果就是更可能生成x特征的y标签。
4.常见的生成模型和判别模型
生成模型:HMM、朴素贝叶斯
判别模型:逻辑回归、SVM、CRF、最近邻、一般的神经网络
二、HMM与CRF
https://www.cnblogs.com/hellochennan/p/6624509.html(很全版)
https://blog.csdn.net/u013378306/article/details/55213029(简单版,很好)
隐马尔科夫模型的缺点:
1、HMM只依赖于每一个状态和它对应的观察对象:
序列标注问题不仅和单个词相关,而且和观察序列的长度,单词的上下文,等等相关。
2、目标函数和预测目标函数不匹配:
HMM学到的是状态和观察序列的联合分布P(Y,X),而预测问题中,我们需要的是条件概率P(Y|X)。
https://zhuanlan.zhihu.com/p/44042528(知乎)
即使没有CRF层,我们照样可以训练一个基于BiLSTM的命名实体识别模型,但CRF层可以学习到句子的约束条件。
CRF层可以加入一些约束来保证最终预测结果是有效的。这些约束可以在训练数据时被CRF层自动学习得到。
CRF中有转移概率矩阵,会平衡各个之间的关系,经过它输出之后,会更加的稳定健全
比如:句子的开头应该是“B-”或“O”,而不是“I-”。
“B-label1 I-label2 I-label3…”,在该模式中,类别1,2,3应该是同一种实体类别。
比如,“B-Person I-Person” 是正确的,而“B-Person I-Organization”则是错误的。
“O I-label”是错误的,命名实体的开头应该是“B-”而不是“I-”。有了这些有用的约束,错误的预测序列将会大大减少。
CRF层中的损失函数包括两种类型的分数,理解这两类分数的计算是理解CRF的关键
第一个类型的分数是发射分数(状态分数)。这些状态分数来自BiLSTM层的输出。
第二个类型的分数是转移分数
转移矩阵是BiLSTM-CRF模型的一个参数。在训练模型之前,可以随机初始化转移矩阵的分数。
这些分数将随着训练的迭代过程被更新,换句话说,CRF层可以自己学到这些约束条件。
比如:转移矩阵已经学习到一些有用的约束条件:句子的第一个单词应该是“B-” 或 “O”,而不是“I”。
损失函数
CRF损失函数由两部分组成,真实路径的分数 和 所有路径的总分数。真实路径的分数应该是所有路径中分数最高的。
一个包含5个单词的句子,可能的类别序列如下。每种可能的路径的分数为Pi,共有N条路径,则路径的总分是
P total = P1+P2+P3+...+Pn = e^S1 + e^S2 +...+ e^Sn
根据如下损失函数,在训练过程中,BiLSTM-CRF模型的参数值将随着训练过程的迭代不断更新,使得真实路径所占的比值越来越大。
Loss = P realPath / (P1+P2+P3+...+Pn)
1.计算真实路径分数eSi。
Si = EmissionScore(来自BiLSTM层的输出) + TransitionScore(来自于CRF层)
2.所有路径的总分
将原损失函数求对数,最终提取出log(e^S1 + e^S2 +...+ e^Sn)
计算的过程像动态规划。首先,w0所有路径的总分先被计算出来,然后计算w0 -> w1的所有路径的得分,
最后计算w0 -> w1 -> w2的所有路径的得分,也就是我们需要的结果。
三、HMM结合分词,CRF结合词性标注和实体识别
1.HMM的典型介绍就是这个模型是一个五元组:
StatusSet: 状态值集合
ObservedSet: 观察值集合
TransProbMatrix: 转移概率矩阵
EmitProbMatrix: 发射概率矩阵
InitStatus: 初始状态分布
2.三个基本假设如下:
齐次性假设(状态和当前时刻无关):
观察值独立性假设(观察值只取决于当前状态值):
有限历史性假设(即Status(i)只和Status(i-1)相关)
HMM模型可以用来解决三种问题:
参数(StatusSet,TransProbMatrix,EmitRobMatrix,InitStatus)已知的情况下,求解观察值序列。(Forward-backward算法)
参数(ObservedSet,TransProbMatrix,EmitRobMatrix,InitStatus)已知的情况下,求解状态值序列。(viterbi算法)
参数(ObservedSet)已知的情况下,求解(TransProbMatrix,EmitRobMatrix,InitStatus)。(Baum-Welch算法)
其中,第三种问题最玄乎也最不常用,第二种问题最常用,【中文分词】,【语音识别】, 【新词发现】, 【词性标注】
都有它的一席之地。所以本文主要介绍第二种问题,即【viterbi算法求解状态值序列】的方法。
3.在分词中的应用
状态值集合为(B, M, E, S): {B:begin, M:middle, E:end, S:single},分别代表每个状态代表的是该字在词语中的位置。
B代表该字是词语中的起始字,M代表是词语中的中间字,E代表是词语中的结束字,S则代表是单字成词。
观察值集合为就是所有汉字(东南西北你我他…),甚至包括标点符号所组成的集合。
输入是一个句子(也就是观察值序列):小明硕士毕业于中国科学院计算所
输出是这个句子中每个字的状态值: BEBEBMEBEBMEBES
根据这个状态切词:BE/BE/BME/BE/BME/BE/S,得到小明/硕士/毕业于/中国/科学院/计算/所
初始状态概率分布,也就是句子的第一个字属于{B,E,M,S}这四种状态的概率。
E和M的概率都是0,这和实际相符合,开头的第一个字只可能是词语的首字(B),或者是单字成词(S)。
B -0.2626866 #E -3.14e+100 #M -3.14e+100 #S -1.4652633
转移概率:TransProbMatrix[0][0]代表的含义就是从状态B转移到状态B的概率(BEMS x BEMS)
发射概率:发射概率(EmitProb)其实也是一个条件概率,P(Observed[i], Status[j]) = P(Status[j]) * P(Observed[i]|Status[j])
其中P(Observed[i]|Status[j])这个值就是从EmitProbMatrix中获取。观察值只取决于当前状态值
4.Viterbi算法
4是状态数(0:B,1:E,2:M,3:S),15是输入句子的字数。
二维数组 weight[4][15],比如 weight[0][2] 代表 状态B的条件下,出现'硕'这个字的可能性。
二维数组 path[4][15],比如 path[0][2] 代表 weight[0][2]取到最大时,前一个字的状态,
比如 path[0][2] = 1, 则代表 weight[0][2]取到最大时,前一个字(也就是明)的状态是E。
记录前一个字的状态是为了能对输入句子从右向左地回溯回来,找出对应的状态序列。
//遍历句子,下标i从1开始是因为刚才初始化的时候已经对0初始化结束了
for(size_t i = 1; i < 15; i++)
{
// 遍历可能的状态
for(size_t j = 0; j < 4; j++)
{
weight[j][i] = MIN_DOUBLE;
path[j][i] = -1;
//遍历前一个字可能的状态
for(size_t k = 0; k < 4; k++)
{
double tmp = weight[k][i-1] + _transProb[k][j] + _emitProb[j][sentence[i]];
if(tmp > weight[j][i]) // 找出最大的weight[j][i]值
{
weight[j][i] = tmp;
path[j][i] = k;
}
}
}
确定边界条件和路径回溯
边界条件如下:对于每个句子,最后一个字的状态只可能是 E 或者 S,不可能是 M 或者 B。
在本文的例子中我们只需要比较 weight[1(E)][14] 和 weight[3(S)][14] 的大小即可。
所以 S > E,也就是对于路径回溯的起点是 path[3][14],回溯的路径是:SEBEMBEBEMBEBEB,
倒序一下就是:BE/BE/BME/BE/BME/BE/S。所以切词结果就是:小明/硕士/毕业于/中国/科学院/计算/所
训练的过程就是将这三个参数,基于已分词完毕的语料进行统计计算,计算出相应的频率和条件概率就可以算出这三个参数。
https://blog.csdn.net/liujianfei526/article/details/50640176