读了CRF++源码,总结如下几点
1,实现的是linear-chain结构
2,感觉对样例的表示方式不如maxent灵活,可以看看suit的实现
3,TaggerImpl存储训练样例,x存储相应的output序列,result存储相应的状态序列,answer存储模型算出来的状态序列;为了实现多线程并发处理,另外存储了处理该TaggerImpl的线程thread_id_;output序列中的每一个token都对应一个feature集合,整个output序列对应了feature集合的序列,系统将所有训练样例的feature集合顺序存储在一个feature_cache中,因此在每一个TaggerImpl中保存了自己的feature序列在feature_cache中偏移量feature_id_,而这个feature_cache存在于FeatureIndex对象中。系统中所有的TaggerImpl都共享一个FeatureIndex对象;为了DP编程的方便,又包含一个Node二维数组,横轴对应output中的每一个token,纵轴代表系统状态集合中的每一个状态。
4,Node存储DP中的每一个状态,包括alpha,beta,verterbi路径前驱等。
5,与maxent不同的是在buildfeature的时候,系统会为每一个<obeservation,state>状态创建feature,这里的state包括unigram和bigram特征,而不管他们是否在训练数据中出现过。
6,所有的observation从training data中提取,然后存储在feature_cache的dict中,这个dict的结构是observation->pair<observationId,count>,最后observationId的最大值就是模型所有参数的个数。