ECOCPAK v0.9
fn_fqmi.hpp
Go to the documentation of this file.
00001 // Copyright (C) 2011 the authors listed below
00002 // http://ecocpak.sourceforge.net
00003 // 
00004 // Authors:
00005 // - Dimitrios Bouzas (bouzas at ieee dot org)
00006 // - Nikolaos Arvanitopoulos (niarvani at ieee dot org)
00007 // - Anastasios Tefas (tefas at aiia dot csd dot auth dot gr)
00008 // 
00009 // This file is part of the ECOC PAK C++ library. It is 
00010 // provided without any warranty of fitness for any purpose.
00011 //
00012 // You can redistribute this file and/or modify it under 
00013 // the terms of the GNU Lesser General Public License (LGPL) 
00014 // as published by the Free Software Foundation, either 
00015 // version 3 of the License or (at your option) any later 
00016 // version.
00017 // (see http://www.opensource.org/licenses for more info)
00018 
00019 
00022 
00023 
00024 
00038 double 
00039 compute_sigma
00040   (
00041   const vector<ClassData>& classes_vector
00042   )
00043   {  
00044   double maximum = 0.0;
00045   double d = 0.0;
00046   
00047   // create samples matrix
00048   mat samples = create_samples_matrix(classes_vector);
00049   
00050   const u32 n_rows_j = samples.n_rows;
00051   const u32 n_rows_i = samples.n_rows - 1;
00052 
00053         // find the minimum distance between all the samples in the set
00054   for(u32 i  = 0; i < n_rows_i; i++)
00055     {
00056     for(u32 j = i + 1; j < n_rows_j; j++)
00057       {
00058       // compute distance as the Euclidean norm
00059       d = norm(samples.row(i) - samples.row(j), 2);
00060       
00061       if(maximum < d)
00062         {
00063         maximum = d;
00064         }
00065 
00066       }
00067     
00068     } 
00069 
00070   return maximum / 2.0;
00071   }
00072 
00073 
00074 
00100 template<typename T1, typename T2>
00101 typename T1::elem_type
00102 fqmi
00103   (
00104   const Base<typename T1::elem_type, T1>& X, 
00105   const Base<typename T2::elem_type, T2>& Y,
00106   const      typename T1::elem_type       sigma
00107   )
00108   {
00109   arma_extra_debug_sigprint();
00110   
00111   // alias to element type of samples' matrix
00112   typedef typename T1::elem_type eT1;
00113   
00114   // alias to element type of labels' vector 
00115   typedef typename T2::elem_type eT2;
00116   
00117   // unwrap samples matrix
00118   const unwrap<T1>             tmp_X(X.get_ref());
00119   const   Mat<eT1>& samples =  tmp_X.M;
00120   
00121   // unwrap labels vector
00122   const unwrap<T2>        tmp_Y(Y.get_ref());
00123   const Mat<eT2> labels = tmp_Y.M;
00124   
00125   // number of samples
00126   const u32 n_samples = samples.n_rows;
00127   
00128   // number of attributes
00129   const u32 n_attributes = samples.n_cols;
00130   
00131   // check whether input labels is a vector
00132   arma_debug_check
00133     (
00134     (labels.is_vec() == false), 
00135     "fqmi(): Input class labels should be a vector"
00136     );
00137   
00138   // check whether input labels number of elements is equal to the 
00139   // number of samples
00140   arma_debug_check
00141     (
00142     labels.n_elem != n_samples, 
00143     "fqmi(): Input class labels must have the same number of elements with the number of input samples"
00144     );
00145   
00146   // Initialize VIN, VALL and VBTW terms to zero.
00147   
00148   // VIN can be seen as interactions between pairs of
00149   // samples inside each class.
00150   eT1 vin  = 0;
00151   
00152   // VBTW consists of interactions between samples of
00153   // each class against all other samples.
00154   eT1 vbtw = 0;
00155   
00156   // VALL consists of interactions between all pairs of
00157   // samples, regardless of class membership.
00158   eT1 vall = 0;
00159 
00160   // find number of classes
00161   // find number of samples in each class
00162   // create new labels that start from one if necessary
00163   u32 n_classes = 0;   
00164   Col<eT1> n_samples_each_class;
00165   Col<eT2> new_labels = 
00166     process_labels(labels, n_samples_each_class, n_classes);
00167 
00168   // compute normalization constant for later use
00169   eT1 n_samples_square = 1.0 / eT1(n_samples * n_samples);
00170 
00171   // compute normalization constant for later use
00172   eT1 v = 2 * sigma * sigma;
00173   
00174   // compact expression used in the kernel for later use
00175   eT1 exp_sigma = eT1(-1) / eT1(2 * v);
00176   
00177   // compute normalization constant for later use
00178   eT1 nc = 
00179     eT1(1) /  eT1
00180                 (
00181                 std::sqrt
00182                   (
00183                   std::pow(2.0 * math::pi(), 
00184                   n_attributes) * std::pow(v, n_attributes)
00185                   )
00186                 );
00187   
00188   // initialize temporary vector VBTW_tmp to hold intermediate 
00189   // computations of VBTW term actually each position of vbtw_tmp 
00190   // corresponds to a class label and holds the sums of the VBTW term 
00191   // for each of the available classes
00192   Col<eT1> vbtw_tmp = zeros< Col<eT1> >(n_classes);
00193   
00194   // initialize temporary scalar to hold intermediate computation of the 
00195   // kernel
00196   eT1 tmp = 0;
00197   
00198   // double for to compute the interactions of all samples with each 
00199   // other it needs N^2 / 2 iterations, where N is the number of samples
00200   
00201   // iterate through samples
00202   for(u32 i = 0; i < n_samples; i++)
00203     {
00204     // compute self interaction of the ith sample
00205     // exponential becomes zero and consequently 
00206     // interaction is a constant as such update
00207     // VIN, VALL and VBTW accordingly
00208     vall += nc;
00209     vbtw_tmp[labels[i] - 1] += nc;
00210     vin  += nc;
00211     
00212     // compute interaction of ith sample with the rest of the samples
00213     for(u32 j = i + 1; j < n_samples; j++)
00214       {
00215       // compute the difference between ith and jth vectors
00216       Row<eT1> centered_sample = samples.row(i) - samples.row(j);
00217   
00218       // compute kernel
00219       tmp = 
00220         nc * std::exp
00221                (
00222                exp_sigma * accu(centered_sample % centered_sample)
00223                );
00224 
00225       // update each of term VALL, VBTW and VIN accordingly
00226       
00227       // multiply the kernel result by 2 because k(i,j) = k(j,i)
00228       vall += (2 * tmp);
00229       
00230       // update the sum jth sample's class
00231       vbtw_tmp[labels[j] - 1] += tmp;
00232       
00233       // update the sum jth sample's class
00234       vbtw_tmp[labels[i] - 1] += tmp;
00235       
00236       // kernel result contributes to the VIN sum if ith and jth
00237       // samples belong to the same class (i.e., their respective
00238       // class labels are equal)
00239       if(labels[i] == labels[j])
00240         {
00241         // multiply the kernel result by 2 because k(i,j) = k(j,i)
00242         vin += (2 * tmp);
00243         }
00244    
00245       }
00246     
00247     }
00248 
00249   // normalization of VIN, VBTW and VALL terms
00250   vall = 
00251     accu
00252       (
00253         (
00254         n_samples_each_class % n_samples_each_class
00255         ) * 
00256         n_samples_square * vall
00257       ) * 
00258       n_samples_square;
00259       
00260   vbtw = 
00261     n_samples_square * 
00262     accu(vbtw_tmp % n_samples_each_class) / eT1(n_samples);
00263     
00264   vin *= n_samples_square;
00265   
00266   // compute and return MI value from vin, vall and vbtw terms
00267   
00268   // equation is obtained by using a Parzen estimate with a
00269   // symmetrical Gaussian kernel of width sigma
00270   return (vin + vall) - (2.0 * vbtw);
00271   }
00272 
00273 
00274 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerator Defines