2 * folded-ctf is an implementation of the folded hierarchy of
3 * classifiers for object detection, developed by Francois Fleuret
6 * Copyright (c) 2008 Idiap Research Institute, http://www.idiap.ch/
7 * Written by Francois Fleuret <francois.fleuret@idiap.ch>
9 * This file is part of folded-ctf.
11 * folded-ctf is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published
13 * by the Free Software Foundation, either version 3 of the License,
14 * or (at your option) any later version.
16 * folded-ctf is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with folded-ctf. If not, see <http://www.gnu.org/licenses/>.
27 #include "loss_machine.h"
29 LossMachine::LossMachine(int loss_type) {
30 _loss_type = loss_type;
33 void LossMachine::get_loss_derivatives(SampleSet *samples,
35 scalar_t *derivatives) {
39 case LOSS_EXPONENTIAL:
41 for(int n = 0; n < samples->nb_samples(); n++) {
43 - samples->label(n) * exp( - samples->label(n) * responses[n]);
50 for(int n = 0; n < samples->nb_samples(); n++) {
51 if(samples->label(n) != 0 && samples->label(n) * responses[n] < 1)
61 for(int n = 0; n < samples->nb_samples(); n++) {
62 if(samples->label(n) == 0)
65 derivatives[n] = samples->label(n) * 1/(1 + exp(samples->label(n) * responses[n]));
71 cerr << "Unknown loss type in BoostedClassifier::get_loss_derivatives."
78 scalar_t LossMachine::loss(SampleSet *samples, scalar_t *responses) {
83 case LOSS_EXPONENTIAL:
85 for(int n = 0; n < samples->nb_samples(); n++) {
86 l += exp( - samples->label(n) * responses[n]);
94 for(int n = 0; n < samples->nb_samples(); n++) {
95 if(samples->label(n) != 0) {
96 if(samples->label(n) * responses[n] < 1)
97 l += (1 - samples->label(n) * responses[n]);
105 for(int n = 0; n < samples->nb_samples(); n++) {
106 if(samples->label(n) != 0) {
107 scalar_t u = - samples->label(n) * responses[n];
111 l += log(1 + exp(u));
119 cerr << "Unknown loss type in LossMachine::loss." << endl;
126 scalar_t LossMachine::optimal_weight(SampleSet *sample_set,
127 scalar_t *weak_learner_responses,
128 scalar_t *current_responses) {
132 case LOSS_EXPONENTIAL:
134 scalar_t num = 0, den = 0, z;
136 for(int n = 0; n < sample_set->nb_samples(); n++) {
137 z = sample_set->label(n) * weak_learner_responses[n];
139 num += exp( - sample_set->label(n) * current_responses[n]);
141 den += exp( - sample_set->label(n) * current_responses[n]);
145 return 0.5 * log(num / den);
153 scalar_t u = 0, du = -0.1;
154 scalar_t *responses = new scalar_t[sample_set->nb_samples()];
156 scalar_t l, prev_l = -1;
158 const scalar_t minimum_delta_for_optimization = 1e-5;
161 while(n < 100 && abs(du) > minimum_delta_for_optimization) {
164 for(int s = 0; s < sample_set->nb_samples(); s++) {
165 responses[s] = current_responses[s] + u * weak_learner_responses[s] ;
167 l = loss(sample_set, responses);
168 if(l > prev_l) du = du * -0.25;
172 (*global.log_stream) << "END l = " << l << " du = " << du << endl;
180 cerr << "Unknown loss type in LossMachine::optimal_weight." << endl;
186 void LossMachine::subsample(int nb, scalar_t *labels, scalar_t *responses,
187 int nb_to_sample, int *sample_nb_occurences, scalar_t *sample_responses,
188 int allow_duplicates) {
192 case LOSS_EXPONENTIAL:
194 scalar_t *weights = new scalar_t[nb];
196 for(int n = 0; n < nb; n++) {
200 weights[n] = exp( - labels[n] * responses[n]);
202 sample_nb_occurences[n] = 0;
203 sample_responses[n] = 0.0;
206 scalar_t total_weight;
207 int nb_sampled = 0, sum_sample_nb_occurences = 0;
209 int *sampled_indexes = new int[nb_to_sample];
211 (*global.log_stream) << "Sampling " << nb_to_sample << " samples." << endl;
214 total_weight = robust_sampling(nb,
219 for(int k = 0; nb_sampled < nb_to_sample && k < nb_to_sample; k++) {
220 int i = sampled_indexes[k];
221 if(allow_duplicates || sample_nb_occurences[i] == 0) nb_sampled++;
222 sample_nb_occurences[i]++;
223 sum_sample_nb_occurences++;
225 } while(nb_sampled < nb_to_sample);
227 (*global.log_stream) << "Done." << endl;
229 delete[] sampled_indexes;
231 scalar_t unit_weight = log(total_weight / scalar_t(sum_sample_nb_occurences));
233 for(int n = 0; n < nb; n++) {
234 if(sample_nb_occurences[n] > 0) {
235 if(allow_duplicates) {
236 sample_responses[n] = - labels[n] * unit_weight;
238 sample_responses[n] = - labels[n] * (unit_weight + log(scalar_t(sample_nb_occurences[n])));
239 sample_nb_occurences[n] = 1;
250 cerr << "Unknown loss type in LossMachine::resample." << endl;