// Copyright (C) 2009 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_ROC_TRAINEr_H_ #define DLIB_ROC_TRAINEr_H_ #include "roc_trainer_abstract.h" #include "../algs.h" #include <limits> namespace dlib { // ---------------------------------------------------------------------------------------- template < typename trainer_type > class roc_trainer_type { public: typedef typename trainer_type::kernel_type kernel_type; typedef typename trainer_type::scalar_type scalar_type; typedef typename trainer_type::sample_type sample_type; typedef typename trainer_type::mem_manager_type mem_manager_type; typedef typename trainer_type::trained_function_type trained_function_type; roc_trainer_type ( ) : desired_accuracy(0), class_selection(0){} roc_trainer_type ( const trainer_type& trainer_, const scalar_type& desired_accuracy_, const scalar_type& class_selection_ ) : trainer(trainer_), desired_accuracy(desired_accuracy_), class_selection(class_selection_) { // make sure requires clause is not broken DLIB_ASSERT(0 <= desired_accuracy && desired_accuracy <= 1 && (class_selection == -1 || class_selection == +1), "\t roc_trainer_type::roc_trainer_type()" << "\n\t invalid inputs were given to this function" << "\n\t desired_accuracy: " << desired_accuracy << "\n\t class_selection: " << class_selection ); } template < typename in_sample_vector_type, typename in_scalar_vector_type > const trained_function_type train ( const in_sample_vector_type& samples, const in_scalar_vector_type& labels ) const /*! requires - is_binary_classification_problem(samples, labels) == true !*/ { // make sure requires clause is not broken DLIB_ASSERT(is_binary_classification_problem(samples, labels), "\t roc_trainer_type::train()" << "\n\t invalid inputs were given to this function" ); return do_train(mat(samples), mat(labels)); } private: template < typename in_sample_vector_type, typename in_scalar_vector_type > const trained_function_type do_train ( const in_sample_vector_type& samples, const in_scalar_vector_type& labels ) const { trained_function_type df = trainer.train(samples, labels); // clear out the old bias df.b = 0; // obtain all the scores from the df using all the class_selection labeled samples std::vector<double> scores; for (long i = 0; i < samples.size(); ++i) { if (labels(i) == class_selection) scores.push_back(df(samples(i))); } if (class_selection == +1) std::sort(scores.rbegin(), scores.rend()); else std::sort(scores.begin(), scores.end()); // now pick out the index that gives us the desired accuracy with regards to selected class unsigned long idx = static_cast<unsigned long>(desired_accuracy*scores.size() + 0.5); if (idx >= scores.size()) idx = scores.size()-1; df.b = scores[idx]; // In this case add a very small extra amount to the bias so that all the samples // with the class_selection label are classified correctly. if (desired_accuracy == 1) { if (class_selection == +1) df.b -= std::numeric_limits<scalar_type>::epsilon()*df.b; else df.b += std::numeric_limits<scalar_type>::epsilon()*df.b; } return df; } trainer_type trainer; scalar_type desired_accuracy; scalar_type class_selection; }; // ---------------------------------------------------------------------------------------- template < typename trainer_type > const roc_trainer_type<trainer_type> roc_c1_trainer ( const trainer_type& trainer, const typename trainer_type::scalar_type& desired_accuracy ) { return roc_trainer_type<trainer_type>(trainer, desired_accuracy, +1); } // ---------------------------------------------------------------------------------------- template < typename trainer_type > const roc_trainer_type<trainer_type> roc_c2_trainer ( const trainer_type& trainer, const typename trainer_type::scalar_type& desired_accuracy ) { return roc_trainer_type<trainer_type>(trainer, desired_accuracy, -1); } // ---------------------------------------------------------------------------------------- } #endif // DLIB_ROC_TRAINEr_H_