SHOGUN  v3.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
FactorType.cpp
Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 2013 Shell Hu
00008  * Copyright (C) 2013 Shell Hu
00009  */
00010 
00011 #include <shogun/structure/FactorType.h>
00012 #include <shogun/base/Parameter.h>
00013 
00014 using namespace shogun;
00015 
00016 CFactorType::CFactorType() : CSGObject()
00017 {
00018     SG_UNSTABLE("CFactorType::CFactorType()", "\n");
00019 
00020     init();
00021 }
00022 
00023 CFactorType::CFactorType(
00024     int32_t id,
00025     SGVector<int32_t> card,
00026     SGVector<float64_t> w)
00027     : CSGObject()
00028 {
00029     init();
00030     m_type_id = id;
00031     m_w = w;
00032     m_cards = card;
00033     init_card();
00034 
00035     ASSERT(m_cards.size() > 0);
00036 
00037     if (m_w.size() == 0)
00038     {
00039         m_data_size = m_num_assignments;
00040     }
00041     else
00042     {
00043         ASSERT(m_w.size() % m_num_assignments == 0);
00044         m_data_size = m_w.size() / m_num_assignments;
00045     }
00046 }
00047 
00048 CFactorType::~CFactorType()
00049 {
00050 }
00051 
00052 void CFactorType::init()
00053 {
00054     SG_ADD(&m_type_id, "type_id", "Factor type name", MS_NOT_AVAILABLE);
00055     SG_ADD(&m_cards, "cards", "Cardinalities", MS_NOT_AVAILABLE);
00056     SG_ADD(&m_cumprod_cards, "cumprod_cards", "Cumulative product of cardinalities", MS_NOT_AVAILABLE);
00057     SG_ADD(&m_num_assignments, "num_assignments", "Number of variable configurations", MS_NOT_AVAILABLE);
00058     SG_ADD(&m_w, "w", "Factor parameters", MS_NOT_AVAILABLE);
00059     SG_ADD(&m_data_size, "data_size", "Size of data vector", MS_NOT_AVAILABLE);
00060 
00061     m_type_id = 0;
00062     m_data_size = 0;
00063     m_num_assignments = 0;
00064 }
00065 
00066 int32_t CFactorType::get_type_id() const
00067 {
00068     return m_type_id;
00069 }
00070 
00071 void CFactorType::set_type_id(int32_t id)
00072 {
00073     m_type_id = id;
00074 }
00075 
00076 SGVector<float64_t> CFactorType::get_w()
00077 {
00078     return m_w;
00079 }
00080 
00081 const SGVector<float64_t> CFactorType::get_w() const
00082 {
00083     return m_w;
00084 }
00085 
00086 void CFactorType::set_w(SGVector<float64_t> w)
00087 {
00088     m_w = w.clone();
00089 }
00090 
00091 int32_t CFactorType::get_w_dim() const
00092 {
00093     return m_w.size();
00094 }
00095 
00096 const SGVector<int32_t> CFactorType::get_cardinalities() const
00097 {
00098     return m_cards;
00099 }
00100 
00101 void CFactorType::set_cardinalities(SGVector<int32_t> cards)
00102 {
00103     m_cards = cards.clone();
00104     init_card();
00105     if (m_w.size() == 0)
00106     {
00107         m_data_size = m_num_assignments;
00108     }
00109     else
00110     {
00111         ASSERT(m_w.size() % m_num_assignments == 0);
00112         m_data_size = m_w.size() / m_num_assignments;
00113     }
00114 }
00115 
00116 int32_t CFactorType::get_num_vars()
00117 {
00118     return m_cards.size();
00119 }
00120 
00121 int32_t CFactorType::get_num_assignments() const
00122 {
00123     return m_num_assignments;
00124 }
00125 
00126 void CFactorType::init_card()
00127 {
00128     m_num_assignments = 1;
00129     m_cumprod_cards.resize_vector(m_cards.size());
00130     for (int32_t n = 0; n < m_cards.size(); ++n)
00131     {
00132         m_cumprod_cards[n] = m_num_assignments;
00133         m_num_assignments *= m_cards[n];
00134     }
00135 }
00136 
00137 CTableFactorType::CTableFactorType()
00138     : CFactorType()
00139 {
00140 }
00141 
00142 CTableFactorType::CTableFactorType(
00143     int32_t id,
00144     SGVector<int32_t> card,
00145     SGVector<float64_t> w)
00146     : CFactorType(id, card, w)
00147 {
00148 }
00149 
00150 CTableFactorType::~CTableFactorType()
00151 {
00152 }
00153 
00154 int32_t CTableFactorType::state_from_index(int32_t ei, int32_t var_index) const
00155 {
00156     ASSERT(var_index < get_cardinalities().size());
00157     return ((ei / m_cumprod_cards[var_index]) % m_cards[var_index]);
00158 }
00159 
00160 SGVector<int32_t> CTableFactorType::assignment_from_index(int32_t ei) const
00161 {
00162     SGVector<int32_t> assig(get_cardinalities().size());
00163     for (int32_t vi = 0; vi < get_cardinalities().size(); ++vi)
00164         assig[vi] = state_from_index(ei, vi);
00165 
00166     return assig;
00167 }
00168 
00169 int32_t CTableFactorType::index_from_assignment(const SGVector<int32_t> assig) const
00170 {
00171     ASSERT(assig.size() == get_cardinalities().size());
00172     int32_t index = 0;
00173     for (int32_t vi = 0; vi < get_cardinalities().size(); ++vi)
00174         index += assig[vi] * m_cumprod_cards[vi];
00175 
00176     return index;
00177 }
00178 
00179 int32_t CTableFactorType::index_from_new_state(
00180     int32_t old_ei, int32_t var_index, int32_t var_state) const
00181 {
00182     ASSERT(var_index < get_cardinalities().size());
00183     ASSERT(var_state < get_cardinalities()[var_index]);
00184     // subtract old contribution and add new contribution from new state
00185     return (old_ei - state_from_index(old_ei, var_index) * m_cumprod_cards[var_index]
00186         + var_state * m_cumprod_cards[var_index]);
00187 }
00188 
00189 int32_t CTableFactorType::index_from_universe_assignment(
00190     const SGVector<int32_t> assig,
00191     const SGVector<int32_t> var_index) const
00192 {
00193     ASSERT(var_index.size() == m_cards.size());
00194     int32_t index = 0;
00195     for (int32_t vi = 0; vi < var_index.size(); vi++)
00196     {
00197         int32_t cur_var = var_index[vi];
00198         ASSERT(assig[cur_var] <= m_cards[vi]);
00199         index += assig[cur_var] * m_cumprod_cards[vi];
00200     }
00201     ASSERT(index < m_num_assignments);
00202     return index;
00203 }
00204 
00205 void CTableFactorType::compute_energies(
00206     const SGVector<float64_t> factor_data,
00207     SGVector<float64_t>& energies) const
00208 {
00209     ASSERT(energies.size() == m_num_assignments);
00210 
00211     if (factor_data.size() == 0)
00212     {
00213         ASSERT(m_w.size() == m_num_assignments);
00214         energies = m_w.clone();
00215     }
00216     else if (m_w.size() == 0)
00217     {
00218         ASSERT(m_data_size == m_num_assignments);
00219         ASSERT(factor_data.size() == m_data_size);
00220         energies = factor_data.clone();
00221     }
00222     else
00223     {
00224         ASSERT(m_data_size * m_num_assignments == m_w.size());
00225         ASSERT(m_data_size == factor_data.size());
00226         for (int32_t ei = 0; ei < m_num_assignments; ++ei)
00227         {
00228             float64_t energy_cur = 0.0;
00229             for (int32_t di = 0; di < m_data_size; ++di)
00230                 energy_cur += factor_data[di] * m_w[di + ei*m_data_size];
00231 
00232             energies[ei] = energy_cur;
00233         }
00234     }
00235 }
00236 
00237 void CTableFactorType::compute_energies(
00238     const SGSparseVector<float64_t> factor_data_sparse,
00239     SGVector<float64_t>& energies) const
00240 {
00241     ASSERT(energies.size() == m_num_assignments);
00242     ASSERT(m_data_size >= factor_data_sparse.num_feat_entries);
00243 
00244     if (factor_data_sparse.num_feat_entries == 0)
00245     {
00246         ASSERT(m_num_assignments == m_w.size());
00247         energies = m_w.clone();
00248     }
00249     else if (m_w.size() == 0)
00250     {
00251         ASSERT(m_num_assignments == m_data_size);
00252         energies.zero();
00253         SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
00254         for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n)
00255             energies[data_ptr[n].feat_index] = data_ptr[n].entry;
00256     }
00257     else
00258     {
00259         ASSERT((m_data_size * m_num_assignments) == m_w.size());
00260         SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
00261 
00262         for (int32_t ei = 0; ei < m_num_assignments; ++ei)
00263         {
00264             float64_t energy_cur = 0.0;
00265             for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n)
00266             {
00267                 energy_cur += data_ptr[n].entry
00268                     * m_w[data_ptr[n].feat_index + ei*m_data_size];
00269             }
00270             energies[ei] = energy_cur;
00271         }
00272     }
00273 }
00274 
00275 void CTableFactorType::compute_gradients(
00276     const SGVector<float64_t> factor_data,
00277     const SGVector<float64_t> marginals,
00278     SGVector<float64_t>& parameter_gradient,
00279     double mult) const
00280 {
00281     if (factor_data.size() == 0)
00282     {
00283         ASSERT(m_num_assignments == parameter_gradient.size());
00284         // Parameters are a simple table, gradient is simply the marginal
00285         for (int32_t ei = 0; ei < m_num_assignments; ++ei)
00286             parameter_gradient[ei] = mult * marginals[ei];
00287     }
00288     else if (m_w.size() == 0)
00289     {
00290         SG_ERROR("%s::compute_gradients(): no parameters for this factor type.\n", get_name());
00291     }
00292     else
00293     {
00294         ASSERT((m_data_size * m_num_assignments) == parameter_gradient.size());
00295         ASSERT(m_data_size == factor_data.size());
00296         // Perform tensor outer product
00297         for (int32_t ei = 0; ei < m_num_assignments; ++ei)
00298         {
00299             for (int32_t di = 0; di < m_data_size; ++di)
00300             {
00301                 parameter_gradient[di + ei*m_data_size] +=
00302                     mult * factor_data[di] * marginals[ei];
00303             }
00304         }
00305     }
00306 }
00307 
00308 void CTableFactorType::compute_gradients(
00309     const SGSparseVector<float64_t> factor_data_sparse,
00310     const SGVector<float64_t> marginals,
00311     SGVector<float64_t>& parameter_gradient,
00312     double mult) const
00313 {
00314     // The first two cases are the same as for the non-sparse case
00315     if (factor_data_sparse.num_feat_entries == 0)
00316     {
00317         ASSERT(m_num_assignments == parameter_gradient.size());
00318         // Parameters are a simple table, gradient is simply the marginal
00319         for (int32_t ei = 0; ei < m_num_assignments; ++ei)
00320             parameter_gradient[ei] = mult * marginals[ei];
00321     }
00322     else if (m_w.size() == 0)
00323     {
00324         SG_ERROR("%s::compute_gradients(): no parameters for this factor type.\n", get_name());
00325     }
00326     else
00327     {
00328         ASSERT((m_data_size * m_num_assignments) == parameter_gradient.size());
00329         SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
00330 
00331         // Perform tensor outer product
00332         for (int32_t ei = 0; ei < m_num_assignments; ++ei) {
00333             for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n) {
00334                 int32_t di = data_ptr[n].feat_index;
00335                 parameter_gradient[di + ei*m_data_size] +=
00336                     mult * data_ptr[n].entry * marginals[ei];
00337             }
00338         }
00339     }
00340 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation