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