void CFactorGraph::loss_augmentation(SGVector<int32_t> states_gt, SGVector<float64_t> loss) { if (loss.size() == 0) { loss.resize_vector(states_gt.size()); SGVector<float64_t>::fill_vector(loss.vector, loss.vlen, 1.0 / states_gt.size()); } int32_t num_vars = states_gt.size(); ASSERT(num_vars == loss.size()); SGVector<int32_t> var_flags(num_vars); var_flags.zero(); // augment loss to incorrect states in the first factor containing the variable // since += L_i for each variable if it takes wrong state ever // TODO: augment unary factors for (int32_t fi = 0; fi < m_factors->get_num_elements(); ++fi) { CFactor* fac = dynamic_cast<CFactor*>(m_factors->get_element(fi)); SGVector<int32_t> vars = fac->get_variables(); for (int32_t vi = 0; vi < vars.size(); vi++) { int32_t vv = vars[vi]; ASSERT(vv < num_vars); if (var_flags[vv]) continue; SGVector<float64_t> energies = fac->get_energies(); for (int32_t ei = 0; ei < energies.size(); ei++) { CTableFactorType* ftype = fac->get_factor_type(); int32_t vstate = ftype->state_from_index(ei, vi); SG_UNREF(ftype); if (states_gt[vv] == vstate) continue; // -delta(y_n, y_i_n) fac->set_energy(ei, energies[ei] - loss[vv]); } var_flags[vv] = 1; } SG_UNREF(fac); } // make sure all variables have been checked int32_t min_var = SGVector<int32_t>::min(var_flags.vector, var_flags.vlen); ASSERT(min_var == 1); }
SGVector< float64_t > CFactorGraphModel::get_joint_feature_vector(int32_t feat_idx, CStructuredData* y) { // factor graph instance CFactorGraphFeatures* mf = CFactorGraphFeatures::obtain_from_generic(m_features); CFactorGraph* fg = mf->get_sample(feat_idx); // ground truth states CFactorGraphObservation* fg_states = CFactorGraphObservation::obtain_from_generic(y); SGVector<int32_t> states = fg_states->get_data(); // initialize psi SGVector<float64_t> psi(get_dim()); psi.zero(); // construct unnormalized psi CDynamicObjectArray* facs = fg->get_factors(); for (int32_t fi = 0; fi < facs->get_num_elements(); ++fi) { CFactor* fac = dynamic_cast<CFactor*>(facs->get_element(fi)); CTableFactorType* ftype = fac->get_factor_type(); int32_t id = ftype->get_type_id(); SGVector<int32_t> w_map = get_params_mapping(id); ASSERT(w_map.size() == ftype->get_w_dim()); SGVector<float64_t> dat = fac->get_data(); int32_t dat_size = dat.size(); ASSERT(w_map.size() == dat_size * ftype->get_num_assignments()); int32_t ei = ftype->index_from_universe_assignment(states, fac->get_variables()); for (int32_t di = 0; di < dat_size; di++) psi[w_map[ei*dat_size + di]] += dat[di]; SG_UNREF(ftype); SG_UNREF(fac); } // negation (-E(x,y) = <w,phi(x,y)>) psi.scale(-1.0); SG_UNREF(facs); SG_UNREF(fg); return psi; }
void CFactorGraph::connect_components() { if (m_dset->get_connected()) return; // need to be reset once factor graph is updated m_dset->make_sets(); bool flag = false; for (int32_t fi = 0; fi < m_factors->get_num_elements(); ++fi) { CFactor* fac = dynamic_cast<CFactor*>(m_factors->get_element(fi)); SGVector<int32_t> vars = fac->get_variables(); int32_t r0 = m_dset->find_set(vars[0]); for (int32_t vi = 1; vi < vars.size(); vi++) { // for two nodes in a factor, should be an edge between them // but this time link() isn't performed, if they are linked already // means there is another path connected them, so cycle detected int32_t ri = m_dset->find_set(vars[vi]); if (r0 == ri) { flag = true; continue; } r0 = m_dset->link_set(r0, ri); } SG_UNREF(fac); } m_has_cycle = flag; m_dset->set_connected(true); }