PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // RegressionTreeMulticlassLeaveFast.cc 00004 // Copyright (c) 1998-2002 Pascal Vincent 00005 // Copyright (C) 1999-2002 Yoshua Bengio and University of Montreal 00006 // Copyright (c) 2002 Jean-Sebastien Senecal, Xavier Saint-Mleux, Rejean Ducharme 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 /* ******************************************************************************** 00038 * $Id: RegressionTreeMulticlassLeaveFast.cc, v 1.0 2004/07/19 10:00:00 Bengio/Kegl/Godbout * 00039 * This file is part of the PLearn library. * 00040 ******************************************************************************** */ 00041 00042 #include "RegressionTreeMulticlassLeaveFast.h" 00043 #include "RegressionTreeRegisters.h" 00044 #include <plearn/math/TMat_maths_impl.h> 00045 00046 namespace PLearn { 00047 using namespace std; 00048 00049 PLEARN_IMPLEMENT_OBJECT(RegressionTreeMulticlassLeaveFast, 00050 "Object to represent the leaves of a regression tree.", 00051 "It maintains the necessary statistics to compute the output and the train error\n" 00052 "of the samples in the leave.\n" 00053 ); 00054 00055 RegressionTreeMulticlassLeaveFast::RegressionTreeMulticlassLeaveFast() 00056 : nb_class(-1), 00057 objective_function("l1") 00058 { 00059 build(); 00060 } 00061 00062 RegressionTreeMulticlassLeaveFast::~RegressionTreeMulticlassLeaveFast() 00063 { 00064 } 00065 00066 void RegressionTreeMulticlassLeaveFast::declareOptions(OptionList& ol) 00067 { 00068 inherited::declareOptions(ol); 00069 00070 declareOption(ol, "nb_class", 00071 &RegressionTreeMulticlassLeaveFast::nb_class, 00072 OptionBase::buildoption, 00073 "The number of class. Should be numbered from 0 to nb_class -1.\n" 00074 ); 00075 declareOption(ol, "objective_function", 00076 &RegressionTreeMulticlassLeaveFast::objective_function, 00077 OptionBase::buildoption, 00078 "The function to be used to compute the leave error.\n" 00079 "Current supported values are l1 and l2 (default is l1)."); 00080 00081 declareOption(ol, "multiclass_weights_sum", 00082 &RegressionTreeMulticlassLeaveFast::multiclass_weights_sum, 00083 OptionBase::learntoption, 00084 "A vector to count the weight sum of each possible output " 00085 "for the sample in this leave.\n"); 00086 redeclareOption(ol, "loss_function_factor", 00087 &RegressionTreeMulticlassLeaveFast::loss_function_factor, 00088 OptionBase::learntoption, 00089 "The loss fct factor. Depend of the objective_function.\n"); 00090 } 00091 00092 void RegressionTreeMulticlassLeaveFast::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00093 { 00094 inherited::makeDeepCopyFromShallowCopy(copies); 00095 deepCopyField(objective_function, copies); 00096 deepCopyField(multiclass_weights_sum, copies); 00097 } 00098 00099 void RegressionTreeMulticlassLeaveFast::build() 00100 { 00101 inherited::build(); 00102 build_(); 00103 } 00104 00105 void RegressionTreeMulticlassLeaveFast::build_() 00106 { 00107 } 00108 00109 void RegressionTreeMulticlassLeaveFast::initStats() 00110 { 00111 length_ = 0; 00112 weights_sum = 0.0; 00113 if (loss_function_weight != 0.0) 00114 { 00115 if(objective_function == "l1") 00116 loss_function_factor = 2.0 / loss_function_weight; 00117 else 00118 loss_function_factor = 2.0 / pow(loss_function_weight, 2); 00119 } 00120 else 00121 { 00122 loss_function_factor = 1.0; 00123 } 00124 multiclass_weights_sum.resize(nb_class); 00125 multiclass_weights_sum.fill(0); 00126 } 00127 00128 void RegressionTreeMulticlassLeaveFast::addRow(int row) 00129 { 00130 real weight = train_set->getWeight(row); 00131 real target = train_set->getTarget(row); 00132 RegressionTreeMulticlassLeaveFast::addRow(row, target, weight); 00133 } 00134 00135 void RegressionTreeMulticlassLeaveFast::addRow(int row, real target, real weight, 00136 Vec outputv, Vec errorv) 00137 { 00138 RegressionTreeMulticlassLeaveFast::addRow(row, target, weight); 00139 RegressionTreeMulticlassLeaveFast::getOutputAndError(outputv,errorv); 00140 } 00141 00142 void RegressionTreeMulticlassLeaveFast::addRow(int row, real target, real weight) 00143 { 00144 length_ += 1; 00145 weights_sum += weight; 00146 multiclass_weights_sum[int(target)] += weight; 00147 } 00148 00149 void RegressionTreeMulticlassLeaveFast::addRow(int row, Vec outputv, Vec errorv) 00150 { 00151 RegressionTreeMulticlassLeaveFast::addRow(row); 00152 RegressionTreeMulticlassLeaveFast::getOutputAndError(outputv,errorv); 00153 } 00154 00155 void RegressionTreeMulticlassLeaveFast::removeRow(int row, Vec outputv, Vec errorv) 00156 { 00157 real weight = train_set->getWeight(row); 00158 real target = train_set->getTarget(row); 00159 RegressionTreeMulticlassLeaveFast::removeRow(row,target,weight,outputv,errorv); 00160 } 00161 00162 void RegressionTreeMulticlassLeaveFast::removeRow(int row, real target, real weight, 00163 Vec outputv, Vec errorv){ 00164 RegressionTreeMulticlassLeaveFast::removeRow(row,target,weight); 00165 RegressionTreeMulticlassLeaveFast::getOutputAndError(outputv,errorv); 00166 } 00167 00168 void RegressionTreeMulticlassLeaveFast::removeRow(int row, real target, real weight) 00169 { 00170 length_ -= 1; 00171 weights_sum -= weight; 00172 PLASSERT(length_>=0); 00173 PLASSERT(weights_sum>=0); 00174 PLASSERT(length_>0 || weights_sum==0); 00175 multiclass_weights_sum[int(target)] -= weight; 00176 } 00177 00178 void RegressionTreeMulticlassLeaveFast::getOutputAndError(Vec& output, Vec& error)const 00179 { 00180 #ifdef BOUNDCHECK 00181 if(nb_class<=0) 00182 PLERROR("In RegressionTreeMulticlassLeaveFast::getOutputAndError() -" 00183 " nb_class must be set."); 00184 #endif 00185 if(length_==0){ 00186 output.clear(); 00187 output[0]=MISSING_VALUE; 00188 error.clear(); 00189 return; 00190 } 00191 int mc_winer = 0; 00192 real conf = 0; 00193 //index of the max. Is their an optimized version? 00194 for (int mc_ind = 1; mc_ind < nb_class; mc_ind++) 00195 { 00196 if (multiclass_weights_sum[mc_ind] > multiclass_weights_sum[mc_winer]) 00197 mc_winer = mc_ind; 00198 } 00199 output[0] = mc_winer; 00200 if (missing_leave) 00201 { 00202 error[0] = 0.0; 00203 error[1] = weights_sum; 00204 error[2] = 0.0; 00205 } 00206 else 00207 { 00208 conf = multiclass_weights_sum[mc_winer] / weights_sum; 00209 error[0] = 0.0; 00210 if (objective_function == "l1") 00211 { 00212 for (int mc_ind = 0; mc_ind < nb_class;mc_ind++) 00213 { 00214 error[0] += abs(mc_winer - mc_ind) 00215 * multiclass_weights_sum[mc_ind]; 00216 } 00217 } 00218 else 00219 { 00220 for (int mc_ind = 0; mc_ind < nb_class;mc_ind++) 00221 { 00222 error[0] += pow(mc_winer - mc_ind, 2.) 00223 * multiclass_weights_sum[mc_ind]; 00224 } 00225 } 00226 error[0] *= loss_function_factor * length_ / weights_sum; 00227 if (error[0] < 1E-10) error[0] = 0.0; 00228 if (error[0] > weights_sum * loss_function_factor) 00229 error[2] = weights_sum * loss_function_factor; 00230 else error[2] = error[0]; 00231 error[1] = (1.0 - conf) * length_; 00232 } 00233 if(output_confidence_target) output[1] = conf; 00234 } 00235 00236 TVec<string> RegressionTreeMulticlassLeaveFast::getOutputNames() const 00237 { 00238 TVec<string> ret; 00239 ret.append("class_pred"); 00240 if(output_confidence_target) 00241 ret.append("confidence"); 00242 return ret; 00243 } 00244 00245 void RegressionTreeMulticlassLeaveFast::addLeave(PP<RegressionTreeLeave> leave_){ 00246 PP<RegressionTreeMulticlassLeaveFast> leave = (PP<RegressionTreeMulticlassLeaveFast>) leave_; 00247 00248 if(leave->classname() == classname()){ 00249 length_ += leave->length_; 00250 weights_sum += leave->weights_sum; 00251 multiclass_weights_sum += leave->multiclass_weights_sum; 00252 }else 00253 PLERROR("In %s::addLeave the leave to add should have the same class. It have %s.", 00254 classname().c_str(), leave->classname().c_str()); 00255 } 00256 00257 void RegressionTreeMulticlassLeaveFast::removeLeave(PP<RegressionTreeLeave> leave_){ 00258 PP<RegressionTreeMulticlassLeaveFast> leave = (PP<RegressionTreeMulticlassLeaveFast>) leave_; 00259 00260 if(leave->classname() == classname()){ 00261 length_ -= leave->length_; 00262 weights_sum -= leave->weights_sum; 00263 multiclass_weights_sum -= leave->multiclass_weights_sum; 00264 }else 00265 PLERROR("In %s::addLeave the leave to add should have the same class. It have %s.", 00266 classname().c_str(), leave->classname().c_str()); 00267 } 00268 00269 void RegressionTreeMulticlassLeaveFast::printStats() 00270 { 00271 cout << " l " << length_; 00272 Vec output(2); 00273 Vec error(3); 00274 getOutputAndError(output,error); 00275 cout << " o0 " << output[0]; 00276 cout << " o1 " << output[1]; 00277 cout << " e0 " << error[0]; 00278 cout << " e1 " << error[1]; 00279 cout << " ws " << weights_sum; 00280 cout << endl; 00281 cout << " mws " << multiclass_weights_sum << endl; 00282 } 00283 00284 } // end of namespace PLearn 00285 00286 00287 /* 00288 Local Variables: 00289 mode:c++ 00290 c-basic-offset:4 00291 c-file-style:"stroustrup" 00292 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00293 indent-tabs-mode:nil 00294 fill-column:79 00295 End: 00296 */ 00297 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :