automatic commit
[folded-ctf.git] / parsing_pool.cc
diff --git a/parsing_pool.cc b/parsing_pool.cc
new file mode 100644 (file)
index 0000000..696477a
--- /dev/null
@@ -0,0 +1,259 @@
+
+///////////////////////////////////////////////////////////////////////////
+// This program is free software: you can redistribute it and/or modify  //
+// it under the terms of the version 3 of the GNU General Public License //
+// as published by the Free Software Foundation.                         //
+//                                                                       //
+// This program is distributed in the hope that it will be useful, but   //
+// WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
+// General Public License for more details.                              //
+//                                                                       //
+// You should have received a copy of the GNU General Public License     //
+// along with this program. If not, see <http://www.gnu.org/licenses/>.  //
+//                                                                       //
+// Written by Francois Fleuret, (C) IDIAP                                //
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
+///////////////////////////////////////////////////////////////////////////
+
+#include "parsing_pool.h"
+#include "tools.h"
+
+ParsingPool::ParsingPool(LabelledImagePool *image_pool, PoseCellHierarchy *hierarchy, scalar_t proportion_negative_cells) {
+  _nb_images = image_pool->nb_images();
+  _parsings = new Parsing *[_nb_images];
+
+  _nb_cells = 0;
+  _nb_positive_cells = 0;
+  _nb_negative_cells = 0;
+  for(int i = 0; i < _nb_images; i++) {
+    _parsings[i] = new Parsing(image_pool, hierarchy, proportion_negative_cells, i);
+    _nb_cells += _parsings[i]->nb_cells();
+    _nb_positive_cells += _parsings[i]->nb_positive_cells();
+    _nb_negative_cells += _parsings[i]->nb_negative_cells();
+  }
+  (*global.log_stream) << "ParsingPool initialized" << endl;
+  (*global.log_stream) << "  _nb_cells = " << _nb_cells << endl;
+  (*global.log_stream) << "  _nb_positive_cells = " << _nb_positive_cells << endl;
+  (*global.log_stream) << "  _nb_negative_cells = " << _nb_negative_cells << endl;
+}
+
+ParsingPool::~ParsingPool() {
+  for(int i = 0; i < _nb_images; i++)
+    delete _parsings[i];
+  delete[] _parsings;
+}
+
+void ParsingPool::down_one_level(LossMachine *loss_machine, PoseCellHierarchy *hierarchy, int level) {
+  scalar_t *labels = new scalar_t[_nb_cells];
+  scalar_t *tmp_responses = new scalar_t[_nb_cells];
+
+  int c;
+
+  { ////////////////////////////////////////////////////////////////////
+    // Sanity check
+    scalar_t l = 0;
+    for(int i = 0; i < _nb_images; i++) {
+      for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
+        if(_parsings[i]->label(d) != 0) {
+          l += exp( - _parsings[i]->label(d) * _parsings[i]->response(d));
+        }
+      }
+    }
+    (*global.log_stream) << "* INITIAL LOSS IS " << l << endl;
+  } ////////////////////////////////////////////////////////////////////
+
+  // Put the negative samples with their current responses, and all
+  // others to 0
+
+  c = 0;
+  for(int i = 0; i < _nb_images; i++) {
+    for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
+      if(_parsings[i]->label(d) < 0) {
+        labels[c] = -1;
+        tmp_responses[c] = _parsings[i]->response(d);
+      } else {
+        labels[c] = 0;
+        tmp_responses[c] = 0;
+      }
+      c++;
+    }
+  }
+
+  // Sub-sample among the negative ones
+
+  int *sample_nb_occurences = new int[_nb_cells];
+  scalar_t *sample_responses = new scalar_t[_nb_cells];
+
+  loss_machine->subsample(_nb_cells, labels, tmp_responses,
+                          _nb_negative_cells, sample_nb_occurences, sample_responses,
+                          1);
+  c = 0;
+  for(int i = 0; i < _nb_images; i++) {
+    for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
+      if(_parsings[i]->label(d) > 0) {
+        sample_nb_occurences[c + d] = 1;
+        sample_responses[c + d] = _parsings[i]->response(d);
+      }
+    }
+
+    int d = c + _parsings[i]->nb_cells();
+
+    _parsings[i]->down_one_level(hierarchy, level, sample_nb_occurences + c, sample_responses + c);
+
+    c = d;
+  }
+
+  { ////////////////////////////////////////////////////////////////////
+    // Sanity check
+    scalar_t l = 0;
+    for(int i = 0; i < _nb_images; i++) {
+      for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
+        if(_parsings[i]->label(d) != 0) {
+          l += exp( - _parsings[i]->label(d) * _parsings[i]->response(d));
+        }
+      }
+    }
+    (*global.log_stream) << "* FINAL LOSS IS " << l << endl;
+  } ////////////////////////////////////////////////////////////////////
+
+  delete[] sample_responses;
+  delete[] sample_nb_occurences;
+}
+
+void ParsingPool::update_cell_responses(PiFeatureFamily *pi_feature_family,
+                                        Classifier *classifier) {
+  for(int i = 0; i < _nb_images; i++) {
+    _parsings[i]->update_cell_responses(pi_feature_family, classifier);
+  }
+}
+
+void ParsingPool::weighted_sampling(LossMachine *loss_machine,
+                                    PiFeatureFamily *pi_feature_family,
+                                    SampleSet *sample_set,
+                                    scalar_t *responses) {
+
+  int nb_negatives_to_sample = sample_set->nb_samples() - _nb_positive_cells;
+
+  ASSERT(nb_negatives_to_sample > 0);
+
+  scalar_t *labels = new scalar_t[_nb_cells];
+  scalar_t *tmp_responses = new scalar_t[_nb_cells];
+
+  int c, s;
+
+  // Put the negative samples with their current responses, and all
+  // others to 0
+
+  c = 0;
+  for(int i = 0; i < _nb_images; i++) {
+    for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
+      if(_parsings[i]->label(d) < 0) {
+        labels[c] = -1;
+        tmp_responses[c] = _parsings[i]->response(d);
+      } else {
+        labels[c] = 0;
+        tmp_responses[c] = 0;
+      }
+      c++;
+    }
+  }
+
+  // Sub-sample among the negative ones
+
+  int *sample_nb_occurences = new int[_nb_cells];
+  scalar_t *sample_responses = new scalar_t[_nb_cells];
+
+  loss_machine->subsample(_nb_cells, labels, tmp_responses,
+                          nb_negatives_to_sample, sample_nb_occurences, sample_responses,
+                          0);
+
+  for(int k = 0; k < _nb_cells; k++) {
+    if(sample_nb_occurences[k] > 0) {
+      ASSERT(sample_nb_occurences[k] == 1);
+      labels[k] = -1.0;
+      tmp_responses[k] = sample_responses[k];
+    } else {
+      labels[k] = 0;
+    }
+  }
+
+  delete[] sample_responses;
+  delete[] sample_nb_occurences;
+
+  // Put the positive ones
+
+  c = 0;
+  for(int i = 0; i < _nb_images; i++) {
+    for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
+      if(_parsings[i]->label(d) > 0) {
+        labels[c] = 1;
+        tmp_responses[c] = _parsings[i]->response(d);
+      }
+      c++;
+    }
+  }
+
+  // Here we have the responses for the sub-sampled in tmp_responses,
+  // and we have labels[n] set to zero for non-sampled samples
+
+  s = 0;
+  c = 0;
+
+//   global.bar.init(&cout, _nb_images);
+
+  for(int i = 0; i < _nb_images; i++) {
+
+    int *to_collect = new int[_parsings[i]->nb_cells()];
+
+    for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
+      to_collect[d] = (labels[c + d] != 0);
+    }
+
+    _parsings[i]->collect_samples(sample_set, pi_feature_family, s, to_collect);
+
+    for(int d = 0; d < _parsings[i]->nb_cells(); d++) {
+      if(to_collect[d]) {
+        responses[s++] = tmp_responses[c + d];
+      }
+    }
+
+    delete[] to_collect;
+
+    c += _parsings[i]->nb_cells();
+
+//     global.bar.refresh(&cout, i);
+  }
+
+//   global.bar.finish(&cout);
+
+  delete[] tmp_responses;
+  delete[] labels;
+}
+
+void ParsingPool::write_roc(ofstream *out) {
+  int nb_negatives = nb_negative_cells();
+  int nb_positives = nb_positive_cells();
+
+  scalar_t *pos_responses = new scalar_t[nb_positives];
+  scalar_t *neg_responses = new scalar_t[nb_negatives];
+  int np = 0, nn = 0;
+  for(int i = 0; i < _nb_images; i++) {
+    for(int c = 0; c < _parsings[i]->nb_cells(); c++) {
+      if(_parsings[i]->label(c) > 0)
+        pos_responses[np++] = _parsings[i]->response(c);
+      else if(_parsings[i]->label(c) < 0)
+        neg_responses[nn++] = _parsings[i]->response(c);
+    }
+  }
+
+  ASSERT(nn == nb_negatives && np == nb_positives);
+
+  print_roc_small_pos(out,
+                      nb_positives, pos_responses,
+                      nb_negatives, neg_responses,
+                      1.0);
+
+  delete[] pos_responses;
+  delete[] neg_responses;
+}