SHOGUN
v3.2.0
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 3 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * Written (W) 2012 Fernando José Iglesias García 00008 * Copyright (C) 2012 Fernando José Iglesias García 00009 */ 00010 00011 #ifdef HAVE_LAPACK 00012 00013 #include <shogun/lib/common.h> 00014 #include <shogun/io/SGIO.h> 00015 #include <shogun/distance/MahalanobisDistance.h> 00016 #include <shogun/features/Features.h> 00017 #include <shogun/mathematics/Math.h> 00018 #include <shogun/mathematics/lapack.h> 00019 00020 using namespace shogun; 00021 00022 CMahalanobisDistance::CMahalanobisDistance() : CRealDistance() 00023 { 00024 init(); 00025 } 00026 00027 CMahalanobisDistance::CMahalanobisDistance(CDenseFeatures<float64_t>* l, CDenseFeatures<float64_t>* r) 00028 : CRealDistance() 00029 { 00030 init(); 00031 init(l, r); 00032 } 00033 00034 CMahalanobisDistance::~CMahalanobisDistance() 00035 { 00036 cleanup(); 00037 } 00038 00039 bool CMahalanobisDistance::init(CFeatures* l, CFeatures* r) 00040 { 00041 CRealDistance::init(l, r); 00042 00043 00044 if ( l == r) 00045 { 00046 mean = ((CDenseFeatures<float64_t>*) l)->get_mean(); 00047 icov = ((CDenseFeatures<float64_t>*) l)->get_cov(); 00048 } 00049 else 00050 { 00051 mean = ((CDenseFeatures<float64_t>*) l)->get_mean((CDotFeatures*) lhs, (CDotFeatures*) rhs); 00052 icov = CDotFeatures::compute_cov((CDotFeatures*) lhs, (CDotFeatures*) rhs); 00053 } 00054 00055 SGMatrix<float64_t>::inverse(icov); 00056 00057 return true; 00058 } 00059 00060 void CMahalanobisDistance::cleanup() 00061 { 00062 } 00063 00064 float64_t CMahalanobisDistance::compute(int32_t idx_a, int32_t idx_b) 00065 { 00066 00067 SGVector<float64_t> bvec = ((CDenseFeatures<float64_t>*) rhs)-> 00068 get_feature_vector(idx_b); 00069 00070 SGVector<float64_t> diff; 00071 SGVector<float64_t> avec; 00072 00073 if (use_mean) 00074 diff = mean.clone(); 00075 else 00076 { 00077 avec = ((CDenseFeatures<float64_t>*) lhs)->get_feature_vector(idx_a); 00078 diff=avec.clone(); 00079 } 00080 00081 ASSERT(diff.vlen == bvec.vlen) 00082 00083 for (int32_t i=0; i < diff.vlen; i++) 00084 diff[i] = bvec.vector[i] - diff[i]; 00085 00086 SGVector<float64_t> v = diff.clone(); 00087 cblas_dgemv(CblasColMajor, CblasNoTrans, 00088 icov.num_rows, icov.num_cols, 1.0, icov.matrix, 00089 diff.vlen, diff.vector, 1, 0.0, v.vector, 1); 00090 00091 float64_t result = cblas_ddot(v.vlen, v.vector, 1, diff.vector, 1); 00092 00093 if (!use_mean) 00094 ((CDenseFeatures<float64_t>*) lhs)->free_feature_vector(avec, idx_a); 00095 00096 ((CDenseFeatures<float64_t>*) rhs)->free_feature_vector(bvec, idx_b); 00097 00098 if (disable_sqrt) 00099 return result; 00100 else 00101 return CMath::sqrt(result); 00102 } 00103 00104 void CMahalanobisDistance::init() 00105 { 00106 disable_sqrt=false; 00107 use_mean=false; 00108 00109 m_parameters->add(&disable_sqrt, "disable_sqrt", "If sqrt shall not be applied."); 00110 m_parameters->add(&use_mean, "use_mean", "If distance shall be computed between mean vector and vector from rhs or between lhs and rhs."); 00111 } 00112 00113 #endif /* HAVE_LAPACK */