PLearn 0.1
Cov2CorrVariable.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Cov2CorrVariable.cc
00004 //
00005 // Copyright (C) 2008 Pascal Vincent
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: Pascal Vincent
00036 
00039 #include "Cov2CorrVariable.h"
00040 //#include "Var_operators.h"
00041 //#include "Var_utils.h"
00042 
00043 namespace PLearn {
00044 using namespace std;
00045 
00046 
00049 PLEARN_IMPLEMENT_OBJECT(
00050         Cov2CorrVariable,
00051         "Convert a covariance matrix to a correlation matrix",
00052         "i.e. it divides off-diagonal term A_ij by sqrt(A_ii A_jj + epsilon).\n"
00053         "Diagonal terms are set according to option diaognal_choice\n"
00054 );
00055 
00057 // Cov2CorrVariable //
00059 
00060 Cov2CorrVariable::Cov2CorrVariable():
00061     diagonal_choice(1),
00062     epsilon(0.)
00063 {}
00064 
00065 Cov2CorrVariable::Cov2CorrVariable(Variable* input, int diagonal_choice_,
00066                                    double epsilon_, bool call_build_):
00067     inherited(input, input->length(), input->width(), call_build_),
00068     diagonal_choice(diagonal_choice_),
00069     epsilon(epsilon_)
00070 {
00071     if (call_build_)
00072         build_();
00073 }
00074 
00075 void Cov2CorrVariable::declareOptions(OptionList& ol)
00076 {
00077     declareOption(
00078         ol, "diagonal_choice", &Cov2CorrVariable::diagonal_choice, OptionBase::buildoption,
00079         "Controls how to fill the diagonal.\n"
00080         "  0: fill it with 0\n"
00081         "  1: fill it with 1\n"
00082         "  2: keep the diagonal of the input (i.e. the original variances)\n");
00083     declareOption(
00084         ol, "epsilon", &Cov2CorrVariable::epsilon, OptionBase::buildoption,
00085         "value to add to product of variances before taking their sqrt.\n");
00086     inherited::declareOptions(ol);
00087 }
00088 
00090 // build //
00092 void Cov2CorrVariable::build() {
00093     inherited::build();
00094     build_();
00095 }
00096 
00098 // build_ //
00100 void Cov2CorrVariable::build_() {
00101     // Nothing to do here.
00102 }
00103 
00105 // recomputeSize //
00107 void Cov2CorrVariable::recomputeSize(int& l, int& w) const
00108 {
00109     if (input) {
00110         l = input->length();
00111         w = input->width();
00112     } else
00113         l = w = 0;
00114 }
00115 
00116 
00117 void Cov2CorrVariable::fprop()
00118 {
00119     Mat C = input->matValue;
00120     int l = C.length();
00121     int w = C.width();
00122     for(int i=0; i<l; i++)
00123         for(int j=0; j<w; j++)
00124         {
00125             if(i!=j)
00126                 matValue(i,j) = C(i,j)/sqrt(C(i,i)*C(j,j)+epsilon);
00127             else // diagonal element
00128             {
00129                 double diagval = 0;
00130                 switch(diagonal_choice)
00131                 {
00132                 case 0:
00133                     diagval = 0;
00134                     break;
00135                 case 1:
00136                     diagval = 1;
00137                     break;
00138                 case 2:
00139                     diagval = C(i,j);
00140                     break;
00141                 default:
00142                     PLERROR("Invalid diagonal_choice option");
00143                 }
00144                 matValue(i,j) = diagval;
00145             }
00146         }
00147 }
00148 
00149 /*
00150   Let C the covariance matrix and D the correlation matrix.
00151   D_ij = C_ij (C_ii C_jj + epsilon)^(-1/2)
00152 
00153   dL/dC_ij = \sum_i'j' dL/dD_i'j' dD_i'j'/dC_ij
00154  
00155   case i!=j:
00156      dL/dC_ij = dL/dD_ij dD_ij/dC_ij
00157               = dL/dD_ij (C_ii C_jj + epsilon)^(-1/2)
00158               = dL/dD_ij D_ij/C_ij
00159 
00160   case i==j
00161 
00162     D_ik = C_ik (C_ii C_kk + epsilon)^(-1/2)
00163     dD_ik/dC_ii = C_ik (-1/2) C_kk (C_ii C_kk + epsilon)^(-3/2)
00164                 = -1/2 C_kk D_ik / (C_ii C_kk + epsilon)
00165     D_ki = C_ki (C_kk C_ii + epsilon)^(-1/2)
00166     dD_ki/dC_ii = C_ki (-1/2) C_kk (C_kk C_ii + epsilon)^(-3/2)
00167                 = -1/2 C_kk D_ki / (C_ii C_kk + epsilon)
00168 
00169      dL/dC_ii = \sum_{k!=i}{   dL/dD_ik dD_ik/dC_ii 
00170                              + dL/dD_ki dD_ki/dC_ii }
00171               = \sum_{k!=i}{   dL/dD_ik [ -1/2 C_kk D_ik/(C_ii C_kk + epsilon) ]
00172                              + dL/dD_ki [ -1/2 C_kk D_ki/(C_ii C_kk + epsilon) ]
00173 
00174 */
00175 
00176 void Cov2CorrVariable::bprop()
00177 {
00178     Mat C = input->matValue;
00179     Mat Cg = input->matGradient;
00180     Mat D = matValue;
00181     Mat Dg = matGradient;
00182     int l = C.length();
00183     int w = C.width();
00184     for(int i=0; i<l; i++)
00185         for(int j=0; j<w; j++)
00186         {
00187             if(i!=j)
00188             {
00189                 Cg(i,j) += Dg(i,j)*D(i,j)/C(i,j);
00190                 double h = -0.5*Dg(i,j)*D(i,j)/(C(i,i)*C(j,j)+epsilon);
00191                 Cg(i,i) += C(j,j)*h;
00192                 Cg(j,j) += C(i,i)*h;
00193             }
00194             else if(diagonal_choice==2)
00195                 Cg(i,i) += Dg(i,i);
00196         }
00197 }
00198 
00199 
00200 void Cov2CorrVariable::bbprop()
00201 {
00202     PLERROR("bbprop not implemented for this variable");
00203 }
00204 
00205 
00206 void Cov2CorrVariable::symbolicBprop()
00207 {
00208     PLERROR("symbolic bprop not yet implemented for this variable");
00209 }
00210 
00211 
00212 void Cov2CorrVariable::rfprop()
00213 {
00214     PLERROR("rfprop no yet implemented for this vairable");
00215 }
00216 
00217 
00218 
00219 } // end of namespace PLearn
00220 
00221 
00222 /*
00223   Local Variables:
00224   mode:c++
00225   c-basic-offset:4
00226   c-file-style:"stroustrup"
00227   c-file-offsets:((innamespace . 0)(inline-open . 0))
00228   indent-tabs-mode:nil
00229   fill-column:79
00230   End:
00231 */
00232 // 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