floatval_t crf1dc_score(crf1d_context_t* ctx, const int *labels) { int i, j, t; floatval_t ret = 0; const floatval_t *state = NULL, *cur = NULL, *trans = NULL; const int T = ctx->num_items; const int L = ctx->num_labels; /* Stay at (0, labels[0]). */ i = labels[0]; state = STATE_SCORE(ctx, 0); ret = state[i]; /* Loop over the rest of items. */ for (t = 1;t < T;++t) { j = labels[t]; trans = TRANS_SCORE(ctx, i); state = STATE_SCORE(ctx, t); /* Transit from (t-1, i) to (t, j). */ ret += trans[j]; ret += state[j]; i = j; } return ret; }
static void crf1dt_transition_score(crf1dt_t* crf1dt) { int i, r, fid; crf1dm_feature_t f; feature_refs_t edge; floatval_t *trans = NULL; crf1dm_t* model = crf1dt->model; crf1d_context_t* ctx = crf1dt->ctx; const int L = crf1dt->num_labels; /* Compute transition scores between two labels. */ for (i = 0;i < L;++i) { trans = TRANS_SCORE(ctx, i); crf1dm_get_labelref(model, i, &edge); for (r = 0;r < edge.num_features;++r) { /* Transition feature from #i to #(f->dst). */ fid = crf1dm_get_featureid(&edge, r); crf1dm_get_feature(model, fid, &f); trans[f.dst] = f.weight; } } }
floatval_t crf1dc_viterbi(crf1d_context_t* ctx, int *labels) { int i, j, t; int *back = NULL; floatval_t max_score, score, *cur = NULL; const floatval_t *prev = NULL, *state = NULL, *trans = NULL; const int T = ctx->num_items; const int L = ctx->num_labels; /* This function assumes state and trans scores to be in the logarithm domain. */ /* Compute the scores at (0, *). */ cur = ALPHA_SCORE(ctx, 0); state = STATE_SCORE(ctx, 0); for (j = 0;j < L;++j) { cur[j] = state[j]; } /* Compute the scores at (t, *). */ for (t = 1;t < T;++t) { prev = ALPHA_SCORE(ctx, t-1); cur = ALPHA_SCORE(ctx, t); state = STATE_SCORE(ctx, t); back = BACKWARD_EDGE_AT(ctx, t); /* Compute the score of (t, j). */ for (j = 0;j < L;++j) { max_score = -FLOAT_MAX; for (i = 0;i < L;++i) { /* Transit from (t-1, i) to (t, j). */ trans = TRANS_SCORE(ctx, i); score = prev[i] + trans[j]; /* Store this path if it has the maximum score. */ if (max_score < score) { max_score = score; /* Backward link (#t, #j) -> (#t-1, #i). */ back[j] = i; } } /* Add the state score on (t, j). */ cur[j] = max_score + state[j]; } } /* Find the node (#T, #i) that reaches EOS with the maximum score. */ max_score = -FLOAT_MAX; prev = ALPHA_SCORE(ctx, T-1); for (i = 0;i < L;++i) { if (max_score < prev[i]) { max_score = prev[i]; labels[T-1] = i; /* Tag the item #T. */ } } /* Tag labels by tracing the backward links. */ for (t = T-2;0 <= t;--t) { back = BACKWARD_EDGE_AT(ctx, t+1); labels[t] = back[labels[t+1]]; } /* Return the maximum score (without the normalization factor subtracted). */ return max_score; }