--- /dev/null
+
+///////////////////////////////////////////////////////////////////////////
+// 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;
+}