PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // plearn_learners/generic/TransformOutputLearner.cc 00004 // 00005 // Copyright (C) 2007 Frederic Bastien 00006 // 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 // Authors: Frederic Bastien 00036 00040 #include "plearn_learners/generic/TransformOutputLearner.h" 00041 00042 namespace PLearn { 00043 using namespace std; 00044 00045 PLEARN_IMPLEMENT_OBJECT( 00046 TransformOutputLearner, 00047 "Transform a Learner who give the log probality as output to give the probability as output", 00048 "MULTI-LINE \nHELP"); 00049 00050 TransformOutputLearner::TransformOutputLearner() 00051 :inherited(), 00052 output_function(-1), 00053 warning0(true), 00054 warning1(true) 00055 { 00056 forward_test=true; 00057 } 00058 00059 void TransformOutputLearner::declareOptions(OptionList& ol) 00060 { 00061 // ### Declare all of this object's options here. 00062 // ### For the "flags" of each option, you should typically specify 00063 // ### one of OptionBase::buildoption, OptionBase::learntoption or 00064 // ### OptionBase::tuningoption. If you don't provide one of these three, 00065 // ### this option will be ignored when loading values from a script. 00066 // ### You can also combine flags, for example with OptionBase::nosave: 00067 // ### (OptionBase::buildoption | OptionBase::nosave) 00068 00069 // ### ex: 00070 // declareOption(ol, "myoption", &TransformOutputLearner::myoption, 00071 // OptionBase::buildoption, 00072 // "Help text describing this option"); 00073 // ... 00074 declareOption(ol, "output_function", &TransformOutputLearner::output_function, 00075 OptionBase::buildoption, 00076 "The operation to do on the output\n" 00077 "0: We transform the sublearner log probability output to probability output\n" 00078 "1: We transform the sublearner probability output of class to class output\n" 00079 "2: We transform the sublearner regression output to class output."); 00080 00081 // Now call the parent class' declareOptions 00082 inherited::declareOptions(ol); 00083 } 00084 00085 void TransformOutputLearner::build_() 00086 { 00087 tmp_output2.resize(learner_->outputsize()); 00088 } 00089 00090 // ### Nothing to add here, simply calls build_ 00091 void TransformOutputLearner::build() 00092 { 00093 inherited::build(); 00094 build_(); 00095 } 00096 00097 void TransformOutputLearner::computeOutput(const Vec& input, Vec& output) const 00098 { 00099 // Compute the output from the input. 00100 // int nout = outputsize(); 00101 // output.resize(nout); 00102 // ... 00103 if(output_function==0){//logprob to prob 00104 learner_->computeOutput(input,output); 00105 exp(output,output); 00106 }else if(output_function==1){//logprob or prob to class 00107 learner_->computeOutput(input,tmp_output2); 00108 output[0]=argmax(tmp_output2); 00109 }else if(output_function==2){//Regression to class v1 00110 learner_->computeOutput(input,tmp_output2); 00111 output[0]=int(round(tmp_output2[0])); 00112 // }else if(output_function==2){//Regression to class v2 00113 // learner_->computeOutput(input, output); 00114 // if (multiclass_outputs.length() <= 0) return; 00115 // real closest_value=multiclass_outputs[0]; 00116 // real margin_to_closest_value=abs(output[0] - multiclass_outputs[0]); 00117 // for (int value_ind = 1; value_ind < multiclass_outputs.length(); value_ind++) 00118 // { 00119 // real v=abs(output[0] - multiclass_outputs[value_ind]); 00120 // if (v < margin_to_closest_value) 00121 // { 00122 // closest_value = multiclass_outputs[value_ind]; 00123 // margin_to_closest_value = v; 00124 // } 00125 // } 00126 // output[0] = closest_value; 00127 }else 00128 PLERROR("In TransformOutputLearner::computeOutput - unknow output_function %d",output_function); 00129 } 00130 00131 void TransformOutputLearner::computeCostsFromOutputs(const Vec& input, const Vec& output, 00132 const Vec& target, Vec& costs) const 00133 { 00134 PLASSERT( learner_ ); 00135 if(output_function==0){ 00136 if(warning0){ 00137 PLWARNING("In TransformOutputLearner::computeCostsFromOutputs - you are loosing precision"); 00138 warning0=false; 00139 } 00140 compute_log(output,tmp_output2); 00141 learner_->computeCostsFromOutputs(input,tmp_output2,target,costs); 00142 }else if(output_function==1 || output_function==2){ 00143 if(warning1){ 00144 PLWARNING("In TransformOutputLearner::computeCostsFromOutputs - we can't compute the costs from\n" 00145 "outputs with output_function %d. We use TransformOutputLearner::computeOutputAndCosts.",output_function); 00146 warning1=false; 00147 } 00148 computeOutputAndCosts(input,target,tmp_output2,costs); 00149 }else 00150 PLERROR("In TransformOutputLearner::computeCostsFromOutputs - unknow output_function %d",output_function); 00151 } 00152 void TransformOutputLearner::computeOutputAndCosts(const Vec& input, const Vec& target, 00153 Vec& output, Vec& costs) const 00154 { 00155 PLASSERT( learner_ ); 00156 if(output_function==0){//logprob to prob 00157 learner_->computeOutputAndCosts(input,target,output,costs); 00158 exp(output,output); 00159 }else if(output_function==1){//logprob or prob to class 00160 learner_->computeOutputAndCosts(input,target,tmp_output2,costs); 00161 output[0]=argmax(output); 00162 }else if(output_function==2){//Regression to class v1 00163 learner_->computeOutputAndCosts(input,target,tmp_output2,costs); 00164 output[0]=int(round(tmp_output2[0])); 00165 }else 00166 PLERROR("In TransformOutputLearner::computeOutputAndCosts - unknow output_function %d",output_function); 00167 } 00168 00169 void TransformOutputLearner::test(VMat testset, PP<VecStatsCollector> test_stats, 00170 VMat testoutputs, VMat testcosts) const 00171 { 00172 PLASSERT( learner_ ); 00173 if(output_function==0){ 00174 learner_->test(testset, test_stats, testoutputs, testcosts); 00175 for(int i = 0;i<testoutputs.length();i++){ 00176 Vec v = testoutputs(i); 00177 exp(v,v); 00178 } 00179 } 00180 else 00181 PLERROR("In TransformOutputLearner::test"); 00182 } 00183 int TransformOutputLearner::outputsize() const 00184 { 00185 PLASSERT( learner_ ); 00186 if(output_function==0) 00187 return learner_->outputsize(); 00188 else if (output_function==1 || output_function==2) 00189 return 1; 00190 else 00191 PLERROR("In TransformOutputLearner::outputsize"); 00192 return -1; 00193 } 00194 00195 } // end of namespace PLearn 00196 00197 00198 /* 00199 Local Variables: 00200 mode:c++ 00201 c-basic-offset:4 00202 c-file-style:"stroustrup" 00203 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00204 indent-tabs-mode:nil 00205 fill-column:79 00206 End: 00207 */ 00208 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :