SHOGUN  v3.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TwoStateModel.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) 2012 Fernando José Iglesias García
8  * Copyright (C) 2012 Fernando José Iglesias García
9  */
10 
14 #include <shogun/structure/Plif.h>
15 
16 using namespace shogun;
17 
19 {
20  // The number of states in this state model is equal to four.
21  // Although parameters are learnt only for two of them, other
22  // two states (start and stop) are used
23  m_num_states = 4;
25 
28  for ( int32_t i = 0 ; i < m_num_states-1 ; ++i )
29  {
30  m_state_loss_mat(m_num_states-1, i) = 1;
31  m_state_loss_mat(i, m_num_states-1) = 1;
32  }
33 
34  // Initialize the start and stop states
38  m_q.set_const(-CMath::INFTY);
39  m_p[0] = 0; // start state
40  m_q[1] = 0; // stop state
41 }
42 
44 {
45 }
46 
48 {
49  SGVector< int32_t > state_seq = labels_to_states(label_seq);
50  SGMatrix< float64_t > loss_mat(m_num_states, state_seq.vlen);
51 
52  for ( int32_t i = 0 ; i < loss_mat.num_cols ; ++i )
53  {
54  for ( int32_t s = 0 ; s < loss_mat.num_rows ; ++s )
55  loss_mat(s,i) = m_state_loss_mat(s, state_seq[i]);
56  }
57 
58  return loss_mat;
59 }
60 
61 float64_t CTwoStateModel::loss(CSequence* label_seq_lhs, CSequence* label_seq_rhs)
62 {
63  SGVector< int32_t > state_seq_lhs = labels_to_states(label_seq_lhs);
64  SGVector< int32_t > state_seq_rhs = labels_to_states(label_seq_rhs);
65 
66  ASSERT(state_seq_lhs.vlen == state_seq_rhs.vlen)
67 
68  float64_t ret = 0.0;
69  for ( int32_t i = 0 ; i < state_seq_lhs.vlen ; ++i )
70  ret += m_state_loss_mat(state_seq_lhs[i], state_seq_rhs[i]);
71 
72  return ret;
73 }
74 
76 {
77  // 0 -> start state
78  // 1 -> stop state
79  // 2 -> negative state (label == 0)
80  // 3 -> positive state (label == 1)
81 
82  SGVector< int32_t > seq_data = label_seq->get_data();
83  SGVector< int32_t > state_seq(seq_data.size());
84  for ( int32_t i = 1 ; i < state_seq.vlen-1 ; ++i )
85  {
86  //FIXME make independent of values 0-1 in labels
87  state_seq[i] = seq_data[i] + 2;
88  }
89 
90  // The first element is always start state
91  state_seq[0] = 0;
92  // The last element is always stop state
93  state_seq[state_seq.vlen-1] = 1;
94 
95  return state_seq;
96 }
97 
99 {
100  SGVector< int32_t > label_seq(state_seq.vlen);
101 
102  //FIXME make independent of values 0-1 in labels
103  // Legend for state indices:
104  // 0 -> start state => label 0
105  // 1 -> stop state => label 0
106  // 2 -> negative state (label == 0) => label 0
107  // 3 -> positive state (label == 1) => label 1
108  label_seq.zero();
109  for ( int32_t i = 0 ; i < state_seq.vlen ; ++i )
110  {
111  if ( state_seq[i] == 3 )
112  label_seq[i] = 1;
113  }
114 
115  CSequence* ret = new CSequence(label_seq);
116  SG_REF(ret);
117  return ret;
118 }
119 
121  SGVector< float64_t > w, int32_t num_feats, int32_t num_obs)
122 {
123  emission_weights.zero();
124 
125  // Legend for state indices:
126  // 0 -> start state
127  // 1 -> stop state
128  // 2 -> negative state (label == 0)
129  // 3 -> positive state (label == 1)
130  //
131  // start and stop states have no emission scores
132 
133  index_t em_idx, w_idx = m_num_transmission_params;
134  for ( int32_t s = 2 ; s < m_num_states ; ++s )
135  {
136  for ( int32_t f = 0 ; f < num_feats ; ++f )
137  {
138  for ( int32_t o = 0 ; o < num_obs ; ++o )
139  {
140  em_idx = s*num_feats*num_obs + f*num_obs + o;
141  emission_weights[em_idx] = w[w_idx++];
142  }
143  }
144  }
145 }
146 
148  SGVector< float64_t > w, int32_t num_feats, int32_t num_plif_nodes)
149 {
150  CPlif* plif;
151  index_t p_idx, w_idx = m_num_transmission_params;
152  for ( int32_t s = 2 ; s < m_num_states ; ++s )
153  {
154  for ( int32_t f = 0 ; f < num_feats ; ++f )
155  {
156  SGVector< float64_t > penalties(num_plif_nodes);
157  p_idx = 0;
158 
159  for ( int32_t i = 0 ; i < num_plif_nodes ; ++i )
160  penalties[p_idx++] = w[w_idx++];
161 
162  plif = (CPlif*) plif_matrix->get_element(m_num_states*f + s);
163  plif->set_plif_penalty(penalties);
164  SG_UNREF(plif);
165  }
166  }
167 }
168 
170  SGMatrix< float64_t >& transmission_weights, SGVector< float64_t > w)
171 {
172  transmission_weights.set_const(-CMath::INFTY);
173 
174  // Legend for state indices:
175  // 0 -> start state
176  // 1 -> stop state
177  // 2 -> negative state (label == 0)
178  // 3 -> positive state (label == 1)
179 
180  // From start
181  transmission_weights(0,2) = 0; // to negative
182  transmission_weights(0,3) = 0; // to positive
183  // From negative
184  transmission_weights(2,1) = 0; // to stop
185  transmission_weights(2,2) = w[0]; // to negative
186  transmission_weights(2,3) = w[1]; // to positive
187  // From positive
188  transmission_weights(3,1) = 0; // to stop
189  transmission_weights(3,2) = w[3]; // to positive
190  transmission_weights(3,3) = w[2]; // to negative
191 }
192 
194  SGMatrix< float64_t > transmission_weights,
195  SGVector< float64_t > emission_weights,
196  int32_t num_feats, int32_t num_obs) const
197 {
198  // Legend for state indices:
199  // 0 -> start state
200  // 1 -> stop state
201  // 2 -> negative state
202  // 3 -> positive state
203  psi[0] = transmission_weights(2,2);
204  psi[1] = transmission_weights(2,3);
205  psi[2] = transmission_weights(3,3);
206  psi[3] = transmission_weights(3,2);
207 
208  // start and stop states have no emission scores
209  index_t obs_idx, psi_idx = m_num_transmission_params;
210  for ( int32_t s = 2 ; s < m_num_states ; ++s )
211  {
212  for ( int32_t f = 0 ; f < num_feats ; ++f )
213  {
214  for ( int32_t o = 0 ; o < num_obs ; ++o )
215  {
216  obs_idx = s*num_feats*num_obs + f*num_obs + o;
217  psi[psi_idx++] = emission_weights[obs_idx];
218  }
219  }
220  }
221 
222 }
223 
225  SGVector< float64_t > emission_weights, int32_t num_feats, int32_t num_obs) const
226 {
227  int32_t num_free_states = 2;
228  SGVector< float64_t > vec(num_free_states*(num_free_states + num_feats*num_obs));
229  vec.zero();
230  weights_to_vector(vec, transmission_weights, emission_weights, num_feats, num_obs);
231  return vec;
232 }
233 
235  int32_t num_feats) const
236 {
237  REQUIRE(num_free_states == 2, "Using the TwoStateModel only two states are free\n")
238 
239  SGVector< int32_t > monotonicity(num_feats*num_free_states);
240 
241  for ( int32_t i = 0 ; i < num_feats ; ++i )
242  monotonicity[i] = -1;
243  for ( int32_t i = num_feats ; i < 2*num_feats ; ++i )
244  monotonicity[i] = +1;
245 
246  return monotonicity;
247 }
248 
249 CHMSVMModel* CTwoStateModel::simulate_data(int32_t num_exm, int32_t exm_len,
250  int32_t num_features, int32_t num_noise_features)
251 {
252  // Number of different states
253  int32_t num_states = 2;
254  // Min and max length of positive block
255  int32_t block_len[] = {10, 100};
256  // Min and max number of positive blocks per example
257  int32_t num_blocks[] = {0, 3};
258 
259  // Proportion of wrong labels
260  float64_t prop_distort = 0.2;
261  // Standard deviation of Gaussian noise
262  float64_t noise_std = 4;
263 
264  // Generate label sequence randomly containing from num_blocks[0] to
265  // num_blocks[1] blocks of positive labels each of length between
266  // block_len[0] and block_len[1]
267 
268  CSequenceLabels* labels = new CSequenceLabels(num_exm, num_states);
269  SGVector< int32_t > ll(num_exm*exm_len);
270  ll.zero();
271  int32_t rnb, rl, rp;
272 
273  for ( int32_t i = 0 ; i < num_exm ; ++i)
274  {
275  SGVector< int32_t > lab(exm_len);
276  lab.zero();
277  rnb = num_blocks[0] + CMath::ceil((num_blocks[1]-num_blocks[0])*
278  CMath::random(0.0, 1.0)) - 1;
279 
280  for ( int32_t j = 0 ; j < rnb ; ++j )
281  {
282  rl = block_len[0] + CMath::ceil((block_len[1]-block_len[0])*
283  CMath::random(0.0, 1.0)) - 1;
284  rp = CMath::ceil((exm_len-rl)*CMath::random(0.0, 1.0));
285 
286  for ( int32_t idx = rp-1 ; idx < rp+rl ; ++idx )
287  {
288  lab[idx] = 1;
289  ll[i*exm_len + idx] = 1;
290  }
291  }
292 
293  labels->add_vector_label(lab);
294  }
295 
296  // Generate features by
297  // i) introducing label noise, i.e. flipping a propotion prop_distort
298  // of labels and
299  // ii) adding Gaussian noise to the (distorted) label sequence
300 
301  SGVector< int32_t > distort(num_exm*exm_len);
302  SGVector< int32_t > d1(CMath::round(distort.vlen*prop_distort));
303  SGVector< int32_t > d2(d1.vlen);
305  SGMatrix< float64_t > signal(num_features, distort.vlen);
306 
307  for ( int32_t i = 0 ; i < num_features ; ++i )
308  {
309  lf = ll;
310  distort.randperm();
311 
312  for ( int32_t j = 0 ; j < d1.vlen ; ++j )
313  d1[j] = distort[j];
314 
315  for ( int32_t j = 0 ; j < d2.vlen ; ++j )
316  d2[j] = distort[ distort.vlen-d2.vlen+j ];
317 
318  for ( int32_t j = 0 ; j < d1.vlen ; ++j )
319  lf[ d1[j] ] = lf[ d2[j] ];
320 
321  int32_t idx = i*signal.num_cols;
322  for ( int32_t j = 0 ; j < signal.num_cols ; ++j )
323  signal[idx++] = lf[j] + noise_std*CMath::normal_random((float64_t)0.0, 1.0);
324  }
325 
326  // Substitute some features by pure noise
327  SGVector< int32_t > ridx(num_features);
328  ridx.randperm();
329  for ( int32_t i = 0 ; i < num_noise_features ; ++i )
330  {
331  int32_t idx = i*signal.num_cols;
332  for ( int32_t j = 0 ; j < signal.num_cols ; ++j )
333  signal[idx++] = noise_std*CMath::normal_random((float64_t)0.0, 1.0);
334  }
335 
336  CMatrixFeatures< float64_t >* features =
337  new CMatrixFeatures< float64_t >(signal, exm_len, num_exm);
338 
339  int32_t num_obs = 0; // continuous observations, dummy value
340  bool use_plifs = true;
341  return new CHMSVMModel(features, labels, SMT_TWO_STATE, num_obs, use_plifs);
342 }

SHOGUN Machine Learning Toolbox - Documentation