例子解析
下面是一个crfpp训练出来的txt模型样例:
version: 100
cost-factor: 1
maxid: 2978536
xsize: 1
B
E
M
O
U00:%x[-3,0]
U01:%x[-2,0]
U02:%x[-1,0]
U03:%x[0,0]
U04:%x[1,0]
U05:%x[2,0]
U06:%x[3,0]
U07:%x[-3,0]/%x[-2,0]/%x[-1,0]/%x[0,0]
U08:%x[-2,0]/%x[-1,0]/%x[0,0]/%x[1,0]
U09:%x[-1,0]/%x[0,0]/%x[1,0]/%x[2,0]
U10:%x[0,0]/%x[1,0]/%x[2,0]/%x[3,0]
U11:%x[-2,0]/%x[-1,0]/%x[0,0]
U12:%x[-1,0]/%x[0,0]/%x[1,0]
U13:%x[0,0]/%x[1,0]/%x[2,0]
U14:%x[-1,0]/%x[0,0]
U15:%x[0,0]/%x[1,0]
B
0 B
16 U00:"
20 U00:#
24 U00:$
28 U00:%
32 U00:&
...
2978512 U15:¥/6
2978516 U15:¥/7
2978520 U15:¥/8
2978524 U15:¥/9
2978528 U15:¥/_
2978532 U15:¥/收
-0.3833645332269790
0.1201377122403721
2.4181637661758955
-2.9061977301372388
-0.8957977672327538
-0.5282220808730558
-0.4808152690227827
-0.0180459673166369
-0.7088260954767709
1.4525415018058483
4.5702819962135459
-2.5223604291302082
...
注意:文件太长,我们省略了一部分内容(用省略号表示)
从上往下,我们一一来看:
- 第1~4行:
maxid
表示最大的特征函数id;xsize
表示训练数据特征列数 - 第6~9行:表示训练数据标注集(状态集),此处分别是
B
、E
、M
、O
- 第11~27行:表示特征模板,其中第27行为bigram特征模板;其余为unigram特征模板
第29~41行:表示特征模板产生的特征函数。格式为:
<特征函数id> <模板id>:<观测>
你发现id显示并不是连续的,为什么呢?
对于id为(0~15),特征函数实际上是bigram特征。bigram特征实际上是状态转移特征,即:
B->B B->E B->M B->O E->B E->E E->M E->O M->B M->E M->M M->O O->B O->E O->M O->O
对于后面的id,你发现每4个显示一次,实际上特征函数是针对某个具体标签的,模型中只显示了针对第一个标签(此处是
B
)产生的特征函数。所以特征函数U00:"
对于标签O
的id就是19。
第43行以后:表示每个特征函数的权重。数值越大,特征函数越重要。前16个数字是状态转移权重;后面是特征函数权重,和上面的特征函数一一对应。
关于解码
- 对于每个观测,每个特征模板都会生成它对于每个状态的特征函数,我们在模型中找到特征函数对应的权重,累加得到score
- 从模型中我们还获得了状态转移权重,于是可以使用维特比解码,找出score最高的序列
看个例子:
我们有如下模板:
U00:%x[-2,0]/%x[-1,0]
U01:%x[-1,0]/%x[0,0]
我们的标注集为:
B E M O
我们要预测的序列为:
我今天很开心
假设当前观测为很
,于是两个模板产生如下特征函数:
今/天 -> B
今/天 -> E
今/天 -> M
今/天 -> O
天/很 -> B
天/很 -> E
天/很 -> M
天/很 -> O
于是,我们从模型中找对应特征函数的权重(找不到就是0),将这些权重加起来,得到当前很
字分别为B
、E
、M
、O
的score。这样,序列的每个观测对应每个状态都会有一个score,再依据状态转移信息,进行维特比解码。