SHOGUN  3.2.1
 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>
14 
15 using namespace shogun;
16 
18 {
19  SG_UNSTABLE("CFactorType::CFactorType()", "\n");
20 
21  init();
22 }
23 
25  int32_t id,
26  SGVector<int32_t> card,
28  : CSGObject()
29 {
30  init();
31  m_type_id = id;
32  m_w = w;
33  m_cards = card;
34  init_card();
35 
36  ASSERT(m_cards.size() > 0);
37 
38  if (m_w.size() == 0)
39  {
41  }
42  else
43  {
44  ASSERT(m_w.size() % m_num_assignments == 0);
46  }
47 }
48 
50 {
51 }
52 
53 void CFactorType::init()
54 {
55  SG_ADD(&m_type_id, "type_id", "Factor type name", MS_NOT_AVAILABLE);
56  SG_ADD(&m_cards, "cards", "Cardinalities", MS_NOT_AVAILABLE);
57  SG_ADD(&m_cumprod_cards, "cumprod_cards", "Cumulative product of cardinalities", MS_NOT_AVAILABLE);
58  SG_ADD(&m_num_assignments, "num_assignments", "Number of variable configurations", MS_NOT_AVAILABLE);
59  SG_ADD(&m_w, "w", "Factor parameters", MS_NOT_AVAILABLE);
60  SG_ADD(&m_data_size, "data_size", "Size of data vector", MS_NOT_AVAILABLE);
61 
62  m_type_id = 0;
63  m_data_size = 0;
65 }
66 
67 int32_t CFactorType::get_type_id() const
68 {
69  return m_type_id;
70 }
71 
72 void CFactorType::set_type_id(int32_t id)
73 {
74  m_type_id = id;
75 }
76 
78 {
79  return m_w;
80 }
81 
83 {
84  return m_w;
85 }
86 
88 {
89  m_w = w.clone();
90 }
91 
92 int32_t CFactorType::get_w_dim() const
93 {
94  return m_w.size();
95 }
96 
98 {
99  return m_cards;
100 }
101 
103 {
104  m_cards = cards.clone();
105  init_card();
106  if (m_w.size() == 0)
107  {
109  }
110  else
111  {
112  ASSERT(m_w.size() % m_num_assignments == 0);
114  }
115 }
116 
118 {
119  return m_cards.size();
120 }
121 
123 {
124  return m_num_assignments;
125 }
126 
128 {
129  m_num_assignments = 1;
131  for (int32_t n = 0; n < m_cards.size(); ++n)
132  {
135  }
136 }
137 
139  : CFactorType()
140 {
141 }
142 
144  int32_t id,
145  SGVector<int32_t> card,
147  : CFactorType(id, card, w)
148 {
149 }
150 
152 {
153 }
154 
155 int32_t CTableFactorType::state_from_index(int32_t ei, int32_t var_index) const
156 {
157  ASSERT(var_index < get_cardinalities().size());
158  return ((ei / m_cumprod_cards[var_index]) % m_cards[var_index]);
159 }
160 
162 {
163  SGVector<int32_t> assig(get_cardinalities().size());
164  for (int32_t vi = 0; vi < get_cardinalities().size(); ++vi)
165  assig[vi] = state_from_index(ei, vi);
166 
167  return assig;
168 }
169 
171 {
172  ASSERT(assig.size() == get_cardinalities().size());
173  int32_t index = 0;
174  for (int32_t vi = 0; vi < get_cardinalities().size(); ++vi)
175  index += assig[vi] * m_cumprod_cards[vi];
176 
177  return index;
178 }
179 
181  int32_t old_ei, int32_t var_index, int32_t var_state) const
182 {
183  ASSERT(var_index < get_cardinalities().size());
184  ASSERT(var_state < get_cardinalities()[var_index]);
185  // subtract old contribution and add new contribution from new state
186  return (old_ei - state_from_index(old_ei, var_index) * m_cumprod_cards[var_index]
187  + var_state * m_cumprod_cards[var_index]);
188 }
189 
191  const SGVector<int32_t> assig,
192  const SGVector<int32_t> var_index) const
193 {
194  ASSERT(var_index.size() == m_cards.size());
195  int32_t index = 0;
196  for (int32_t vi = 0; vi < var_index.size(); vi++)
197  {
198  int32_t cur_var = var_index[vi];
199  ASSERT(assig[cur_var] <= m_cards[vi]);
200  index += assig[cur_var] * m_cumprod_cards[vi];
201  }
202  ASSERT(index < m_num_assignments);
203  return index;
204 }
205 
207  const SGVector<float64_t> factor_data,
208  SGVector<float64_t>& energies) const
209 {
210  ASSERT(energies.size() == m_num_assignments);
211 
212  if (factor_data.size() == 0)
213  {
215  energies = m_w.clone();
216  }
217  else if (m_w.size() == 0)
218  {
220  ASSERT(factor_data.size() == m_data_size);
221  energies = factor_data.clone();
222  }
223  else
224  {
226  ASSERT(m_data_size == factor_data.size());
227  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
228  {
229  float64_t energy_cur = 0.0;
230  for (int32_t di = 0; di < m_data_size; ++di)
231  energy_cur += factor_data[di] * m_w[di + ei*m_data_size];
232 
233  energies[ei] = energy_cur;
234  }
235  }
236 }
237 
239  const SGSparseVector<float64_t> factor_data_sparse,
240  SGVector<float64_t>& energies) const
241 {
242  ASSERT(energies.size() == m_num_assignments);
243  ASSERT(m_data_size >= factor_data_sparse.num_feat_entries);
244 
245  if (factor_data_sparse.num_feat_entries == 0)
246  {
248  energies = m_w.clone();
249  }
250  else if (m_w.size() == 0)
251  {
253  energies.zero();
254  SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
255  for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n)
256  energies[data_ptr[n].feat_index] = data_ptr[n].entry;
257  }
258  else
259  {
261  SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
262 
263  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
264  {
265  float64_t energy_cur = 0.0;
266  for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n)
267  {
268  energy_cur += data_ptr[n].entry
269  * m_w[data_ptr[n].feat_index + ei*m_data_size];
270  }
271  energies[ei] = energy_cur;
272  }
273  }
274 }
275 
277  const SGVector<float64_t> factor_data,
278  const SGVector<float64_t> marginals,
279  SGVector<float64_t>& parameter_gradient,
280  double mult) const
281 {
282  if (factor_data.size() == 0)
283  {
284  ASSERT(m_num_assignments == parameter_gradient.size());
285  // Parameters are a simple table, gradient is simply the marginal
286  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
287  parameter_gradient[ei] = mult * marginals[ei];
288  }
289  else if (m_w.size() == 0)
290  {
291  SG_ERROR("%s::compute_gradients(): no parameters for this factor type.\n", get_name());
292  }
293  else
294  {
295  ASSERT((m_data_size * m_num_assignments) == parameter_gradient.size());
296  ASSERT(m_data_size == factor_data.size());
297  // Perform tensor outer product
298  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
299  {
300  for (int32_t di = 0; di < m_data_size; ++di)
301  {
302  parameter_gradient[di + ei*m_data_size] +=
303  mult * factor_data[di] * marginals[ei];
304  }
305  }
306  }
307 }
308 
310  const SGSparseVector<float64_t> factor_data_sparse,
311  const SGVector<float64_t> marginals,
312  SGVector<float64_t>& parameter_gradient,
313  double mult) const
314 {
315  // The first two cases are the same as for the non-sparse case
316  if (factor_data_sparse.num_feat_entries == 0)
317  {
318  ASSERT(m_num_assignments == parameter_gradient.size());
319  // Parameters are a simple table, gradient is simply the marginal
320  for (int32_t ei = 0; ei < m_num_assignments; ++ei)
321  parameter_gradient[ei] = mult * marginals[ei];
322  }
323  else if (m_w.size() == 0)
324  {
325  SG_ERROR("%s::compute_gradients(): no parameters for this factor type.\n", get_name());
326  }
327  else
328  {
329  ASSERT((m_data_size * m_num_assignments) == parameter_gradient.size());
330  SGSparseVectorEntry<float64_t>* data_ptr = factor_data_sparse.features;
331 
332  // Perform tensor outer product
333  for (int32_t ei = 0; ei < m_num_assignments; ++ei) {
334  for (int32_t n = 0; n < factor_data_sparse.num_feat_entries; ++n) {
335  int32_t di = data_ptr[n].feat_index;
336  parameter_gradient[di + ei*m_data_size] +=
337  mult * data_ptr[n].entry * marginals[ei];
338  }
339  }
340  }
341 }

SHOGUN Machine Learning Toolbox - Documentation