Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
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