2013年4月3日星期三

往cdec中添加一个新feature

可按下面步骤:
1) 在decoder/目录下新建ff_feature_name.h和ff_feature_name.cc文件.
    在ff_feature_name.h中定义继承于FeatureFunction的类, 如何有需要, 定义继承于FactoryBase的factory类. 可参考ff_klm.h, ff_basic.h等.

2) 注册新定义的feature
    在decoder/cdec_ff.cc中注册新feature
    #include "ff_feature_name.h"
    在void register_feature_functions()中添加:
    ff_registry.Register("NewFeatureName", new NewFeatureFactory()); //如果定义了factory类
    或者
    ff_registry.Register("NewFeatureName", new FFFactory); //如果没有定义factory类

3) 在decoder/Makefile.am 中添加新定义的类(文件) ff_feature_name.cc, 可参考ff_klm类的写法.

4) 重新编译..


添加一个新的feature, contextual free, 但是需要用state来保留些信息, 用于快速计算该feature值.
这个时候需要注意, apply_models.cc/IncorporateIntoPlusLMForest(...), 里面(*s2n)[item->state_]会根据state值,决定是否产生一个新的node,或者丢弃. 因此在这之前需要将state里面的内容关于新feature的部分给erase掉. 按以下:
1) 在ff_set.h/ModelSet类里添加
public: 
FFState GetRealFFState(const FFState& state) const;
在该方法的实现中根据原state状态, 返回一个新的real_state, real_state里将新feature部分的state给删除掉了
2) 在apply_models.cc/IncorporateInputPlusLMForest(...)里:
Candidate*& o_item = (*s2n)[item->state_];
修改为

FFState real_state = models.GetRealFFState(item->state_);
Candidate*& o_item = (*s2n)[real_state];


assert(o_item->state_ == item->state_);    // sanity check!
修改为

assert(models.GetRealFFState(o_item->state_) == models.GetRealFFState(item->state_));  //sanity check!

附: GetRealFFState()实现
void ModelSet::GetRealFFState(const FFState& state, FFState& real_state) const {
real_state.resize(state.size());
for (int i = 0; i < state.size(); i++) {
real_state[i] = state[i];
}

if (state.size() == 0)
return;
assert(state.size() == state_size_);

//erase the states for SRLReorderFeature
for (int i = 0; i < models_.size(); i++) {
if (models_[i]->name_ == string( "NewFeatureName" )) {
int start_pos = model_state_pos_[i];
int end_pos;
if (i == models_.size() - 1)
end_pos = state_size_;
else
end_pos = model_state_pos_[i + 1];
for (int j = start_pos; j < end_pos; j++)
real_state[j] = 0;
}
}
}

FFState ModelSet::GetRealFFState(const FFState& state) const {
FFState real_state;
GetRealFFState(state, real_state);
return real_state;
}