PLearn 0.1
|
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 :