PLearn 0.1
ClassifierFromConditionalPDistribution.cc
Go to the documentation of this file.
00001 
00002 // -*- C++ -*-
00003 
00004 // ClassifierFromConditionalPDistribution.cc
00005 //
00006 // Copyright (C) 2003-2005  Pascal Vincent & Olivier Delalleau
00007 // 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are met:
00010 // 
00011 //  1. Redistributions of source code must retain the above copyright
00012 //     notice, this list of conditions and the following disclaimer.
00013 // 
00014 //  2. Redistributions in binary form must reproduce the above copyright
00015 //     notice, this list of conditions and the following disclaimer in the
00016 //     documentation and/or other materials provided with the distribution.
00017 // 
00018 //  3. The name of the authors may not be used to endorse or promote
00019 //     products derived from this software without specific prior written
00020 //     permission.
00021 // 
00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 // 
00033 // This file is part of the PLearn library. For more information on the PLearn
00034 // library, go to the PLearn Web site at www.plearn.org
00035 
00036 /* *******************************************************      
00037  * $Id: ClassifierFromConditionalPDistribution.cc 4412 2005-11-02 19:00:20Z tihocan $ 
00038  ******************************************************* */
00039 
00041 #include "ClassifierFromConditionalPDistribution.h"
00042 #include <plearn/io/PPath.h>
00043 
00044 namespace PLearn {
00045 using namespace std;
00046 
00047 ClassifierFromConditionalPDistribution::ClassifierFromConditionalPDistribution() 
00048     : nclasses(-1),
00049       output_type("predicted_class")
00050 {}
00051 
00052 PLEARN_IMPLEMENT_OBJECT(
00053     ClassifierFromConditionalPDistribution,
00054     "Classifier that takes a ConditionalPDistribution and classifies with it.", 
00055     "ClassifierFromConditionalPDistribution classifies by finding the target\n"
00056     "class y that maximizes p(y|x), where x is the input.\n");
00057 
00059 // declareOptions //
00061 void ClassifierFromConditionalPDistribution::declareOptions(OptionList& ol)
00062 {
00063 
00064     // Build options.
00065 
00066     declareOption(ol, "nclasses", &ClassifierFromConditionalPDistribution::nclasses, OptionBase::buildoption,
00067                   "The number of classes");
00068 
00069     declareOption(ol, "conditional_distribution", &ClassifierFromConditionalPDistribution::pcd, OptionBase::buildoption,
00070                   "ConditionalPDistribution that computes p(y|x) for all possible classes y.");
00071 
00072     declareOption(ol, "output_type", &ClassifierFromConditionalPDistribution::output_type, OptionBase::buildoption,
00073                   "Output type. Choose among: \n"
00074                   "- \"predicted_class\"\n"
00075                   "- \"class_probabilities\"\n"
00076                   "- \"class_log-probabilities\")\n"
00077                   "Note that this may change the value of output_defs of the conditional_distribution.");
00078  
00079     // Now call the parent class' declareOptions
00080     inherited::declareOptions(ol);
00081 }
00082 
00084 // build //
00086 void ClassifierFromConditionalPDistribution::build()
00087 {
00088     inherited::build();
00089     build_();
00090 }
00091 
00093 // build_ //
00095 void ClassifierFromConditionalPDistribution::build_()
00096 {
00097     if(pcd && train_set)
00098     {
00099         PP<Dictionary> target_dict = train_set->getDictionary(inputsize());
00100         if(!target_dict && nclasses <= 0) PLERROR("In ClassifierFromConditionalPDistribution::build_(): There is not way to know what are the possible targets (nclasses <= 0 and no Dictionary for target field)");
00101         if(target_dict) nclasses = -1;
00102         if(output_type == "predicted_class" || output_type == "class_log-probabilities") pcd->outputs_def = "l";
00103         else if (output_type == "class_probabilities") pcd->outputs_def = "d";
00104         else PLERROR("ClassifierFromConditionalPDistribution::build_(): output_type %s is not supported", output_type.c_str());
00105 
00106         pcd_input.resize(train_set->inputsize() + train_set->targetsize());
00107         pcd_output.resize(1);
00108     }
00109 
00110 }
00111 
00113 // makeDeepCopyFromShallowCopy //
00115 void ClassifierFromConditionalPDistribution::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00116 {
00117     inherited::makeDeepCopyFromShallowCopy(copies);
00118     deepCopyField(pcd, copies);
00119     deepCopyField(target_values, copies);
00120     deepCopyField(pcd_input, copies);
00121 }
00122 
00124 // outputsize //
00126 int ClassifierFromConditionalPDistribution::outputsize() const
00127 {
00128     if(nclasses > 0) return nclasses;
00129     else
00130     {
00131         train_set->getValues(0,inputsize(),target_values);
00132         return target_values.length();
00133     }
00134 }
00135 
00137 // forget //
00139 void ClassifierFromConditionalPDistribution::forget()
00140 {
00141     stage=0;
00142     pcd->forget();
00143 }
00144 
00146 // train //
00148 void ClassifierFromConditionalPDistribution::train()
00149 {
00150     if(targetsize()!=1)
00151         PLERROR("In ClassifierFromConditionalPDistribution::train - Expecting a targetsize of 1, not %d !!",targetsize());
00152 
00153     if(nstages<stage) // asking to revert to a previous stage!
00154         forget();  // reset the learner to stage=0
00155 
00156     if(stage==0)
00157     {
00158         pcd->setExperimentDirectory(getExperimentDirectory() / "PCD");
00159         train_set->defineSizes(inputsize()+1,targetsize()-1,weightsize());
00160         pcd->setTrainingSet(train_set);
00161         PP<VecStatsCollector> train_stats = new VecStatsCollector();
00162         train_stats->setFieldNames(pcd->getTrainCostNames());
00163         pcd->setTrainStatsCollector(train_stats);
00164         pcd->nstages = nstages;
00165         if (verbosity >= 2)
00166         pout << ">>> Training ConditionalPDistribution" << endl;    
00167         pcd->train();
00168         if (verbosity >= 2)
00169         pout << ">>> Training is over" << endl;    
00170         train_set->defineSizes(inputsize(),targetsize(),weightsize());
00171     }
00172     stage = nstages; // trained!
00173 }
00174 
00176 // computeOutput //
00178 void ClassifierFromConditionalPDistribution::computeOutput(const Vec& input, Vec& output) const
00179 {    
00180     pcd_input.subVec(0,inputsize()) << input;
00181     if(nclasses <= 0)
00182     {   
00183         train_set->getValues(input, inputsize(),target_values);
00184         output.resize(target_values.length());
00185         for(int i=0; i<target_values.length(); i++)
00186         {
00187             pcd_input[inputsize()] = target_values[i];            
00188             pcd->computeOutput(pcd_input, pcd_output);
00189             output[i] = pcd_output[0];
00190         }
00191     }
00192     else
00193     {
00194         output.resize(nclasses);
00195         for(int c=0; c<nclasses; c++)
00196         {
00197             pcd_input[inputsize()] = c;
00198             pcd->computeOutput(pcd_input, pcd_output);
00199             output[c] = pcd_output[0];
00200         }     
00201     }
00202 
00203     if(output_type == "predicted_class") 
00204     {
00205         if(nclasses <= 0)
00206             output[0] = (int)target_values[argmax(output)];
00207         else
00208             output[0] = argmax(output);
00209         output.resize(1);
00210     }
00211 }
00212 
00214 // computeCostsFromOutputs //
00216 void ClassifierFromConditionalPDistribution::computeCostsFromOutputs(const Vec& input, const Vec& output, 
00217                                                     const Vec& target, Vec& costs) const
00218 {
00219     if(output_type == "predicted_class")
00220     {
00221         costs[0] = (int) (target[0] != output[0]);
00222     }
00223     else
00224     {
00225         int c;
00226         if(nclasses <= 0)
00227         {
00228             train_set->getValues(input,inputsize(),target_values);
00229             c = target_values.find(target[0]);           
00230         }
00231         else
00232             c = (int)target[0];
00233         costs[0] = (int) (argmax(output) != c);
00234         if(output_type == "class_probabilities") costs[1] = safeflog(output[c]);
00235         else costs[1] = output[c];
00236     }
00237 }                                
00238 
00240 // getTestCostNames //
00242 TVec<string> ClassifierFromConditionalPDistribution::getTestCostNames() const
00243 {
00244     TVec<string> cnames;    
00245     if(output_type == "predicted_class")
00246     {
00247         cnames.resize(1);
00248         cnames[0] = "class_error";
00249     }
00250     else
00251     {
00252         cnames.resize(2);
00253         cnames[0] = "class_error";
00254         cnames[1] = "NLL";
00255     }
00256     return cnames;
00257 }
00258 
00260 // getTrainCostNames //
00262 TVec<string> ClassifierFromConditionalPDistribution::getTrainCostNames() const
00263 {
00264     return TVec<string>();
00265 }
00266 
00267 } // end of namespace PLearn
00268 
00269 
00270 /*
00271   Local Variables:
00272   mode:c++
00273   c-basic-offset:4
00274   c-file-style:"stroustrup"
00275   c-file-offsets:((innamespace . 0)(inline-open . 0))
00276   indent-tabs-mode:nil
00277   fill-column:79
00278   End:
00279 */
00280 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines