X-Git-Url: https://fleuret.org/cgi-bin/gitweb/gitweb.cgi?p=folded-ctf.git;a=blobdiff_plain;f=parsing_pool.cc;fp=parsing_pool.cc;h=696477a30f642f08b50802c86081cf79ff9d3497;hp=0000000000000000000000000000000000000000;hb=d922ad61d35e9a6996730bec24b16f8bf7bc426c;hpb=3bb118f5a9462d02ff7d99ef28ecc0d7e23529f9 diff --git a/parsing_pool.cc b/parsing_pool.cc new file mode 100644 index 0000000..696477a --- /dev/null +++ b/parsing_pool.cc @@ -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 . // +// // +// Written by Francois Fleuret, (C) IDIAP // +// Contact 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; +}