PLearn 0.1
MixUnlabeledNeighbourVMatrix.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // MixUnlabeledNeighbourVMatrix.cc
00004 //
00005 // Copyright (C) 2006 Pierre-Jean L Heureux
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: Pierre-Jean L Heureux
00036 
00039 #include "MixUnlabeledNeighbourVMatrix.h"
00040 #include <plearn_learners/generic/PLearner.h>
00041 
00042 namespace PLearn {
00043 using namespace std;
00044 
00045 PLEARN_IMPLEMENT_OBJECT(
00046     MixUnlabeledNeighbourVMatrix,
00047     "For a given labeled dataset, find related examples in a second dataset.",
00048     "The last target column of the two dataset contains the relational key. \n"
00049     " The output will be a merged VMat with the labeled example on top \n"
00050     " and a selection of unlabeled related example at the bottom. The \n"
00051     " relational key column must be a string AND will be discarded. We force \n"
00052     " MISSING_VALUE for the target of unlabeled example. We put the 'weight' \n"
00053     " of the first occuring labeled example inside the realted unlabeled examples.\n"
00054     "WARNING: We sort the unlabeled dataset according to the key.\n"
00055     );
00056 
00058 // MixUnlabeledNeighbourVMatrix //
00060 MixUnlabeledNeighbourVMatrix::MixUnlabeledNeighbourVMatrix() :
00061 /* ### Initialize all fields to their default value */
00062     seed(-1),
00063     frac(1),
00064     random_generator(new PRandom())
00065 {
00066     // ...
00067     // ### You may (or not) want to call build_() to finish building the object
00068     // ### (doing so assumes the parent classes' build_() have been called too
00069     // ### in the parent classes' constructors, something that you must ensure)
00070 }
00071 
00073 // declareOptions //
00075 void MixUnlabeledNeighbourVMatrix::declareOptions(OptionList& ol)
00076 {
00077     // ### Declare all of this object's options here
00078     // ### For the "flags" of each option, you should typically specify
00079     // ### one of OptionBase::buildoption, OptionBase::learntoption or
00080     // ### OptionBase::tuningoption. Another possible flag to be combined with
00081     // ### is OptionBase::nosave
00082 
00083     declareOption(ol, "seed", &MixUnlabeledNeighbourVMatrix::seed, OptionBase::buildoption, "Random generator seed (>0) (exceptions : -1 = initialized from clock, 0 = no initialization).");
00084     declareOption(ol, "source_select", &MixUnlabeledNeighbourVMatrix::source_select, OptionBase::buildoption, "The VMat containing the related examples.");
00085     declareOption(ol, "frac", &MixUnlabeledNeighbourVMatrix::frac, OptionBase::buildoption, "Fraction of the bag of related examples to be randomly chosen");
00086 
00087     // Now call the parent class' declareOptions
00088     inherited::declareOptions(ol);
00089 }
00090 
00092 // build //
00094 void MixUnlabeledNeighbourVMatrix::build()
00095 {
00096     // ### Nothing to add here, simply calls build_
00097     inherited::build();
00098     build_();
00099 }
00100 
00102 // build_ //
00104 void MixUnlabeledNeighbourVMatrix::build_()
00105 {
00106     // ### This method should do the real building of the object,
00107     // ### according to set 'options', in *any* situation.
00108     // ### Typical situations include:
00109     // ###  - Initial building of an object from a few user-specified options
00110     // ###  - Building of a "reloaded" object: i.e. from the complete set of all serialised options.
00111     // ###  - Updating or "re-building" of an object after a few "tuning" options have been modified.
00112     // ### You should assume that the parent class' build_() has already been called.
00113 
00114     random_generator->manual_seed(seed);
00115 
00116     if (!source)
00117         return;
00118 
00119     if (source && ( source->targetsize() < 1))
00120         PLERROR("In MixUnlabeledNeighbourVMatrix::build_ - We need a key column for 'source'");
00121     if (source_select && (source_select->targetsize() < 1))
00122         PLERROR("In MixUnlabeledNeighbourVMatrix::build_ - We need a key column for 'source_select'");
00123     if (source_select && source && source_select->inputsize() != source->inputsize())
00124         PLERROR("In MixUnlabeledNeighbourVMatrix::build_ - VMats 'source_select'"
00125                 "and 'source' should have the same inputsize().");
00126 
00127     indices.resize(0); // This get rid of the user's build option value.
00128     TVec<int> bag_indices;
00129     Vec input,target,targetSel;
00130     string lastKey;
00131     real weight;
00132     bool sourceFound;
00133     int rowSel,row;
00134     int keyCol = source->inputsize() + source->targetsize()-1;
00135     neighbor_weights.resize(0);
00136 
00137     if (source_select){ // If it was given, find the related example
00138         int keyCol_select = source_select->inputsize() + source_select->targetsize()-1;
00139         sorted_source_select = new SortRowsVMatrix();
00140         sorted_source_select->source = source_select;
00141         sorted_source_select->sort_columns = TVec<int>(1,keyCol_select);
00142         sorted_source_select->build();
00143         sorted_source_select->getExample(0,input,targetSel,weight);
00144         lastKey = sorted_source_select->getValString(keyCol_select,targetSel.lastElement());
00145         rowSel = 0;
00146         bag_indices.resize(0);
00147         while(rowSel < sorted_source_select->length()){
00148             sorted_source_select->getExample(rowSel,input,targetSel,weight);
00149             if (lastKey == sorted_source_select->getValString(keyCol_select,
00150                                                        targetSel.lastElement())){
00151                 bag_indices.push_back(rowSel);
00152             }else{
00153                 sourceFound = (lastKey == "all");
00154                 for(row=0; row < source->length() && !sourceFound; row++){
00155                     source->getExample(row,input,target,weight);
00156                     if(lastKey == source->getValString(keyCol,target.lastElement())) sourceFound=true;
00157                 }
00158                 if (sourceFound){
00159                     random_generator->shuffleElements(bag_indices);
00160                     int n_kept = int(round(frac*bag_indices.length()));
00161                     for(int i=0; i < n_kept; i++) {
00162                         if (source->weightsize() > 0) {
00163                             PLASSERT( source->weightsize() == 1 );
00164                             neighbor_weights.append(weight); // normally still pointing to the correct weight
00165                         }
00166                         indices.push_back(bag_indices[i]);
00167                     }
00168                 }
00169                 bag_indices.resize(0);
00170                 lastKey = sorted_source_select->getValString(keyCol_select,targetSel.lastElement());
00171                 bag_indices.push_back(rowSel);
00172             }
00173             rowSel++;
00174             if (rowSel == sorted_source_select->length()){
00175                 sourceFound = (lastKey == "all");
00176                 for(row=0; row < source->length() && !sourceFound; row++){
00177                     source->getExample(row,input,target,weight);
00178                     if(lastKey == source->getValString(keyCol,target.lastElement())) sourceFound=true;
00179                 }
00180                 if (sourceFound){
00181                     random_generator->shuffleElements(bag_indices);
00182                     int n_kept = int(round(frac*bag_indices.length()));
00183                     for(int i=0; i < n_kept; i++) {
00184                         if (source->weightsize() > 0) {
00185                             PLASSERT( source->weightsize() == 1 );
00186                             neighbor_weights.append(weight); // normally still pointing to the correct weight
00187                         }
00188                         indices.push_back(bag_indices[i]);
00189                     }
00190                 }
00191             }
00192         }
00193         updateMtime(source_select);
00194     }
00195     // ?? Modify the width, length, (targetsize, inputsize and weight) size attribute.
00196     inputsize_ = source->inputsize();
00197     targetsize_ = source->targetsize()-1;
00198     weightsize_ = source->weightsize();
00199     width_ = source->width()-1;
00200 
00201     if(source_select) {
00202         length_ = source->length() + indices.length();
00203     }else{
00204         length_ = source->length();
00205     }
00206 
00207     TVec<string>tempofn = source->fieldNames();
00208     tempofn.remove(inputsize()+targetsize());
00209     declareFieldNames(tempofn);
00210     // ### In a SourceVMatrix, you will typically end build_() with:
00211     setMetaInfoFromSource();
00212 }
00213 
00215 // getNewRow //
00217 void MixUnlabeledNeighbourVMatrix::getNewRow(int i, const Vec& v) const
00218 {
00219     if (i < source->length()) {
00220         row_buffer.resize(source->width());
00221         source->getRow(i, row_buffer);
00222         int rest_size = width() - inputsize() - targetsize();
00223         int input_target_size = inputsize() + targetsize();
00224         v.subVec(0, input_target_size)
00225             << row_buffer.subVec(0, input_target_size);
00226         v.subVec(input_target_size, rest_size)
00227             << row_buffer.subVec(input_target_size + 1, rest_size);
00228     } else {
00229         sorted_source_select->getSubRow(indices[i - source->length()],0,
00230                                  v.subVec(0,inputsize()));
00231         for (int j=inputsize(); j < inputsize() + targetsize(); j++)
00232             v[j]=MISSING_VALUE;
00233         if (!neighbor_weights.isEmpty())
00234             v[v.length() - 1] = neighbor_weights[i - source->length()];
00235     }
00236 }
00237 
00239 // makeDeepCopyFromShallowCopy //
00241 void MixUnlabeledNeighbourVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00242 {
00243     inherited::makeDeepCopyFromShallowCopy(copies);
00244 
00245     deepCopyField(indices, copies);
00246     deepCopyField(source_select, copies);
00247     deepCopyField(sorted_source_select, copies);
00248     deepCopyField(random_generator, copies);
00249     deepCopyField(row_buffer, copies);
00250     deepCopyField(neighbor_weights, copies);
00251 }
00252 
00253 } // end of namespace PLearn
00254 
00255 
00256 /*
00257   Local Variables:
00258   mode:c++
00259   c-basic-offset:4
00260   c-file-style:"stroustrup"
00261   c-file-offsets:((innamespace . 0)(inline-open . 0))
00262   indent-tabs-mode:nil
00263   fill-column:79
00264   End:
00265 */
00266 // 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