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