| 232 | return score |
| 233 | |
| 234 | def _viterbi_decode(self, feats): |
| 235 | backpointers = [] |
| 236 | |
| 237 | # Initialize the viterbi variables in log space |
| 238 | init_vvars = torch.full((1, self.tagset_size), -10000.) |
| 239 | init_vvars[0][self.tag_to_ix[START_TAG]] = 0 |
| 240 | |
| 241 | # forward_var at step i holds the viterbi variables for step i-1 |
| 242 | forward_var = init_vvars |
| 243 | for feat in feats: |
| 244 | bptrs_t = [] # holds the backpointers for this step |
| 245 | viterbivars_t = [] # holds the viterbi variables for this step |
| 246 | |
| 247 | for next_tag in range(self.tagset_size): |
| 248 | # next_tag_var[i] holds the viterbi variable for tag i at the |
| 249 | # previous step, plus the score of transitioning |
| 250 | # from tag i to next_tag. |
| 251 | # We don't include the emission scores here because the max |
| 252 | # does not depend on them (we add them in below) |
| 253 | next_tag_var = forward_var + self.transitions[next_tag] |
| 254 | best_tag_id = argmax(next_tag_var) |
| 255 | bptrs_t.append(best_tag_id) |
| 256 | viterbivars_t.append(next_tag_var[0][best_tag_id].view(1)) |
| 257 | # Now add in the emission scores, and assign forward_var to the set |
| 258 | # of viterbi variables we just computed |
| 259 | forward_var = (torch.cat(viterbivars_t) + feat).view(1, -1) |
| 260 | backpointers.append(bptrs_t) |
| 261 | |
| 262 | # Transition to STOP_TAG |
| 263 | terminal_var = forward_var + self.transitions[self.tag_to_ix[STOP_TAG]] |
| 264 | best_tag_id = argmax(terminal_var) |
| 265 | path_score = terminal_var[0][best_tag_id] |
| 266 | |
| 267 | # Follow the back pointers to decode the best path. |
| 268 | best_path = [best_tag_id] |
| 269 | for bptrs_t in reversed(backpointers): |
| 270 | best_tag_id = bptrs_t[best_tag_id] |
| 271 | best_path.append(best_tag_id) |
| 272 | # Pop off the start tag (we dont want to return that to the caller) |
| 273 | start = best_path.pop() |
| 274 | assert start == self.tag_to_ix[START_TAG] # Sanity check |
| 275 | best_path.reverse() |
| 276 | return path_score, best_path |
| 277 | |
| 278 | def neg_log_likelihood(self, sentence, tags): |
| 279 | feats = self._get_lstm_features(sentence) |