文章出处:http://blog.sina.com.cn/s/blog_5980285201018ijz.html

再贴一个函数调用图:
需要注意的地方也不多:
最需要注意的是TaggerImpl::gradient()函数
1. 首先调用buildLattice函数来构造出一个表
buildLattice函数调用 rebuildFeatures函数
在rebuildFeatures函数中,建立了tagger需要的node_矩阵,同时填充了path信息。
重要需要关注的是node类:
2. buildLattice函数接下来调用calcCost()函数
分别对应于论文【条件随机场理论综述,韩雪冬,周彩根】中公式(55)的第一项和第二项:
(注意,这里已经都经过了取对数的处理)
从公式中可以看到, Node和Path的cost是对应的特征的权重的和,这在代码 calcCost(Node *)和calcCost(Path *)中体现的很明显
3.gradient函数接下来调用forwardbackward函数
calcAlpha, calcBeta
这里的Alpha和Beta分别对应于论文【条件随机场理论综述,韩雪冬,周彩根】中公式(59,60)中的Alpha, Beta.
计算如下是:
这几个公式在代码中体现的都很明显,Alpha和Beta是用动态规划的方法进行计算(跟HMM如出一辙)
Z是partition function,等于所有M矩阵的乘积,在代码中体现也很明显
4.gradient函数接下来调用calcExpectation函数
Node和Path对应的expectation都是用论文【条件随机场理论综述,韩雪冬,周彩根】中公式(61)
5.计算梯度
根据论文【条件随机场理论综述,韩雪冬,周彩根】中公式(52)来计算梯度
公式中的第一项已经在代码的calcExpectation中加上去了
公式中的第二项体现在gradient函数中的两个地方:
--expected[*f + answer_[i]]; //对应于unigram
--expected[*f +(*it)->lnode->y * ysize_ +(*it)->rnode->y]; //对应于bigram
5.gradient函数接下来调用viterbi函数
这个跟HMM中的viterbi函数是一样的,略过
6.gradient的目标函数
目标函数是似然函数的相反数
似然函数定义如下:论文【条件随机场理论综述,韩雪冬,周彩根】中公式(49)
代码中的体现如下:
return Z_ - s;