X-Boost  2.3.8
PrecomputedPatternResponse.h
Go to the documentation of this file.
1 /* XBoost: Ada-Boost and Friends on Haar/ICF/HOG Features, Library and ToolBox
2  *
3  * Copyright (c) 2008-2014 Paolo Medici <medici@ce.unipr.it>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #ifndef _PRECOMPUTED_PATTERN_RESPONSE_H
22 #define _PRECOMPUTED_PATTERN_RESPONSE_H
23 
27 #include <vector>
28 #include <cmath> // abs
29 #include "_stdint.h"
30 
31 #ifdef _MULTITHREAD
32 # include "Thread/thread_group.h"
33 # include "Thread/bind.h"
34 #endif
35 
36 #include <iostream>
37 
39 // TODO: for caching-reason it is better to invert samples and feature order in the matrixes
40 template<class ResponseType>
42 public:
44  int n_samples;
48  int *category;
50  double *weights;
52  ResponseType *response;
54  std::pair<ResponseType, ResponseType> *response_range;
56  int *bin;
59 
60 private:
61 
63  template<class TrainintSetType, class FeatureType>
64  void internal_precompute_feat_wide(int f0, int f1, const TrainintSetType * set, const std::vector<FeatureType> * feats)
65  {
66 // int feat_size = feats->size();
67  int sample_size = set->Size();
68  // export the data
69  for(int j=f0; j<f1; ++j)
70  {
71  for(int i =0; i<sample_size; ++i)
72  {
73  category[i] = set->templates[i].category;
74 
75  ResponseType v = (*feats)[j].response(getData1(set->templates[i], *set), getData2(set->templates[i], *set));
76  response[i + j * sample_size] = v;
77  if(i == 0)
78  {
79  response_range[j].first =response_range[j].second = v;
80  }
81  else
82  {
83  // min
84  if(response_range[j].first > v) response_range[j].first = v;
85  // max
86  if(response_range[j].second < v) response_range[j].second = v;
87  }
88 
89  }
90 
91  if(number_of_bins>0)
92  {
93  ResponseType delta = (response_range[j].second > response_range[j].first) ? (response_range[j].second - response_range[j].first + 1) : ResponseType(1);
94 
95  for(unsigned int i=0; i<set->Size(); ++i)
96  {
97  // create quantization table
98  bin[i + j * sample_size] = (int) ( ((response[i + j * sample_size] - response_range[j].first) * number_of_bins) / delta );
99  }
100  }
101 
102  }
103 
104  }
105 public:
106 
107  PrecomputedPatternResponse(int n_bins) : n_samples(0), n_features(0), category(0), weights(0), response(0), response_range(0), bin(0), number_of_bins(n_bins) {}
109  delete [] category;
110  delete [] weights;
111  delete [] response;
112  delete [] response_range;
113  delete [] bin;
114  }
115 
117  void allocate(int samples, int feats) {
118  std::cout << "allocate memory for " << samples << " samples and "<< feats << " features" << std::endl;
119 
120  int64_t n_elements = static_cast<int64_t>(samples) * feats;
121 
122 #ifndef USE_64_BIT
123  if(n_elements > int64_t(0xFFFFFFFF))
124  {
125  std::cerr << "too much samples" << std::endl;
126  }
127 #endif
128 
129  if(samples!=n_samples)
130  {
131  delete [] category;
132  delete [] weights;
133  weights = new double[samples];
134  category = new int[samples];
135  }
136  if(samples!=n_samples || feats != n_features)
137  {
138  delete [] response;
139  response = new ResponseType[n_elements];
140  delete [] bin;
141  bin=0;
142  if(number_of_bins>0)
143  bin = new int[n_elements];
144  }
145  if(feats!=n_features)
146  {
147  delete [] response_range;
148  response_range = new std::pair<ResponseType, ResponseType> [feats];
149  }
150  n_samples = samples;
151  n_features = feats;
152  }
153 
157  template<class TrainintSetType, class FeatureType>
158  void Precompute(const TrainintSetType & set, const std::vector<FeatureType> & feats, int max_concurrent_jobs )
159  {
160  int feat_size = feats.size();
161  int sample_size = set.Size();
162 
163  // allocate memory
164  allocate(sample_size, feat_size);
165 
166 #ifdef _MULTITHREAD
167  if(max_concurrent_jobs > 1)
168  {
169  sprint::thread_group thread_pool_;
170 
171  for(int k=0; k<max_concurrent_jobs; ++k)
172  {
173  int f0 = (k * feat_size) / max_concurrent_jobs;
174  int f1 = ((k+1) * feat_size) / max_concurrent_jobs;
175 
176  thread_pool_.create_thread(sprint::thread_bind(&PrecomputedPatternResponse::internal_precompute_feat_wide<TrainintSetType,FeatureType>, this, f0, f1, &set, &feats));
177 
178  }
179  thread_pool_.join_all();
180  }
181  else
182 #endif
183  {
185  // export the data
186  for(int i =0; i<sample_size; ++i)
187  {
188  category[i] = set.templates[i].category;
189 
190  for(int j=0; j<feat_size; ++j)
191  {
192  ResponseType v = feats[j].response(getData1(set.templates[i], set), getData2(set.templates[i], set));
193  response[i + j * sample_size] = v;
194  if(i == 0)
195  {
196  response_range[j].first =response_range[j].second = v;
197  }
198  else
199  {
200  // min
201  if(response_range[j].first > v) response_range[j].first = v;
202  // max
203  if(response_range[j].second < v) response_range[j].second = v;
204  }
205 
206  }
207  }
208 
209  if(number_of_bins>0)
210  {
211  // PRECOMPUTE BIN
212  for(int j=0; j<feat_size; ++j)
213  {
214  ResponseType delta = (response_range[j].second > response_range[j].first) ? (response_range[j].second - response_range[j].first + 1) : ResponseType(1);
215 
216  for(unsigned int i =0; i<set.Size(); ++i)
217  {
218  // create quantization table
219  bin[i + j * sample_size] = (int) ( ((response[i + j * sample_size] - response_range[j].first) * number_of_bins) / delta );
220  }
221 
222  }
223 
224  }
225 
226 
228  }
229 
230  }
231 
233  void PrepareBins()
234  {
235  // export the data
236  for(int j=0; j<n_features; ++j)
237  {
238  for(int i =0; i<n_samples; ++i)
239  {
240  ResponseType v = response[i + j * n_samples];
241  if(i == 0)
242  {
243  response_range[j].first =response_range[j].second = v;
244  }
245  else
246  {
247  // min
248  if(response_range[j].first > v) response_range[j].first = v;
249  // max
250  if(response_range[j].second < v) response_range[j].second = v;
251  }
252 
253  }
254 
255  if(number_of_bins>0)
256  {
257  ResponseType delta = (response_range[j].second > response_range[j].first) ? (response_range[j].second - response_range[j].first + 1) : ResponseType(1);
258 
259  for(int i =0; i<n_samples; ++i)
260  {
261  // create quantization table
262  bin[i + j * n_samples] = (int) ( ((response[i + j * n_samples] - response_range[j].first) * number_of_bins) / delta );
263  }
264  }
265 
266  }
267  }
268 
269 
272  {
273  double w = 1.0 / (double)n_samples;
274  for(int i=0; i<n_samples; ++i)
275  {
276  weights[i] = (category[i] == 1) ? w : -w;
277  }
278  }
279 
285  template<class Classifier>
286  void ExecuteClassifier(const Classifier & c, bool *correct_tables, double *_wp, double *_wn, int *_match) const
287  {
288  double wp = 0.0, wn = 0.0;
289  int match = 0;
290  // for each samples...
291  for(int i =0; i<n_samples; ++i)
292  {
293  int test = c(&response[i], n_samples ); // starting from column i, features along rows so the stride is n_samples
294  if(test == category[i])
295  {
296  wp += std::abs(weights[i]);
297  correct_tables[i] = true;
298  match++;
299  }
300  else
301  {
302  wn += std::abs(weights[i]);
303  correct_tables[i] = false;
304  }
305  }
306 
307  if(_wp)
308  *_wp = wp;
309  if(_wn)
310  *_wn = wn;
311  if(_match)
312  *_match = match;
313  }
314 
315 
316 };
317 
318 
319 #endif
int * category
category list
Definition: PrecomputedPatternResponse.h:48
double * weights
weights list
Definition: PrecomputedPatternResponse.h:50
int number_of_bins
Quantization level.
Definition: PrecomputedPatternResponse.h:58
int * bin
precomputed bin matrix (rows features, columns samples)
Definition: PrecomputedPatternResponse.h:56
Definition: thread_group.h:82
void join_all()
wait all threads terminate
Definition: thread_group.h:114
proposal 1 for thread group
int n_features
number of feature preallocated
Definition: PrecomputedPatternResponse.h:46
void Precompute(const TrainintSetType &set, const std::vector< FeatureType > &feats, int max_concurrent_jobs)
Definition: PrecomputedPatternResponse.h:158
void InitializeWeights()
Initialize ugual weights.
Definition: PrecomputedPatternResponse.h:271
int n_samples
number of samples
Definition: PrecomputedPatternResponse.h:44
Definition: PrecomputedPatternResponse.h:41
method to create function pointer for thread call
std::pair< ResponseType, ResponseType > * response_range
precomputed response ranges
Definition: PrecomputedPatternResponse.h:54
bool create_thread(const sprint::thread_function &p)
create an additional thread
Definition: thread_group.h:102
ResponseType * response
response matrix. For performance reason it each row is a feature and columns are samples ...
Definition: PrecomputedPatternResponse.h:52
void ExecuteClassifier(const Classifier &c, bool *correct_tables, double *_wp, double *_wn, int *_match) const
Definition: PrecomputedPatternResponse.h:286
additional typedef, for portability under win32
void allocate(int samples, int feats)
allocate the response matrix
Definition: PrecomputedPatternResponse.h:117
void PrepareBins()
compute bin
Definition: PrecomputedPatternResponse.h:233