本文只是补充,更详细关于CRF++信息请参考:CRF++: Yet Another CRF toolkit
1. 特征模板
CRF++的特征模板:
- unigram模板会生成状态特征;(包含单特征和组合特征)
- bigram模板即转移特征。
一个模板(unigram模板文件中的一行)会生成 L*N
个特征函数,这里L
是输出类标种类数,N
是模板表示的唯一字符串个数。比如对于%x[0,1]
,假设第1
列特征表示词性,N
是词性种类数。
一个常用的单列特征模板:
# Unigram
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]
# Bigram
B
2. 解码
假设我们要用CRF做分词,数据被标注为如下格式:
今 B
天 E
天 B
气 E
很 S
好 S
啊 S
我 S
开 B
开 M
心 M
心 E
玩 S
去 S
了 S
我们使用上述格式数据,使用crf_learn
训练了一个分词模型wordseg_model
,接下来可以使用下面代码在线解码。
单列特征分词crf模型解码:
# coding: utf-8
from __future__ import unicode_literals
import os
from CRFPP import Tagger
class CRFDecoder(object):
def __init__(self, model_path):
assert os.path.isfile(model_path) and isinstance(model_path, unicode)
self._crf_tagger = Tagger('-m {}'.format(model_path).encode('utf-8'))
def parse(self, sent):
assert isinstance(sent, unicode)
sent = sent.strip()
result = []
self._crf_tagger.clear()
for char in sent:
if char:
self._crf_tagger.add(char.encode('utf-8'))
self._crf_tagger.parse()
size = self._crf_tagger.size()
xsize = self._crf_tagger.xsize()
tags = [self._crf_tagger.y2(i) for i in range(size)]
return tags
if __name__ == '__main__':
model_path = 'wordseg_model'
decoder = CRFDecoder(model_path)
sent = '今天天气很好啊'
tags = decoder.parse(sent)
print(tags)