一 标注标签分类
IO
BIO
BMEWO
BMES
二 CRF++简介
CRF++是著名的条件随机场的开源工具,简单介绍一下windows系统下CRF++的使用
下载地址:crf++0.58
下载完解压就可以使用
2.1 文件目录
doc文件夹:就是官方主页的内容。
example文件夹:有四个任务的训练数据、测试数据和模板文件。
sdk文件夹:CRF++的头文件和静态链接库。
crf_learn.exe:CRF++的训练程序。
crf_test.exe:CRF++的预测程序
libcrfpp.dll:训练程序和预测程序需要使用的静态链接库。
一般我们只需要使用的就是crf_learn.exe,crf_test.exe和libcrfpp.dll,这三个文件。
2.2 命令行格式
训练
% crf_learn template_file train_file model_file
这个训练过程的时间、迭代次数等信息会输出到控制台上(感觉上是crf_learn程序的输出信息到标准输出流上了),如果想保存这些信息,我们可以将这些标准输出流到文件上,命令格式如下:
% crf_learn template_file train_file model_file >> train_info_file
四个主要参数调整:
-a CRF-L2 or CRF-L1
规范化算法选择。默认是CRF-L2。一般来说L2算法效果要比L1算法稍微好一点,虽然L1算法中非零特征的数值要比L2中大幅度的小。
-c float
这个参数设置CRF的hyper-parameter。c的数值越大,CRF拟合训练数据的程度越高。这个参数可以调整过度拟合和不拟合之间的平衡度。这个参数可以通过交叉验证等方法寻找较优的参数。
-f NUM
这个参数设置特征的cut-off threshold。CRF++使用训练数据中至少NUM次出现的特征。默认值为1。当使用CRF++到大规模数据时,只出现一次的特征可能会有几百万,这个选项就会在这样的情况下起到作用。
-p NUM
如果电脑有多个CPU,那么那么可以通过多线程提升训练速度。NUM是线程数量。
一个示例
crf_learn -f 3 -c 4 template_file train_file model_file
测试
% crf_test -m model_file test_files
有两个参数-v和-n都是显示一些信息的,-v可以显示预测标签的概率值,-n可以显示不同可能序列的概率值,对于准确率,召回率,运行效率,没有影响。
与crf_learn类似,输出的结果放到了标准输出流上,而这个输出结果是最重要的预测结果信息(测试文件的内容+预测标注),同样可以使用重定向,将结果保存下来,命令行如下:
% crf_test -m model_file test_files >> output_file
训练过程中会输出一些信息,其意义如下:
iter:迭代次数。当迭代次数达到maxiter时,迭代终止
terr:标记错误率
serr:句子错误率
obj:当前对象的值。当这个值收敛到一个确定值的时候,训练完成
diff:与上一个对象值之间的相对差。当此值低于eta时,训练完成
如果希望训练快速结束,可以在命令行中适当减小maxiter值,增大eta值
三 模板构建
模板构建分为两类,一类是Unigram标注,一类是Bigram标注。
Unigram模板是比较常用的模板,这类模板提取的信息较为全面,组成的模板数量也比较多;
Bigram模板比较简单,一般是当前词和前面一个词的自动组合生成的Bigram特征集合。
Unigram和Bigram模板分别生成CRF的状态特征函数 sl(yi,x,i) 和转移特征函数 tk(yi-1,yi,x,i) 。其中 yi 是标签, x 是观测序列, i 是当前节点位置。每个函数还有一个权值.
crf++模板定义里的%x[row,col],即是特征函数的参数 x 。
举个例子。假设有如下用于分词标注的训练文件:
北 N B
京 N E
欢 V B
迎 V M
你 N E
第一列是文字,第二列是词性,前两列都可以视为特征,第三列为标签,也就是我们需要预测的内容,有BME三种状态。
我们选取第一列作为特征来讲解便于理解,去除中间的词性标注
所以训练文件变为:
北 B
京 E
欢 B
迎 M
你 E
特征模板格式:%x[row,col]。x可取U或B,对应两种类型。方括号里的编号用于标定特征来源,row表示相对当前位置的行,0即是当前行;col对应训练文件中的列。这里只使用第1列(编号0),即文字。
Unigram类型
每一行模板生成一组状态特征函数,数量是L * N 个,L是标签状态数。N是此行模板在训练集上展开后的唯一样本数,在这个例子中,第一列的唯一字数是5个,所以有L * N = 3*5=15。
例如:U01:%x[0,0],生成如下15个函数:
func1 = if (output = B and feature=U01:“北”) return 1 else return 0
func2 = if (output = M and feature=U01:“北”) return 1 else return 0
func3 = if (output = E and feature=U01:“北”) return 1 else return 0
func4 = if (output = B and feature=U01:“京”) return 1 else return 0
…
func13 = if (output = B and feature=U01:“你”) return 1 else return 0
func14 = if (output = M and feature=U01:“你”) return 1 else return 0
func15 = if (output = E and feature=U01:“你”) return 1 else return 0
这些函数经过训练后,其权值表示函数内文字对应该标签的概率(形象说法,概率和可大于1)。
又如 U02:%x[-1,0] 因为第一行没有前一行(-1 行)所以从第二行开始选取当前token的前一行的第一列。一直到最后一行的前一行结束
token = “北”
func1 = if (output = B and feature=U01:“京”) return 1 else return 0
func1 = if (output = M and feature=U01:“京”) return 1 else return 0
func1 = if (output = E and feature=U01:“京”) return 1 else return 0
…
token = “你”
func10 = if (output = B and feature=U01:“迎”) return 1 else return 0
func11 = if (output = M and feature=U01:“迎”) return 1 else return 0
func12 = if (output = E and feature=U01:“迎”) return 1 else return 0
训练后,该组函数权值反映了句子中上一个字对当前字的标签的影响。
对于每一个不同的token(这里指第一列的数据),依此套入模板来生成状态特征函数
Bigram类型
与Unigram不同的是,Bigram类型模板生成的函数会多一个参数:上个节点的标签 。第一个字符是B,每一行%x[#,#]生成一个CRFs中的边(Edge)函数:f(s’, s, o), 其中s’为t – 1时刻的标签.也就是说,Bigram类型与Unigram大致机同,只是还要考虑到t – 1时刻的标签。
每行模板则会生成 L* L* N 个特征函数。经过训练后,这些函数的权值反映了上一个节点的标签对当前节点的影响。
生成函数类似于(对于token =“北”):
func1 = if (prev_output = B and output = B and feature=B01:“北”) return 1 else return 0
func1 = if (prev_output = B and output = M and feature=B01:“北”) return 1 else return 0
func1 = if (prev_output = B and output =E and feature=B01:“北”) return 1 else return 0
func1 = if (prev_output = M and output = B and feature=B01:“北”) return 1 else return 0
func1 = if (prev_output = M and output = M and feature=B01:“北”) return 1 else return 0
func1 = if (prev_output = M and output = E and feature=B01:“北”) return 1 else return 0
func1 = if (prev_output = E and output = B and feature=B01:“北”) return 1 else return 0
func1 = if (prev_output = E and output = M and feature=B01:“北”) return 1 else return 0
func1 = if (prev_output = E and output = E and feature=B01:“北”) return 1 else return 0
…
对于上面的训练数据 一共生成45个转移函数
如果只写一个B的话,默认生成f(s’, s),这意味着前一个output token和current token将组合成bigram features。
先写到这儿,有不对的地方 欢迎指出