[mlpack-git] master: Generalize metrics to arbitrary types. (c566aaf)

gitdub at mlpack.org gitdub at mlpack.org
Wed Jun 8 10:05:13 EDT 2016


Repository : https://github.com/mlpack/mlpack
On branch  : master
Link       : https://github.com/mlpack/mlpack/compare/8551a21f9821399ded164d8dbb11e453bcb33c45...e8e2ff17da5978cacf3c9a45d4aa572a4bf008e5

>---------------------------------------------------------------

commit c566aaf3549a3863acab39f874d9cbd492ea07b0
Author: Ryan Curtin <ryan at ratml.org>
Date:   Wed Jun 8 14:04:53 2016 +0000

    Generalize metrics to arbitrary types.


>---------------------------------------------------------------

c566aaf3549a3863acab39f874d9cbd492ea07b0
 src/mlpack/core/metrics/ip_metric.hpp      |  2 +-
 src/mlpack/core/metrics/ip_metric_impl.hpp | 10 +++---
 src/mlpack/core/metrics/lmetric.hpp        |  3 +-
 src/mlpack/core/metrics/lmetric_impl.hpp   | 57 +++++++++++++++++++-----------
 4 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/src/mlpack/core/metrics/ip_metric.hpp b/src/mlpack/core/metrics/ip_metric.hpp
index d8caf2f..b55ace8 100644
--- a/src/mlpack/core/metrics/ip_metric.hpp
+++ b/src/mlpack/core/metrics/ip_metric.hpp
@@ -46,7 +46,7 @@ class IPMetric
    * @return Distance between the two points in kernel space.
    */
   template<typename VecTypeA, typename VecTypeB>
-  double Evaluate(const VecTypeA& a, const VecTypeB& b);
+  typename VecTypeA::elem_type Evaluate(const VecTypeA& a, const VecTypeB& b);
 
   //! Get the kernel.
   const KernelType& Kernel() const { return *kernel; }
diff --git a/src/mlpack/core/metrics/ip_metric_impl.hpp b/src/mlpack/core/metrics/ip_metric_impl.hpp
index 4297c94..0d9cc1c 100644
--- a/src/mlpack/core/metrics/ip_metric_impl.hpp
+++ b/src/mlpack/core/metrics/ip_metric_impl.hpp
@@ -44,8 +44,9 @@ IPMetric<KernelType>::~IPMetric()
 
 template<typename KernelType>
 template<typename Vec1Type, typename Vec2Type>
-inline double IPMetric<KernelType>::Evaluate(const Vec1Type& a,
-                                             const Vec2Type& b)
+inline typename Vec1Type::elem_type IPMetric<KernelType>::Evaluate(
+    const Vec1Type& a,
+    const Vec2Type& b)
 {
   // This is the metric induced by the kernel function.
   // Maybe we can do better by caching some of this?
@@ -71,8 +72,9 @@ void IPMetric<KernelType>::Serialize(Archive& ar,
 // the Euclidean distance.
 template<>
 template<typename Vec1Type, typename Vec2Type>
-inline double IPMetric<kernel::LinearKernel>::Evaluate(const Vec1Type& a,
-                                                       const Vec2Type& b)
+inline typename Vec1Type::elem_type IPMetric<kernel::LinearKernel>::Evaluate(
+    const Vec1Type& a,
+    const Vec2Type& b)
 {
   return metric::LMetric<2, true>::Evaluate(a, b);
 }
diff --git a/src/mlpack/core/metrics/lmetric.hpp b/src/mlpack/core/metrics/lmetric.hpp
index 5d599ab..240ae2a 100644
--- a/src/mlpack/core/metrics/lmetric.hpp
+++ b/src/mlpack/core/metrics/lmetric.hpp
@@ -75,7 +75,8 @@ class LMetric
    * @return Distance between vectors a and b.
    */
   template<typename VecTypeA, typename VecTypeB>
-  static double Evaluate(const VecTypeA& a, const VecTypeB& b);
+  static typename VecTypeA::elem_type Evaluate(const VecTypeA& a,
+                                               const VecTypeB& b);
 
   //! Serialize the metric (nothing to do).
   template<typename Archive>
diff --git a/src/mlpack/core/metrics/lmetric_impl.hpp b/src/mlpack/core/metrics/lmetric_impl.hpp
index c87b7e7..5e1c886 100644
--- a/src/mlpack/core/metrics/lmetric_impl.hpp
+++ b/src/mlpack/core/metrics/lmetric_impl.hpp
@@ -16,74 +16,89 @@ namespace metric {
 // Unspecialized implementation.  This should almost never be used...
 template<int Power, bool TakeRoot>
 template<typename VecTypeA, typename VecTypeB>
-double LMetric<Power, TakeRoot>::Evaluate(const VecTypeA& a,
-                                          const VecTypeB& b)
+typename VecTypeA::elem_type LMetric<Power, TakeRoot>::Evaluate(
+    const VecTypeA& a,
+    const VecTypeB& b)
 {
-  double sum = 0;
+  typename VecTypeA::elem_type sum = 0;
   for (size_t i = 0; i < a.n_elem; i++)
-    sum += pow(fabs(a[i] - b[i]), Power);
+    sum += std::pow(fabs(a[i] - b[i]), Power);
 
   if (!TakeRoot) // The compiler should optimize this correctly at compile-time.
     return sum;
 
-  return pow(sum, (1.0 / Power));
+  return std::pow(sum, (1.0 / Power));
 }
 
 // L1-metric specializations; the root doesn't matter.
 template<>
 template<typename VecTypeA, typename VecTypeB>
-double LMetric<1, true>::Evaluate(const VecTypeA& a, const VecTypeB& b)
+typename VecTypeA::elem_type LMetric<1, true>::Evaluate(
+    const VecTypeA& a,
+    const VecTypeB& b)
 {
-  return accu(abs(a - b));
+  return arma::accu(abs(a - b));
 }
 
 template<>
 template<typename VecTypeA, typename VecTypeB>
-double LMetric<1, false>::Evaluate(const VecTypeA& a, const VecTypeB& b)
+typename VecTypeA::elem_type LMetric<1, false>::Evaluate(
+    const VecTypeA& a,
+    const VecTypeB& b)
 {
-  return accu(abs(a - b));
+  return arma::accu(abs(a - b));
 }
 
 // L2-metric specializations.
 template<>
 template<typename VecTypeA, typename VecTypeB>
-double LMetric<2, true>::Evaluate(const VecTypeA& a, const VecTypeB& b)
+typename VecTypeA::elem_type LMetric<2, true>::Evaluate(
+    const VecTypeA& a,
+    const VecTypeB& b)
 {
-  return sqrt(accu(square(a - b)));
+  return sqrt(arma::accu(square(a - b)));
 }
 
 template<>
 template<typename VecTypeA, typename VecTypeB>
-double LMetric<2, false>::Evaluate(const VecTypeA& a, const VecTypeB& b)
+typename VecTypeA::elem_type LMetric<2, false>::Evaluate(
+    const VecTypeA& a,
+    const VecTypeB& b)
 {
-  return accu(square(a - b));
+  return accu(arma::square(a - b));
 }
 
 // L3-metric specialization (not very likely to be used, but just in case).
 template<>
 template<typename VecTypeA, typename VecTypeB>
-double LMetric<3, true>::Evaluate(const VecTypeA& a, const VecTypeB& b)
+typename VecTypeA::elem_type LMetric<3, true>::Evaluate(
+    const VecTypeA& a,
+    const VecTypeB& b)
 {
-  double sum = 0;
+  typename VecTypeA::elem_type sum = 0;
   for (size_t i = 0; i < a.n_elem; i++)
-    sum += pow(fabs(a[i] - b[i]), 3.0);
+    sum += std::pow(fabs(a[i] - b[i]), 3.0);
 
-  return pow(accu(pow(abs(a - b), 3.0)), 1.0 / 3.0);
+  return std::pow(arma::accu(arma::pow(arma::abs(a - b), 3.0)), 1.0 / 3.0);
 }
 
 template<>
 template<typename VecTypeA, typename VecTypeB>
-double LMetric<3, false>::Evaluate(const VecTypeA& a, const VecTypeB& b)
+typename VecTypeA::elem_type LMetric<3, false>::Evaluate(
+    const VecTypeA& a,
+    const VecTypeB& b)
 {
-  return accu(pow(abs(a - b), 3.0));
+  return arma::accu(arma::pow(arma::abs(a - b), 3.0));
 }
 
 // L-infinity (Chebyshev distance) specialization
 template<>
 template<typename VecTypeA, typename VecTypeB>
-double LMetric<INT_MAX, false>::Evaluate(const VecTypeA& a, const VecTypeB& b)
+typename VecTypeA::elem_type LMetric<INT_MAX, false>::Evaluate(
+    const VecTypeA& a,
+    const VecTypeB& b)
 {
-  return arma::as_scalar(max(abs(a - b)));
+  return arma::as_scalar(arma::max(arma::abs(a - b)));
 }
 
 } // namespace metric




More information about the mlpack-git mailing list