PLearn 0.1
SecondIterationWrapper.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines