PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // SecondIterationWrapper.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: SecondIterationWrapper.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 "SecondIterationWrapper.h" 00043 #include <plearn/vmat/FileVMatrix.h> 00044 00045 namespace PLearn { 00046 using namespace std; 00047 00048 PLEARN_IMPLEMENT_OBJECT(SecondIterationWrapper, 00049 "A PLearner to wrap around a generic regressor to calculate the predicted class.", 00050 "Algorithm built to wrap around a generic regressor in the context of the second iteration\n" 00051 "of the annual sales estimation project.\n" 00052 "It calculates the predicted class and computes the cse error. It do not work with classifier\n" 00053 ); 00054 00055 SecondIterationWrapper::SecondIterationWrapper() 00056 : class_prediction(1) 00057 { 00058 } 00059 00060 SecondIterationWrapper::~SecondIterationWrapper() 00061 { 00062 } 00063 00064 void SecondIterationWrapper::declareOptions(OptionList& ol) 00065 { 00066 declareOption(ol, "class_prediction", &SecondIterationWrapper::class_prediction, OptionBase::buildoption, 00067 "When set to 1 (default), indicates the base regression is on the class target.\n" 00068 "Otherwise, we assume the regression is on the sales target.\n"); 00069 00070 declareOption(ol, "base_regressor_template", &SecondIterationWrapper::base_regressor_template, OptionBase::buildoption, 00071 "The template for the base regressor to be used.\n"); 00072 00073 declareOption(ol, "ref_train", &SecondIterationWrapper::ref_train, OptionBase::buildoption, 00074 "The reference set to compute train statistics.\n"); 00075 00076 declareOption(ol, "ref_test", &SecondIterationWrapper::ref_test, OptionBase::buildoption, 00077 "The reference set to compute test statistice.\n"); 00078 00079 declareOption(ol, "ref_sales", &SecondIterationWrapper::ref_sales, OptionBase::buildoption, 00080 "The reference set to de-gaussianize the prediction.\n"); 00081 00082 declareOption(ol, "train_dataset", &SecondIterationWrapper::train_dataset, OptionBase::buildoption, 00083 "The train data set.\n"); 00084 00085 declareOption(ol, "test_dataset", &SecondIterationWrapper::test_dataset, OptionBase::buildoption, 00086 "The test data set.\n"); 00087 00088 declareOption(ol, "base_regressor", &SecondIterationWrapper::base_regressor, OptionBase::learntoption, 00089 "The base regressor built from the template.\n"); 00090 inherited::declareOptions(ol); 00091 } 00092 00093 void SecondIterationWrapper::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00094 { 00095 inherited::makeDeepCopyFromShallowCopy(copies); 00096 deepCopyField(class_prediction, copies); 00097 deepCopyField(ref_train, copies); 00098 deepCopyField(ref_test, copies); 00099 deepCopyField(ref_sales, copies); 00100 deepCopyField(test_dataset, copies); 00101 deepCopyField(base_regressor_template, copies); 00102 deepCopyField(base_regressor, copies); 00103 } 00104 00105 void SecondIterationWrapper::build() 00106 { 00107 inherited::build(); 00108 build_(); 00109 } 00110 00111 void SecondIterationWrapper::build_() 00112 { 00113 if (train_set) 00114 { 00115 if (class_prediction == 0) 00116 if(!ref_train || !ref_test || !ref_test || !train_dataset || !test_dataset) 00117 PLERROR("In SecondIterationWrapper: missing reference data sets to compute statistics"); 00118 margin = 0; 00119 loan = 1; 00120 sales = 2; 00121 tclass = 3; 00122 base_regressor = ::PLearn::deepCopy(base_regressor_template); 00123 base_regressor->setTrainingSet(train_set, true); 00124 base_regressor->setTrainStatsCollector(new VecStatsCollector); 00125 if (class_prediction == 0) search_table = ref_sales->toMat(); 00126 sample_input.resize(train_set->inputsize()); 00127 sample_target.resize(train_set->targetsize()); 00128 sample_output.resize(base_regressor->outputsize()); 00129 sample_costs.resize(4); 00130 } 00131 } 00132 00133 void SecondIterationWrapper::train() 00134 { 00135 base_regressor->nstages = nstages; 00136 base_regressor->train(); 00137 if (class_prediction == 1) computeClassStatistics(); 00138 else computeSalesStatistics(); 00139 } 00140 00141 void SecondIterationWrapper::computeClassStatistics() 00142 { 00143 real sample_weight; 00144 ProgressBar* pb = NULL; 00145 if (report_progress) 00146 pb = new ProgressBar("Second Iteration : computing the train statistics: ", 00147 train_set->length()); 00148 00149 train_stats->forget(); 00150 for (int row = 0; row < train_set->length(); row++) 00151 { 00152 train_set->getExample(row, sample_input, sample_target, sample_weight); 00153 computeOutput(sample_input, sample_output); 00154 computeCostsFromOutputs(sample_input, sample_output, sample_target, sample_costs); 00155 train_stats->update(sample_costs); 00156 if (report_progress) pb->update(row); 00157 } 00158 train_stats->finalize(); 00159 if (report_progress) delete pb; 00160 } 00161 00162 void SecondIterationWrapper::computeSalesStatistics() 00163 { 00164 int row; 00165 Vec sample_input(train_set->inputsize()); 00166 Vec sample_target(train_set->targetsize()); 00167 Vec reference_vector(ref_train->width()); 00168 real sample_weight; 00169 Vec sample_output(base_regressor->outputsize()); 00170 Vec sample_costs(4); 00171 Vec train_mean(3); 00172 Vec train_std_error(3); 00173 Vec valid_mean(3); 00174 Vec valid_std_error(3); 00175 Vec test_mean(3); 00176 Vec test_std_error(3); 00177 real sales_prediction; 00178 real commitment; 00179 real predicted_class; 00180 ProgressBar* pb = NULL; 00181 if (report_progress) 00182 { 00183 pb = new ProgressBar("Second Iteration : computing the train statistics: ", train_set->length()); 00184 } 00185 train_stats->forget(); 00186 for (row = 0; row < train_set->length(); row++) 00187 { 00188 train_set->getExample(row, sample_input, sample_target, sample_weight); 00189 ref_train->getRow(row, reference_vector); 00190 computeOutput(sample_input, sample_output); 00191 sales_prediction = deGaussianize(sample_output[0]); 00192 commitment = 0.0; 00193 if (!is_missing(reference_vector[margin])) commitment += reference_vector[margin]; 00194 if (!is_missing(reference_vector[loan])) commitment += reference_vector[loan]; 00195 if (sales_prediction < 1000000.0 && commitment < 200000.0) predicted_class = 1.0; 00196 else if (sales_prediction < 10000000.0 && commitment < 1000000.0) predicted_class = 2.0; 00197 else if (sales_prediction < 100000000.0 && commitment < 20000000.0) predicted_class = 3.0; 00198 else predicted_class = 4.0; 00199 sample_costs[0] = pow((sales_prediction - reference_vector[sales]), 2); 00200 sample_costs[1] = pow((predicted_class - reference_vector[tclass]), 2); 00201 if (predicted_class == reference_vector[tclass]) sample_costs[2] = 0.0; 00202 else sample_costs[2] = 1.0; 00203 train_stats->update(sample_costs); 00204 if (report_progress) pb->update(row); 00205 } 00206 train_stats->finalize(); 00207 train_mean << train_stats->getMean(); 00208 train_std_error << train_stats->getStdError(); 00209 if (report_progress) delete pb; 00210 if (report_progress) 00211 { 00212 pb = new ProgressBar("Second Iteration : computing the valid statistics: ", train_dataset->length() - train_set->length()); 00213 } 00214 train_stats->forget(); 00215 for (row = train_set->length(); row < train_dataset->length(); row++) 00216 { 00217 train_dataset->getExample(row, sample_input, sample_target, sample_weight); 00218 ref_train->getRow(row, reference_vector); 00219 computeOutput(sample_input, sample_output); 00220 sales_prediction = deGaussianize(sample_output[0]); 00221 commitment = 0.0; 00222 if (!is_missing(reference_vector[margin])) commitment += reference_vector[margin]; 00223 if (!is_missing(reference_vector[loan])) commitment += reference_vector[loan]; 00224 if (sales_prediction < 1000000.0 && commitment < 200000.0) predicted_class = 1.0; 00225 else if (sales_prediction < 10000000.0 && commitment < 1000000.0) predicted_class = 2.0; 00226 else if (sales_prediction < 100000000.0 && commitment < 20000000.0) predicted_class = 3.0; 00227 else predicted_class = 4.0; 00228 sample_costs[0] = pow((sales_prediction - reference_vector[sales]), 2); 00229 sample_costs[1] = pow((predicted_class - reference_vector[tclass]), 2); 00230 if (predicted_class == reference_vector[tclass]) sample_costs[2] = 0.0; 00231 else sample_costs[2] = 1.0; 00232 train_stats->update(sample_costs); 00233 if (report_progress) pb->update(row); 00234 } 00235 train_stats->finalize(); 00236 valid_mean << train_stats->getMean(); 00237 valid_std_error << train_stats->getStdError(); 00238 if (report_progress) delete pb; 00239 if (report_progress) 00240 { 00241 pb = new ProgressBar("Second Iteration : computing the test statistics: ", test_dataset->length()); 00242 } 00243 train_stats->forget(); 00244 for (row = 0; row < test_dataset->length(); row++) 00245 { 00246 test_dataset->getExample(row, sample_input, sample_target, sample_weight); 00247 ref_test->getRow(row, reference_vector); 00248 computeOutput(sample_input, sample_output); 00249 sales_prediction = deGaussianize(sample_output[0]); 00250 commitment = 0.0; 00251 if (!is_missing(reference_vector[margin])) commitment += reference_vector[margin]; 00252 if (!is_missing(reference_vector[loan])) commitment += reference_vector[loan]; 00253 if (sales_prediction < 1000000.0 && commitment < 200000.0) predicted_class = 1.0; 00254 else if (sales_prediction < 10000000.0 && commitment < 1000000.0) predicted_class = 2.0; 00255 else if (sales_prediction < 100000000.0 && commitment < 20000000.0) predicted_class = 3.0; 00256 else predicted_class = 4.0; 00257 sample_costs[0] = pow((sales_prediction - reference_vector[sales]), 2); 00258 sample_costs[1] = pow((predicted_class - reference_vector[tclass]), 2); 00259 if (predicted_class == reference_vector[tclass]) sample_costs[2] = 0.0; 00260 else sample_costs[2] = 1.0; 00261 train_stats->update(sample_costs); 00262 if (report_progress) pb->update(row); 00263 } 00264 train_stats->finalize(); 00265 test_mean << train_stats->getMean(); 00266 test_std_error << train_stats->getStdError(); 00267 if (report_progress) delete pb; 00268 TVec<string> stat_names(6); 00269 stat_names[0] = "mse"; 00270 stat_names[1] = "mse_stderr"; 00271 stat_names[2] = "cse"; 00272 stat_names[3] = "cse_stderr"; 00273 stat_names[4] = "cle"; 00274 stat_names[5] = "cle_stderr"; 00275 VMat stat_file = new FileVMatrix(expdir + "class_stats.pmat", 3, stat_names); 00276 stat_file->put(0, 0, train_mean[0]); 00277 stat_file->put(0, 1, train_std_error[0]); 00278 stat_file->put(0, 2, train_mean[1]); 00279 stat_file->put(0, 3, train_std_error[1]); 00280 stat_file->put(0, 4, train_mean[2]); 00281 stat_file->put(0, 5, train_std_error[2]); 00282 stat_file->put(1, 0, valid_mean[0]); 00283 stat_file->put(1, 1, valid_std_error[0]); 00284 stat_file->put(1, 2, valid_mean[1]); 00285 stat_file->put(1, 3, valid_std_error[1]); 00286 stat_file->put(1, 4, valid_mean[2]); 00287 stat_file->put(1, 5, valid_std_error[2]); 00288 stat_file->put(2, 0, test_mean[0]); 00289 stat_file->put(2, 1, test_std_error[0]); 00290 stat_file->put(2, 2, test_mean[1]); 00291 stat_file->put(2, 3, test_std_error[1]); 00292 stat_file->put(2, 4, test_mean[2]); 00293 stat_file->put(2, 5, test_std_error[2]); 00294 } 00295 00296 real SecondIterationWrapper::deGaussianize(real prediction) 00297 { 00298 if (prediction < search_table(0, 0)) return search_table(0, 1); 00299 if (prediction > search_table(search_table.length() - 1, 0)) return search_table(search_table.length() - 1, 1); 00300 int mid; 00301 int min = 0; 00302 int max = search_table.length() - 1; 00303 while (max - min > 1) 00304 { 00305 mid = (max + min) / 2; 00306 real mid_val = search_table(mid, 0); 00307 if (prediction < mid_val) max = mid; 00308 else if (prediction > mid_val) min = mid; 00309 else min = max = mid; 00310 } 00311 if (min == max) return search_table(min, 1); 00312 return (search_table(min, 1) + search_table(max, 1)) / 2.0; 00313 } 00314 00315 void SecondIterationWrapper::forget() 00316 { 00317 } 00318 00319 int SecondIterationWrapper::outputsize() const 00320 { 00321 return base_regressor?base_regressor->outputsize():-1; 00322 } 00323 00324 TVec<string> SecondIterationWrapper::getTrainCostNames() const 00325 { 00326 TVec<string> return_msg(4); 00327 return_msg[0] = "mse"; 00328 return_msg[1] = "square_class_error"; 00329 return_msg[2] = "linear_class_error"; 00330 return_msg[3] = "class_error"; 00331 return return_msg; 00332 } 00333 00334 TVec<string> SecondIterationWrapper::getTestCostNames() const 00335 { 00336 return getTrainCostNames(); 00337 } 00338 00339 void SecondIterationWrapper::computeOutput(const Vec& inputv, Vec& outputv) const 00340 { 00341 base_regressor->computeOutput(inputv, outputv); 00342 } 00343 00344 void SecondIterationWrapper::computeOutputAndCosts(const Vec& inputv, const Vec& targetv, Vec& outputv, Vec& costsv) const 00345 { 00346 computeOutput(inputv, outputv); 00347 computeCostsFromOutputs(inputv, outputv, targetv, costsv); 00348 } 00349 00350 void SecondIterationWrapper::computeCostsFromOutputs(const Vec& inputv, const Vec& outputv, const Vec& targetv, Vec& costsv) const 00351 { 00352 costsv[0] = pow((outputv[0] - targetv[0]), 2); 00353 if (class_prediction == 1) 00354 { 00355 real class_pred; 00356 if (outputv[0] <= 0.5) class_pred = 0.; 00357 else if (outputv[0] <= 1.5) class_pred = 1.0; 00358 // else if (outputv[0] <= 2.5) class_pred = 2.0; 00359 else class_pred = 2.0; 00360 costsv[1] = pow((class_pred - targetv[0]), 2); 00361 costsv[2] = fabs(class_pred - targetv[0]); 00362 costsv[3] = class_pred == targetv[0]?0:1; 00363 return; 00364 } 00365 costsv[1] = 0.0; 00366 costsv[2] = 0.0; 00367 costsv[3] = 0.0; 00368 } 00369 00370 } // end of namespace PLearn 00371 00372 00373 /* 00374 Local Variables: 00375 mode:c++ 00376 c-basic-offset:4 00377 c-file-style:"stroustrup" 00378 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00379 indent-tabs-mode:nil 00380 fill-column:79 00381 End: 00382 */ 00383 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :