SHOGUN  v3.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FactorType.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 2013 Shell Hu
8  * Copyright (C) 2013 Shell Hu
9  */
10 
12 #include <shogun/base/Parameter.h>
13 
14 using namespace shogun;
15 
17 {
18  SG_UNSTABLE("CFactorType::CFactorType()", "\n");
19 
20  init();
21 }
22 
24  int32_t id,
25  SGVector<int32_t> card,
27  : CSGObject()
28 {
29  init();
30  m_type_id = id;
31  m_w = w;
32  m_cards = card;
33  init_card();
34 
35  ASSERT(m_cards.size() > 0);
36 
37  if (m_w.size() == 0)
38  {
40  }
41  else
42  {
43  ASSERT(m_w.size() % m_num_assignments == 0);
45  }
46 }
47 
49 {
50 }
51 
52 void CFactorType::init()
53 {
54  SG_ADD(&m_type_id, "type_id", "Factor type name", MS_NOT_AVAILABLE);
55  SG_ADD(&m_cards, "cards", "Cardinalities", MS_NOT_AVAILABLE);
56  SG_ADD(&m_cumprod_cards, "cumprod_cards", "Cumulative product of cardinalities", MS_NOT_AVAILABLE);
57  SG_ADD(&m_num_assignments, "num_assignments", "Number of variable configurations", MS_NOT_AVAILABLE);
58  SG_ADD(&m_w, "w", "Factor parameters", MS_NOT_AVAILABLE);
59  SG_ADD(&m_data_size, "data_size", "Size of data vector", MS_NOT_AVAILABLE);
60 
61  m_type_id = 0;
62  m_data_size = 0;
64 }
65 
66 int32_t CFactorType::get_type_id() const
67 {
68  return m_type_id;
69 }
70 
71 void CFactorType::set_type_id(int32_t id)
72 {
73  m_type_id = id;
74 }
75 
77 {
78  return m_w;
79 }
80 
82 {
83  return m_w;
84 }
85 
87 {
88  m_w = w.clone();
89 }
90 
91 int32_t CFactorType::get_w_dim() const
92 {
93  return m_w.size();
94 }
95 
97 {
98  return m_cards;
99 }
100 
102 {
103  m_cards = cards.clone();
104  init_card();
105  if (m_w.size() == 0)
106  {
108  }
109  else
110  {
111  ASSERT(m_w.size() % m_num_assignments == 0);
113  }
114 }
115 
117 {
118  return m_cards.size();
119 }
120 
122 {
123  return m_num_assignments;
124 }
125 
127 {
128  m_num_assignments = 1;
130  for (int32_t n = 0; n < m_cards.size(); ++n)
131  {
134  }
135 }
136 
138  : CFactorType()
139 {
140 }
141 
143  int32_t id,
144  SGVector<int32_t> card,
146  : CFactorType(id, card, w)
147 {
148 }
149 
151 {
152 }
153 
154 int32_t CTableFactorType::state_from_index(int32_t ei, int32_t var_index) const
155 {
156  ASSERT(var_index < get_cardinalities().size());
157  return ((ei / m_cumprod_cards[var_index]) % m_cards[var_index]);
158 }
159 
161 {
162  SGVector<int32_t> assig(get_cardinalities().size());
163  for (int32_t vi = 0; vi < get_cardinalities().size(); ++vi)
164  assig[vi] = state_from_index(ei, vi);
165 
166  return assig;
167 }
168 
170 {
171  ASSERT(assig.size() == get_cardinalities().size());
172  int32_t index = 0;
173  for (int32_t vi = 0; vi < get_cardinalities().size(); ++vi)
174  index += assig[vi] * m_cumprod_cards[vi];
175 
176  return index;
177 }
178 
180  int32_t old_ei, int32_t var_index, int32_t var_state) const
181 {
182  ASSERT(var_index < get_cardinalities().size());
183  ASSERT(var_state < get_cardinalities()[var_index]);
184  // subtract old contribution and add new contribution from new state
185  return (old_ei - state_from_index(old_ei, var_index) * m_cumprod_cards[var_index]
186  + var_state * m_cumprod_cards[var_index]);
187 }
188 
190  const SGVector<int32_t> assig,
191  const SGVector<int32_t> var_index) const
192 {
193  ASSERT(var_index.size() == m_cards.size());
194  int32_t index = 0;
195  for (int32_t vi = 0; vi < var_index.size(); vi++)
196  {
197  int32_t cur_var = var_index[vi];
198  ASSERT(assig[cur_var] <= m_cards[vi]);
199  index += assig[cur_var] * m_cumprod_cards[vi];
200  }
201  ASSERT(index < m_num_assignments);
202  return index;
203 }
204 
206  const SGVector<float64_t> factor_data,
207  SGVector<float64_t>& energies) const
208 {
209  ASSERT(energies.size() == m_num_assignments);
210 
211  if (factor_data.size() == 0)
212  {
214  energies = m_w.clone();
215  }
216  else if (m_w.size() == 0)
217  {
219  ASSERT(factor_data.size() == m_data_size);
220  energies = factor_data.clone();
221  }
222  else
223  {
225  ASSERT(m_data_size == factor_data.size());
226  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
227  {
228  float64_t energy_cur = 0.0;
229  for (int32_t di = 0; di < m_data_size; ++di)
230  energy_cur += factor_data[di] * m_w[di + ei*m_data_size];
231 
232  energies[ei] = energy_cur;
233  }
234  }
235 }
236 
238  const SGSparseVector<float64_t> factor_data_sparse,
239  SGVector<float64_t>& energies) const
240 {
241  ASSERT(energies.size() == m_num_assignments);
242  ASSERT(m_data_size >= factor_data_sparse.num_feat_entries);
243 
244  if (factor_data_sparse.num_feat_entries == 0)
245  {
247  energies = m_w.clone();
248  }
249  else if (m_w.size() == 0)
250  {
252  energies.zero();
253  SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
254  for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n)
255  energies[data_ptr[n].feat_index] = data_ptr[n].entry;
256  }
257  else
258  {
260  SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
261 
262  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
263  {
264  float64_t energy_cur = 0.0;
265  for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n)
266  {
267  energy_cur += data_ptr[n].entry
268  * m_w[data_ptr[n].feat_index + ei*m_data_size];
269  }
270  energies[ei] = energy_cur;
271  }
272  }
273 }
274 
276  const SGVector<float64_t> factor_data,
277  const SGVector<float64_t> marginals,
278  SGVector<float64_t>& parameter_gradient,
279  double mult) const
280 {
281  if (factor_data.size() == 0)
282  {
283  ASSERT(m_num_assignments == parameter_gradient.size());
284  // Parameters are a simple table, gradient is simply the marginal
285  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
286  parameter_gradient[ei] = mult * marginals[ei];
287  }
288  else if (m_w.size() == 0)
289  {
290  SG_ERROR("%s::compute_gradients(): no parameters for this factor type.\n", get_name());
291  }
292  else
293  {
294  ASSERT((m_data_size * m_num_assignments) == parameter_gradient.size());
295  ASSERT(m_data_size == factor_data.size());
296  // Perform tensor outer product
297  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
298  {
299  for (int32_t di = 0; di < m_data_size; ++di)
300  {
301  parameter_gradient[di + ei*m_data_size] +=
302  mult * factor_data[di] * marginals[ei];
303  }
304  }
305  }
306 }
307 
309  const SGSparseVector<float64_t> factor_data_sparse,
310  const SGVector<float64_t> marginals,
311  SGVector<float64_t>& parameter_gradient,
312  double mult) const
313 {
314  // The first two cases are the same as for the non-sparse case
315  if (factor_data_sparse.num_feat_entries == 0)
316  {
317  ASSERT(m_num_assignments == parameter_gradient.size());
318  // Parameters are a simple table, gradient is simply the marginal
319  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
320  parameter_gradient[ei] = mult * marginals[ei];
321  }
322  else if (m_w.size() == 0)
323  {
324  SG_ERROR("%s::compute_gradients(): no parameters for this factor type.\n", get_name());
325  }
326  else
327  {
328  ASSERT((m_data_size * m_num_assignments) == parameter_gradient.size());
329  SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
330 
331  // Perform tensor outer product
332  for (int32_t ei = 0; ei < m_num_assignments; ++ei) {
333  for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n) {
334  int32_t di = data_ptr[n].feat_index;
335  parameter_gradient[di + ei*m_data_size] +=
336  mult * data_ptr[n].entry * marginals[ei];
337  }
338  }
339  }
340 }

SHOGUN Machine Learning Toolbox - Documentation