#———————————解码————————————
#转移概率共36项,输入格式如下
#-3.0613860150847194
#6.3296570233861047
#-1.0675635747046173
#4.6421254962811851
#-1.5142773207880604
#……
# 0 1 2 3 4 5
# B B2 B3 E M S
open(Intrans, "<$ARGV[0]") or die "无法打开转移概率文件。\n";
$i=0;
$j=0;
@trans=();
while(<Intrans>)
{
chomp($_);
if($_ eq "")
{
last;
}
if($j==6)
{
$i++;
$j=0;
}
$trans[$i][$j]=$_;
$j++;
}
close(Intrans);
#发射概率,已经整理好的格式为:
#斑 3.97691826923261 -2.52579567328892 -1.5895838657426 -3.72106476979734 -0.650725191401929 4.51025123096978
#鳐 -1.1952615290497 -1.27312993797494 -0.912265484804526 3.04872521886247 0.0471828435366093 0.284748889415727
# 0 1 2 3 4 5
# B B2 B3 E M S
open(Infeature, "<$ARGV[1]") or die "无法打开发射概率文件。\n";
$num=0;
while(<Infeature>)
{
chomp($_);
if($_ eq "")#开始结算当前viterbi
{
# $num * 6 矩阵;@score[$num][6] 得分矩阵;@father[$num][6]父节点矩阵;
# $i * $j 下标; $my_j当前类别下标; $father_j父节点类别下标
# CRF的解码全部使用加法,本程序暂且“不归一化”。
# 初始化首节点,首节点只能是B或者S,其它设置成最大负值。
for($j=0;$j<6;$j++)
{
$score[0][$j]=-100;
$father[0][$j]=-1;
}
$score[0][0]=$feature{0}->{0};
$score[0][0]=$feature{0}->{5};
#中间节点计算路径
for($i=1;$i<$num;$i++)
{
for($my_j=0;$my_j<6;$my_j++)
{
$father_j=0;
$score[$i][$my_j]=$score[$i-1][$father_j]+$trans[$father_j][$my_j];
$father[$i][$my_j]=$father_j;
for($father_j=1;$father_j<6;$father_j++)
{
if($score[$i-1][$father_j]+$trans[$father