SHOGUN
v3.2.0
|
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 }