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

SHOGUN Machine Learning Toolbox - Documentation