Repository navigation
Expand file tree
/
Copy pathTagger.cs
More file actions
154 lines (134 loc) · 4.46 KB
/
Copy pathTagger.cs
File metadata and controls
154 lines (134 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
namespace Bigtree.Algorithm.CRFLite
{
public class Tagger
{
public List<List<string>> x_;
public Node[,] node_; //Node matrix
public short ysize_;
public short word_num; //the number of tokens need to be labeled
public double Z_; //概率值
public double cost_; //The path cost
public short[] result_;
public List<long[]> feature_cache_;
//Calculate the cost of each path. It's used for finding the best or N-best result
public int viterbi()
{
var bestc = double.MinValue;
Node bestNode = null;
for (var i = 0; i < word_num; ++i)
{
for (var j = 0; j < ysize_; ++j)
{
bestc = double.MinValue;
bestNode = null;
var node_i_j = node_[i, j];
for (int index = 0; index < node_i_j.lpathList.Count; ++index)
{
var p = node_i_j.lpathList[index];
var cost = p.lnode.bestCost + p.cost + node_i_j.cost;
if (cost > bestc)
{
bestc = cost;
bestNode = p.lnode;
}
}
node_i_j.prev = bestNode;
node_i_j.bestCost = bestNode != null ? bestc : node_i_j.cost;
}
}
bestc = double.MinValue;
bestNode = null;
var s = (short)(word_num - 1);
for (short j = 0; j < ysize_; ++j)
{
if (bestc < node_[s, j].bestCost)
{
bestNode = node_[s, j];
bestc = node_[s, j].bestCost;
}
}
var n = bestNode;
while (n != null)
{
result_[n.x] = n.y;
n = n.prev;
}
cost_ = -node_[s, result_[s]].bestCost;
return BaseUtils.RETURN_SUCCESS;
}
private void calcAlpha(int m, int n)
{
var nd = node_[m, n];
nd.alpha = 0.0;
var i = 0;
for (int index = 0; index < nd.lpathList.Count; index++)
{
var p = nd.lpathList[index];
nd.alpha = BaseUtils.logsumexp(nd.alpha, p.cost + p.lnode.alpha, (i == 0));
i++;
}
nd.alpha += nd.cost;
}
private void calcBeta(int m, int n)
{
var nd = node_[m, n];
nd.beta = 0.0f;
if (m + 1 < word_num)
{
var i = 0;
for (int index = 0; index < nd.rpathList.Count; index++)
{
var p = nd.rpathList[index];
nd.beta = BaseUtils.logsumexp(nd.beta, p.cost + p.rnode.beta, (i == 0));
i++;
}
}
nd.beta += nd.cost;
}
public void forwardbackward()
{
for (int i = 0, k = word_num - 1; i < word_num; ++i, --k)
{
for (var j = 0; j < ysize_; ++j)
{
calcAlpha(i, j);
calcBeta(k, j);
}
}
Z_ = 0.0;
for (var j = 0; j < ysize_; ++j)
{
Z_ = BaseUtils.logsumexp(Z_, node_[0, j].beta, j == 0);
}
}
//Assign feature ids to node and path
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int RebuildFeatures()
{
var fid = 0;
for (short cur = 0; cur < word_num; ++cur)
{
for (short i = 0; i < ysize_; ++i)
{
node_[cur, i].fid = fid;
if (cur > 0)
{
Node previousNode = node_[cur - 1, i];
for (int index = 0; index < previousNode.rpathList.Count; ++index)
{
Path path = previousNode.rpathList[index];
path.fid = fid + word_num - 1;
}
}
}
++fid;
}
return 0;
}
}
}