Removed the definition of basename, which confuses an existing system one.
[folded-ctf.git] / parsing_pool.cc
1 /*
2  *  folded-ctf is an implementation of the folded hierarchy of
3  *  classifiers for object detection, developed by Francois Fleuret
4  *  and Donald Geman.
5  *
6  *  Copyright (c) 2008 Idiap Research Institute, http://www.idiap.ch/
7  *  Written by Francois Fleuret <francois.fleuret@idiap.ch>
8  *
9  *  This file is part of folded-ctf.
10  *
11  *  folded-ctf is free software: you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License version 3 as
13  *  published by the Free Software Foundation.
14  *
15  *  folded-ctf is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with folded-ctf.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "parsing_pool.h"
26 #include "tools.h"
27
28 ParsingPool::ParsingPool(LabelledImagePool *image_pool, PoseCellHierarchy *hierarchy, scalar_t proportion_negative_cells) {
29   _nb_images = image_pool->nb_images();
30   _parsings = new Parsing *[_nb_images];
31
32   _nb_cells = 0;
33   _nb_positive_cells = 0;
34   _nb_negative_cells = 0;
35   for(int i = 0; i < _nb_images; i++) {
36     _parsings[i] = new Parsing(image_pool, hierarchy, proportion_negative_cells, i);
37     _nb_cells += _parsings[i]->nb_cells();
38     _nb_positive_cells += _parsings[i]->nb_positive_cells();
39     _nb_negative_cells += _parsings[i]->nb_negative_cells();
40   }
41   (*global.log_stream) << "ParsingPool initialized" << endl;
42   (*global.log_stream) << "  _nb_cells = " << _nb_cells << endl;
43   (*global.log_stream) << "  _nb_positive_cells = " << _nb_positive_cells << endl;
44   (*global.log_stream) << "  _nb_negative_cells = " << _nb_negative_cells << endl;
45 }
46
47 ParsingPool::~ParsingPool() {
48   for(int i = 0; i < _nb_images; i++)
49     delete _parsings[i];
50   delete[] _parsings;
51 }
52
53 void ParsingPool::down_one_level(LossMachine *loss_machine, PoseCellHierarchy *hierarchy, int level) {
54   scalar_t *labels = new scalar_t[_nb_cells];
55   scalar_t *tmp_responses = new scalar_t[_nb_cells];
56
57   int c;
58
59   { ////////////////////////////////////////////////////////////////////
60     // Sanity check
61     scalar_t l = 0;
62     for(int i = 0; i < _nb_images; i++) {
63       for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
64         if(_parsings[i]->label(d) != 0) {
65           l += exp( - _parsings[i]->label(d) * _parsings[i]->response(d));
66         }
67       }
68     }
69     (*global.log_stream) << "* INITIAL LOSS IS " << l << endl;
70   } ////////////////////////////////////////////////////////////////////
71
72   // Put the negative samples with their current responses, and all
73   // others to 0
74
75   c = 0;
76   for(int i = 0; i < _nb_images; i++) {
77     for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
78       if(_parsings[i]->label(d) < 0) {
79         labels[c] = -1;
80         tmp_responses[c] = _parsings[i]->response(d);
81       } else {
82         labels[c] = 0;
83         tmp_responses[c] = 0;
84       }
85       c++;
86     }
87   }
88
89   // Sub-sample among the negative ones
90
91   int *sample_nb_occurences = new int[_nb_cells];
92   scalar_t *sample_responses = new scalar_t[_nb_cells];
93
94   loss_machine->subsample(_nb_cells, labels, tmp_responses,
95                           _nb_negative_cells, sample_nb_occurences, sample_responses,
96                           1);
97
98   c = 0;
99   for(int i = 0; i < _nb_images; i++) {
100     for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
101       if(_parsings[i]->label(d) > 0) {
102         sample_nb_occurences[c + d] = 1;
103         sample_responses[c + d] = _parsings[i]->response(d);
104       }
105     }
106
107     int d = c + _parsings[i]->nb_cells();
108
109     _parsings[i]->down_one_level(hierarchy, level, sample_nb_occurences + c, sample_responses + c);
110
111     c = d;
112   }
113
114   { ////////////////////////////////////////////////////////////////////
115     // Sanity check
116     scalar_t l = 0;
117     for(int i = 0; i < _nb_images; i++) {
118       for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
119         if(_parsings[i]->label(d) != 0) {
120           l += exp( - _parsings[i]->label(d) * _parsings[i]->response(d));
121         }
122       }
123     }
124     (*global.log_stream) << "* FINAL LOSS IS " << l << endl;
125   } ////////////////////////////////////////////////////////////////////
126
127   delete[] sample_responses;
128   delete[] sample_nb_occurences;
129
130   delete[] labels;
131   delete[] tmp_responses;
132 }
133
134 void ParsingPool::update_cell_responses(PiFeatureFamily *pi_feature_family,
135                                         Classifier *classifier) {
136   for(int i = 0; i < _nb_images; i++) {
137     _parsings[i]->update_cell_responses(pi_feature_family, classifier);
138   }
139 }
140
141 void ParsingPool::weighted_sampling(LossMachine *loss_machine,
142                                     PiFeatureFamily *pi_feature_family,
143                                     SampleSet *sample_set,
144                                     scalar_t *responses) {
145
146   int nb_negatives_to_sample = sample_set->nb_samples() - _nb_positive_cells;
147
148   ASSERT(nb_negatives_to_sample > 0);
149
150   scalar_t *labels = new scalar_t[_nb_cells];
151   scalar_t *tmp_responses = new scalar_t[_nb_cells];
152
153   int c, s;
154
155   // Put the negative samples with their current responses, and all
156   // others to 0
157
158   c = 0;
159   for(int i = 0; i < _nb_images; i++) {
160     for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
161       if(_parsings[i]->label(d) < 0) {
162         labels[c] = -1;
163         tmp_responses[c] = _parsings[i]->response(d);
164       } else {
165         labels[c] = 0;
166         tmp_responses[c] = 0;
167       }
168       c++;
169     }
170   }
171
172   // Sub-sample among the negative ones
173
174   int *sample_nb_occurences = new int[_nb_cells];
175   scalar_t *sample_responses = new scalar_t[_nb_cells];
176
177   loss_machine->subsample(_nb_cells, labels, tmp_responses,
178                           nb_negatives_to_sample, sample_nb_occurences, sample_responses,
179                           0);
180
181   for(int k = 0; k < _nb_cells; k++) {
182     if(sample_nb_occurences[k] > 0) {
183       ASSERT(sample_nb_occurences[k] == 1);
184       labels[k] = -1.0;
185       tmp_responses[k] = sample_responses[k];
186     } else {
187       labels[k] = 0;
188     }
189   }
190
191   delete[] sample_responses;
192   delete[] sample_nb_occurences;
193
194   // Put the positive ones
195
196   c = 0;
197   for(int i = 0; i < _nb_images; i++) {
198     for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
199       if(_parsings[i]->label(d) > 0) {
200         labels[c] = 1;
201         tmp_responses[c] = _parsings[i]->response(d);
202       }
203       c++;
204     }
205   }
206
207   // Here we have the responses for the sub-sampled in tmp_responses,
208   // and we have labels[n] set to zero for non-sampled samples
209
210   s = 0;
211   c = 0;
212
213   for(int i = 0; i < _nb_images; i++) {
214
215     int *to_collect = new int[_parsings[i]->nb_cells()];
216
217     for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
218       to_collect[d] = (labels[c + d] != 0);
219     }
220
221     _parsings[i]->collect_samples(sample_set, pi_feature_family, s, to_collect);
222
223     for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
224       if(to_collect[d]) {
225         responses[s++] = tmp_responses[c + d];
226       }
227     }
228
229     delete[] to_collect;
230
231     c += _parsings[i]->nb_cells();
232   }
233
234   delete[] tmp_responses;
235   delete[] labels;
236 }
237
238 void ParsingPool::write_roc(ofstream *out) {
239   int nb_negatives = nb_negative_cells();
240   int nb_positives = nb_positive_cells();
241
242   scalar_t *pos_responses = new scalar_t[nb_positives];
243   scalar_t *neg_responses = new scalar_t[nb_negatives];
244   int np = 0, nn = 0;
245   for(int i = 0; i < _nb_images; i++) {
246     for(int c = 0; c < _parsings[i]->nb_cells(); c++) {
247       if(_parsings[i]->label(c) > 0)
248         pos_responses[np++] = _parsings[i]->response(c);
249       else if(_parsings[i]->label(c) < 0)
250         neg_responses[nn++] = _parsings[i]->response(c);
251     }
252   }
253
254   ASSERT(nn == nb_negatives && np == nb_positives);
255
256   print_roc_small_pos(out,
257                       nb_positives, pos_responses,
258                       nb_negatives, neg_responses,
259                       1.0);
260
261   delete[] pos_responses;
262   delete[] neg_responses;
263 }