void crf_context_marginals(crf_context_t *self) { const size_t T = self->num_items; const size_t L = self->num_labels; double *scale = self->scale_factor->a; /* Compute the model expectations of states. p(t,i) = fwd[t][i] * bwd[t][i] / norm = (1. / C[t]) * fwd'[t][i] * bwd'[t][i] */ int t; for (t = 0; t < T; t++) { double *forward = alpha_score(self, t); double *backward = beta_score(self, t); double *prob = state_mexp(self, t); double_array_raw_copy(prob, forward, L); double_array_mul_array(prob, backward, L); double scale_t = scale[t]; double_array_div(prob, scale_t, L); } /* Compute the model expectations of transitions. p(t,i,t+1,j) = fwd[t][i] * state[t+1][j] * edge[i][j] * state_edge[t+1][i][j] * bwd[t+1][j] / norm = (fwd'[t][i] / (C[0] ... C[t])) * state[t+1][j] * edge[i][j] * state_edge[t+1][i][j] * (bwd'[t+1][j] / (C[t+1] ... C[T-1])) * (C[0] * ... * C[T-1]) = fwd'[t][i] * state[t+1][j] * edge[i][j] * state_edge[t+1][i][j] * bwd'[t+1][j] The model expectation of a transition (i -> j) is the sum of the marginal probabilities p(t,i,t+1,j) over t. */ for (t = 0; t < T - 1; t++) { double *forward = alpha_score(self, t); double *state = exp_state_score(self, t + 1); double *backward = beta_score(self, t + 1); double *row = self->row->a; double_array_raw_copy(row, backward, L); double_array_mul_array(row, state, L); for (int i = 0; i < L; i++) { double *edge = exp_trans_score(self, i); double *edge_state = exp_state_trans_score(self, t + 1, i); double *prob = state_trans_mexp(self, t + 1, i); for (int j = 0; j < L; j++) { prob[j] += forward[i] * edge[j] * edge_state[j] * row[j]; } } } }
double crf_context_marginal_path(crf_context_t *self, const uint32_t *path, size_t begin, size_t end) { /* Compute the marginal probability of a (partial) path. a = path[begin], b = path[begin+1], ..., y = path[end-2], z = path[end-1] fwd[begin][a] = (fwd'[begin][a] / (C[0] ... C[begin]) bwd[end-1][z] = (bwd'[end-1][z] / (C[end-1] ... C[T-1])) norm = 1 / (C[0] * ... * C[T-1]) p(a, b, ..., z) = fwd[begin][a] * state_edge[begin+1][a * L + b] * edge[a][b] * state[begin+1][b] * ... * edge[y][z] * state_edge[end-1][y][z] * state[end-1][z] * bwd[end-1][z] / norm = fwd'[begin][a] * state_edge[begin+1][a * L + b] * edge[a][b] * state[begin+1][b] * ... * edge[y][z] * state_edge[end-1][y][z] * state[end-1][z] * bwd'[end-1][z] * (C[begin+1] * ... * C[end-2]) */ double *forward = alpha_score(self, begin); double *backward = beta_score(self, end - 1); double prob = forward[path[begin]] * backward[path[end]]; for (int t = begin; t < end - 1; t++) { double *state = exp_state_score(self, t + 1); double *edge = exp_trans_score(self, (size_t)path[t]); double *edge_state = exp_state_trans_score(self, t + 1, (size_t)path[t]); prob *= (edge[path[t+1]] * edge_state[path[t + 1]] * state[path[t + 1]] * self->scale_factor->a[t]); } return prob; }
void crf_context_beta_score(crf_context_t *self) { double *cur = NULL; double *row = self->row->a; double *row_trans = self->row_trans->a; const double *next = NULL; const double *state = NULL; const double *state_trans = NULL; const double *trans = NULL; const size_t T = self->num_items; const size_t L = self->num_labels; double *scale = self->scale_factor->a; /* Compute the beta scores at (T-1, *). */ cur = beta_score(self, T - 1); double scale_t = scale[T - 1]; double_array_set(cur, scale_t, L); /* Compute the beta scores at (t, *). */ for (ssize_t t = T - 2; t >= 0; t--) { cur = beta_score(self, t); next = beta_score(self, t + 1); state = exp_state_score(self, t + 1); double_array_raw_copy(row, next, L); double_array_mul_array(row, state, L); /* Compute the beta score at (t, i). */ for (int i = 0; i < L; i++) { trans = exp_trans_score(self, i); double_array_raw_copy(row_trans, row, L); double_array_mul_array(row_trans, trans, L); state_trans = exp_state_trans_score(self, t + 1, i); cur[i] = double_array_dot(state_trans, row_trans, L); } scale_t = scale[t]; double_array_mul(cur, scale_t, L); } }
double crf_context_marginal_point(crf_context_t *self, uint32_t l, uint32_t t) { double *forward = alpha_score(self, t); double *backward = beta_score(self, t); return forward[l] * backward[l] / self->scale_factor->a[t]; }
double insertion_score(glam2_scorer *s, int insert_count, int no_insert_count) { return beta_score(&s->i_prior, insert_count, no_insert_count); }
double deletion_score(glam2_scorer *s, int delete_count, int no_delete_count) { return beta_score(&s->d_prior, delete_count, no_delete_count); }