我发现一个问题,CRF++的结果好于CRFsuite 差0.01-0.02左右
不会python啊,太弱了。
自己写了个perl的预处理,从crf++的模板改成crfsuite的。还不知道它能不能跑大语料,试试吧
#输入文件格式
#迈 n_punc N_num B
#向 n_punc N_num E
#充 n_punc N_num B
#满 n_punc N_num E
#希 n_punc N_num B
#望 n_punc N_num E
#句子间有空行
#迈 n_punc N_num B
#向 n_punc N_num E
#充 n_punc N_num B
#满 n_punc N_num E
#希 n_punc N_num B
#望 n_punc N_num E
#最后必须空一行
#模板文件格式:
#W P N
#%x[-1,0]
#%x[0,0]
#%x[1,0]
#%x[-2,0]
#%x[2,0]
#%x[-1,0]/%x[0,0]
#%x[0,0]/%x[1,0]
#%x[-1,0]/%x[1,0]
#%x[-2,0]/%x[-1,0]
#%x[1,0]/%x[2,0]
#%x[0,1]
#%x[0,2]
#输出文件格式:
#句首:B-NP w[0]=He w[0]|w[1]=He|reckonspos[0]=PRP pos[0]|pos[1]=PRP|VBZ __BOS__
#句中:I-NP w[0]=He w[0]|w[1]=He|reckonspos[0]=PRP pos[0]|pos[1]=PRP|VBZ
#句尾:E-NP w[0]=He w[0]|w[1]=He|reckonspos[0]=PRP pos[0]|pos[1]=PRP|VBZ __EOS__
#没有的特征则可以不写
#由于句首句尾都有BOS、EOS对于训练语料测试语料中一个字一行的情况,全部删除
#当前perl只支持到二元观察特征,并且没有标签到标签的转移特征,那需要使用markov的CRF
open(Intemp,"<$ARGV[1]");#模板文件
$uni_sub=0;#一元特征数量
$bin_sub=0;#二元特征数量
#第一行是列名,用空格分开
$firstline=<Intemp>;
chomp($firstline);
@colo_name=split " ",$firstline;
$colo_num=scalar(@colo_name);
while(<Intemp>){
chomp();
if($_ eq "")
{
next;
}
if($_=~/x\[(.*)]\/\%x\[(.*)\]/)
{
$bin_sub++;
@temp_cell=();
@temp_cell=split "\,",$1;
$bin_array{$bin_sub}->{0}=$temp_cell[0];
$bin_array{$bin_sub}->{1}=$temp_cell[1];
@temp_cell=();
@temp_cell=split "\,",$2;
$bin_array{$bin_sub}->{2}=$temp_cell[0];
$bin_array{$bin_sub}->{3}=$temp_cell[1];
}
elsif($_=~/x\[(.*)\]/)
{
$uni_sub++;
@temp_cell=();
@temp_cell=split "\,",$1;
$uni_array{$uni_sub}->{0}=$temp_cell[0];
$uni_array{$uni_sub}->{1}=$temp_cell[1];
}
}
close(Intemp);
$sentence_num=0;#用于记录这句话的字数,也可以判断这句话是否被输出
@sentence_array=();
open(Incrf,"<$ARGV[0]");#原文
while(<Incrf>){
chomp();
if($_ eq "")
{
if($sentence_num>1){#只对句长大于1的句子分析
for($i=0;$i<$sentence_num;$i++)#i行,j列,第一个特征是哪列,就用哪个列名
{
print"$sentence_array{$i}->{$colo_num}\t";#先打印出标签
foreach(keys %uni_array)
{
$row=$i+$uni_array{$_}->{0};
$column=$uni_array{$_}->{1};
if( $row >-1 and $row < $sentence_num)
{
print"$colo_name[$column]\[$uni_array{$_}->{0}\]\=$sentence_array{$row}->{$column}\t";
}
}
foreach(keys %bin_array)
{
$row_a=$i+$bin_array{$_}->{0};
$column_a=$bin_array{$_}->{1};
$row_b=$i+$bin_array{$_}->{2};
$column_b=$bin_array{$_}->{3};
if( $row_a >-1 and $row_a < $sentence_num and $row_b >-1 and $row_b < $sentence_num)
{
print"$colo_name[$column_a]\[$bin_array{$_}->{0}\]\|$colo_name[$column_b]\[$bin_array{$_}->{2}\]";
print"\=$sentence_array{$row_a}->{$column_a}\|$sentence_array{$row_b}->{$column_b}\t"
}
}
#控制句子边界
if ($i < 1) {
print"__BOS__";
}elsif($i > $sentence_num-2)
{
print"__EOS__";
}
print"\n";
}
print"\n";
}
$sentence_num=0;
%sentence_array=();
}else{
@chars=split " ",$_;
for($i=0;$i<@chars;$i++){
$sentence_array{$sentence_num}->{$i}=$chars[$i];
}
$sentence_num++;
}
}
close(Incrf);