PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // MovingAverageVMatrix.cc 00004 // 00005 // Copyright (C) 2004 Yoshua Bengio 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 /* ******************************************************* 00036 * $Id: MovingAverageVMatrix.cc 8607 2008-02-29 17:11:46Z nouiz $ 00037 ******************************************************* */ 00038 00039 // Authors: Yoshua Bengio 00040 00044 #include "MovingAverageVMatrix.h" 00045 #include <plearn/base/tostring.h> 00046 00047 namespace PLearn { 00048 using namespace std; 00049 00050 00051 MovingAverageVMatrix::MovingAverageVMatrix() 00052 :inherited(), centered_windows(true) 00053 /* ### Initialise all fields to their default value */ 00054 { 00055 // ... 00056 00057 // ### You may or may not want to call build_() to finish building the object 00058 // build_(); 00059 } 00060 00061 PLEARN_IMPLEMENT_OBJECT(MovingAverageVMatrix, "Perform moving average of given columns", 00062 "The user specifies one or more columns and for each such <column-name>\n" 00063 "a moving average window size: a ma<windowsize>-<column-name> column is\n" 00064 "created which will contain at row t the moving average from row t-<windowsize>+1\n" 00065 "to t inclusively of <column-name>.\n"); 00066 00067 void MovingAverageVMatrix::getNewRow(int i, Vec& v) const 00068 { 00069 source->getRow(i,sourcerow); 00070 int max_target = centered_windows?min(i+max_window_size/2,length()-1):i; 00071 if (is_missing(sums(max_target,0))) 00072 { 00073 int k=max_target-1; 00074 while (k>=0 && is_missing(sums(k,0))) k--; 00075 if (k<0) 00076 { 00077 k=0; 00078 source->getRow(k,previous_sourcerow); 00079 for (int j=0;j<columns.length();j++) 00080 { 00081 real new_value = previous_sourcerow[columns[j]]; 00082 if (is_missing(new_value)) 00083 { 00084 sums(k,j) = 0; 00085 ma(k,j) = MISSING_VALUE; 00086 } 00087 else 00088 { 00089 sums(k,j) = new_value; 00090 nnonmissing(k,j) = 1; 00091 ma(k,j) = new_value; 00092 } 00093 } 00094 } 00095 for (;k<max_target;k++) 00096 { 00097 source->getRow(k+1,previous_sourcerow); 00098 for (int j=0;j<columns.length();j++) 00099 { 00100 real new_value = previous_sourcerow[columns[j]]; 00101 if (!is_missing(new_value)) 00102 { 00103 sums(k+1,j) = sums(k,j) + new_value; 00104 nnonmissing(k+1,j) = nnonmissing(k,j) + 1; 00105 } 00106 else sums(k+1,j) = sums(k,j); 00107 int delta = k+1-window_sizes[j]; 00108 int n_at_window_start = (delta>=0)?nnonmissing(delta,j):0; 00109 int n = nnonmissing(k+1,j) - n_at_window_start; 00110 if (n>0) 00111 { 00112 if (delta>=0) 00113 ma(k+1,j) = (sums(k+1,j) - sums(delta,j))/n; 00114 else 00115 ma(k+1,j) = sums(k+1,j)/n; 00116 } 00117 else 00118 ma(k+1,j) = MISSING_VALUE; 00119 } 00120 } 00121 } 00122 for (int j=0;j<columns_to_average.length();j++) 00123 { 00124 int target = centered_windows?min(i+window_sizes[j]/2,length()-1):i; 00125 row[sourcerow.length()+j]=ma(target,j); 00126 } 00127 v << row; 00128 } 00129 00130 void MovingAverageVMatrix::declareOptions(OptionList& ol) 00131 { 00132 // ### Declare all of this object's options here 00133 // ### For the "flags" of each option, you should typically specify 00134 // ### one of OptionBase::buildoption, OptionBase::learntoption or 00135 // ### OptionBase::tuningoption. Another possible flag to be combined with 00136 // ### is OptionBase::nosave 00137 00138 declareOption(ol, "columns_to_average", &MovingAverageVMatrix::columns_to_average, OptionBase::buildoption, 00139 "Names of the columns to average."); 00140 00141 declareOption(ol, "window_sizes", &MovingAverageVMatrix::window_sizes, OptionBase::buildoption, 00142 "Sizes (in number of rows) of the moving average windows for each column to average."); 00143 00144 declareOption(ol, "centered_windows", &MovingAverageVMatrix::centered_windows, OptionBase::buildoption, 00145 "Wether or not to center the window around the current example or to average only over previous examples"); 00146 00147 // Now call the parent class' declareOptions 00148 inherited::declareOptions(ol); 00149 } 00150 00151 void MovingAverageVMatrix::build_() 00152 { 00153 int nc=columns_to_average.length(); 00154 if (source) 00155 { 00156 row.resize(source->width()+nc); 00157 sourcerow = row.subVec(0,source->width()); 00158 previous_sourcerow.resize(source->width()); 00159 columns.resize(nc); 00160 max_window_size=0; 00161 if (window_sizes.length()!=nc) 00162 PLERROR("MovingAverageVMatrix: the window_sizes option should have the same length as the columns_to_average option (got %d and %d)", 00163 window_sizes.length(),nc); 00164 for (int j=0;j<nc;j++) 00165 { 00166 if ((columns[j] = source->fieldIndex(columns_to_average[j])) == -1) 00167 PLERROR("MovingAverageVMatrix: provided field name %s not found in source VMatrix",columns_to_average[j].c_str()); 00168 if (window_sizes[j]>max_window_size) 00169 max_window_size=window_sizes[j]; 00170 } 00171 00172 updateMtime(source); 00173 00174 // copy length and width from source if not set 00175 if(length_<0) 00176 length_ = source->length(); 00177 if(width_<0) 00178 width_ = source->width() + nc; 00179 00180 sums.resize(length_,nc); 00181 sums.fill(MISSING_VALUE); 00182 nnonmissing.resize(length_,nc); 00183 nnonmissing.clear(); 00184 ma.resize(length_,nc); 00185 ma.fill(MISSING_VALUE); 00186 00187 // copy fieldnames from source if not set and they look good 00188 if(!hasFieldInfos() && source->hasFieldInfos() ) 00189 { 00190 Array<VMField>& sinfo = source->getFieldInfos(); 00191 int w=sinfo.size(); 00192 sinfo.resize(w+nc); 00193 for (int j=0;j<nc;j++) 00194 { 00195 sinfo[w+j]=sinfo[columns[j]]; 00196 sinfo[w+j].name = "ma"+tostring(window_sizes[j])+"-"+sinfo[w+j].name; 00197 } 00198 setFieldInfos(sinfo); 00199 } 00200 } 00201 } 00202 00203 // ### Nothing to add here, simply calls build_ 00204 void MovingAverageVMatrix::build() 00205 { 00206 inherited::build(); 00207 build_(); 00208 } 00209 00210 void MovingAverageVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00211 { 00212 inherited::makeDeepCopyFromShallowCopy(copies); 00213 00214 deepCopyField(columns, copies); 00215 deepCopyField(columns_to_average, copies); 00216 deepCopyField(sums, copies); 00217 deepCopyField(window_sizes, copies); 00218 00219 } 00220 00221 } // end of namespace PLearn 00222 00223 00224 /* 00225 Local Variables: 00226 mode:c++ 00227 c-basic-offset:4 00228 c-file-style:"stroustrup" 00229 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00230 indent-tabs-mode:nil 00231 fill-column:79 00232 End: 00233 */ 00234 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :