[mlpack-svn] r12946 - mlpack/trunk/src/mlpack/core/kernels

fastlab-svn at coffeetalk-1.cc.gatech.edu fastlab-svn at coffeetalk-1.cc.gatech.edu
Tue Jun 5 14:53:37 EDT 2012


Author: rcurtin
Date: 2012-06-05 14:53:36 -0400 (Tue, 05 Jun 2012)
New Revision: 12946

Added:
   mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel.cpp
   mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp
Modified:
   mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel.hpp
Log:
Refactor and clean epanechnikov kernel.


Added: mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel.cpp
===================================================================
--- mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel.cpp	                        (rev 0)
+++ mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel.cpp	2012-06-05 18:53:36 UTC (rev 12946)
@@ -0,0 +1,34 @@
+/**
+ * @file epanechnikov_kernel.hpp
+ * @author Neil Slagle
+ *
+ * This is an example kernel.  If you are making your own kernel, follow the
+ * outline specified in this file.
+ */
+#include "epanechnikov_kernel.hpp"
+
+#include <boost/math/special_functions/gamma.hpp>
+
+using namespace mlpack;
+using namespace mlpack::kernel;
+
+/**
+ * Compute the normalizer of this Epanechnikov kernel for the given dimension.
+ *
+ * @param dimension Dimension to calculate the normalizer for.
+ */
+double EpanechnikovKernel::Normalizer(const size_t dimension)
+{
+  return 2.0 * pow(bandwidth, (double) dimension) *
+      std::pow(M_PI, dimension / 2.0) /
+      (boost::math::tgamma(dimension / 2.0 + 1.0) * (dimension + 2.0));
+}
+
+/**
+ * Evaluate the kernel not for two points but for a numerical value.
+ */
+double EpanechnikovKernel::Evaluate(const double t)
+{
+  double evaluatee = 1.0 - t * t * inverseBandwidthSquared;
+  return (evaluatee > 0.0) ? evaluatee : 0.0;
+}

Modified: mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel.hpp	2012-06-05 09:01:08 UTC (rev 12945)
+++ mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel.hpp	2012-06-05 18:53:36 UTC (rev 12946)
@@ -5,97 +5,80 @@
  * This is an example kernel.  If you are making your own kernel, follow the
  * outline specified in this file.
  */
-#ifndef __MLPACK_CORE_KERNELS_EPANECHNIKOV_KERNEL_H
-#define __MLPACK_CORE_KERNELS_EPANECHNIKOV_KERNEL_H
+#ifndef __MLPACK_CORE_KERNELS_EPANECHNIKOV_KERNEL_HPP
+#define __MLPACK_CORE_KERNELS_EPANECHNIKOV_KERNEL_HPP
 
-#include <boost/math/special_functions/gamma.hpp>
-
 #include <mlpack/core.hpp>
-#include <mlpack/core/metrics/lmetric.hpp>
 
 namespace mlpack {
 namespace kernel {
 
+/**
+ * The Epanechnikov kernel, defined as
+ *
+ * @f[
+ * K(x, y) = \max \{0, 1 - || x - y ||^2_2 / b^2 \}
+ * @f]
+ *
+ * where @f$ b @f$ is the bandwidth the of the kernel (defaults to 1.0).
+ */
 class EpanechnikovKernel
 {
  public:
-  EpanechnikovKernel() :
-    bandwidth(1.0),
-    inverseBandwidthSquared(1.0) {}
-  EpanechnikovKernel(double b) :
-    bandwidth(b),
-    inverseBandwidthSquared(1.0/(b*b)) {}
+  /**
+   * Instantiate the Epanechnikov kernel with the given bandwidth (default 1.0).
+   *
+   * @param bandwidth Bandwidth of the kernel.
+   */
+  EpanechnikovKernel(const double bandwidth = 1.0) :
+      bandwidth(bandwidth),
+      inverseBandwidthSquared(1.0 / (bandwidth * bandwidth))
+  {  }
 
-  template<typename VecType>
-  double Evaluate(const VecType& a, const VecType& b)
-  {
-    double evaluatee =
-      1.0 - metric::SquaredEuclideanDistance::Evaluate(a, b) * inverseBandwidthSquared;
-    return (evaluatee > 0.0) ? evaluatee : 0.0;
-  }
   /**
-   * Obtains the convolution integral [integral K(||x-a||)K(||b-x||)dx]
-   * for the two vectors.  In this case, because
-   * our simple example kernel has no internal parameters, we can declare the
-   * function static.  For a more complex example which cannot be declared
-   * static, see the GaussianKernel, which stores an internal parameter.
+   * Evaluate the Epanechnikov kernel on the given two inputs.
    *
+   * @param a One input vector.
+   * @param b The other input vector.
+   */
+  template<typename Vec1Type, typename Vec2Type>
+  double Evaluate(const Vec1Type& a, const Vec2Type& b);
+
+  /**
+   * Obtains the convolution integral [integral of K(||x-a||) K(||b-x||) dx]
+   * for the two vectors.
+   *
    * @tparam VecType Type of vector (arma::vec, arma::spvec should be expected).
    * @param a First vector.
    * @param b Second vector.
    * @return the convolution integral value.
    */
   template<typename VecType>
-  double ConvolutionIntegral(const VecType& a, const VecType& b)
-  {
-    double distance = sqrt(metric::SquaredEuclideanDistance::Evaluate(a, b));
-    if (distance >= 2.0 * bandwidth)
-    {
-      return 0.0;
-    }
-    double volumeSquared = pow(Normalizer(a.n_rows), 2.0);
+  double ConvolutionIntegral(const VecType& a, const VecType& b);
 
-    switch(a.n_rows)
-    {
-      case 1:
-        return 1.0 / volumeSquared *
-          (16.0/15.0*bandwidth-4.0*distance*distance /
-          (3.0*bandwidth)+2.0*distance*distance*distance/
-          (3.0*bandwidth*bandwidth) -
-          pow(distance,5.0)/(30.0*pow(bandwidth,4.0)));
-        break;
-      case 2:
-        return 1.0 / volumeSquared *
-          ((2.0/3.0*bandwidth*bandwidth-distance*distance)*
-          asin(sqrt(1.0-pow(distance/(2.0*bandwidth),2.0))) +
-          sqrt(4.0*bandwidth*bandwidth-distance*distance)*
-          (distance/6.0+2.0/9.0*distance*pow(distance/bandwidth,2.0)-
-          distance/72.0*pow(distance/bandwidth,4.0)));
-        break;
-      default:
-        Log::Fatal << "Epanechnikov doesn't support your dimension (yet).";
-        return -1.0;
-        break;
-    }
-  }
+  /**
+   * Compute the normalizer of this Epanechnikov kernel for the given dimension.
+   *
+   * @param dimension Dimension to calculate the normalizer for.
+   */
+  double Normalizer(const size_t dimension);
 
-  double Normalizer(size_t dimension)
-  {
-    return 2.0 * pow(bandwidth, (double) dimension) *
-        pow(M_PI, dimension / 2.0) /
-        (boost::math::tgamma(dimension / 2.0 + 1.0) * (dimension + 2.0));
-  }
-  double Evaluate(double t)
-  {
-    double evaluatee = 1.0 - t * t * inverseBandwidthSquared;
-    return (evaluatee > 0.0) ? evaluatee : 0.0;
-  }
+  /**
+   * Evaluate the kernel not for two points but for a numerical value.
+   */
+  double Evaluate(const double t);
+
  private:
+  //! Bandwidth of the kernel.
   double bandwidth;
+  //! Cached value of the inverse bandwidth squared (to speed up computation).
   double inverseBandwidthSquared;
 };
 
 }; // namespace kernel
 }; // namespace mlpack
 
+// Include implementation.
+#include "epanechnikov_kernel_impl.hpp"
+
 #endif

Added: mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp	                        (rev 0)
+++ mlpack/trunk/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp	2012-06-05 18:53:36 UTC (rev 12946)
@@ -0,0 +1,74 @@
+/**
+ * @file epanechnikov_kernel.hpp
+ * @author Neil Slagle
+ *
+ * This is an example kernel.  If you are making your own kernel, follow the
+ * outline specified in this file.
+ */
+#ifndef __MLPACK_CORE_KERNELS_EPANECHNIKOV_KERNEL_IMPL_HPP
+#define __MLPACK_CORE_KERNELS_EPANECHNIKOV_KERNEL_IMPL_HPP
+
+// In case it hasn't already been included.
+#include "epanechnikov_kernel.hpp"
+
+#include <mlpack/core/metrics/lmetric.hpp>
+
+namespace mlpack {
+namespace kernel {
+
+template<typename Vec1Type, typename Vec2Type>
+inline double EpanechnikovKernel::Evaluate(const Vec1Type& a, const Vec2Type& b)
+{
+  return std::max(0.0, 1.0 - metric::SquaredEuclideanDistance::Evaluate(a, b)
+      * inverseBandwidthSquared);
+}
+
+/**
+ * Obtains the convolution integral [integral of K(||x-a||) K(||b-x||) dx]
+ * for the two vectors.
+ *
+ * @tparam VecType Type of vector (arma::vec, arma::spvec should be expected).
+ * @param a First vector.
+ * @param b Second vector.
+ * @return the convolution integral value.
+ */
+template<typename VecType>
+double EpanechnikovKernel::ConvolutionIntegral(const VecType& a,
+                                               const VecType& b)
+{
+  double distance = sqrt(metric::SquaredEuclideanDistance::Evaluate(a, b));
+  if (distance >= 2.0 * bandwidth)
+    return 0.0;
+
+  double volumeSquared = std::pow(Normalizer(a.n_rows), 2.0);
+
+  switch (a.n_rows)
+  {
+    case 1:
+      return 1.0 / volumeSquared *
+          (16.0 / 15.0 * bandwidth - 4.0 * distance * distance /
+          (3.0 * bandwidth) + 2.0 * distance * distance * distance /
+          (3.0 * bandwidth * bandwidth) -
+          std::pow(distance, 5.0) / (30.0 * std::pow(bandwidth, 4.0)));
+      break;
+    case 2:
+      return 1.0 / volumeSquared *
+          ((2.0 / 3.0 * bandwidth * bandwidth - distance * distance) *
+          asin(sqrt(1.0 - std::pow(distance / (2.0 * bandwidth), 2.0))) +
+          sqrt(4.0 * bandwidth * bandwidth - distance * distance) *
+          (distance / 6.0 + 2.0 / 9.0 * distance *
+          std::pow(distance / bandwidth, 2.0) - distance / 72.0 *
+          std::pow(distance / bandwidth, 4.0)));
+      break;
+    default:
+      Log::Fatal << "EpanechnikovKernel::ConvolutionIntegral(): dimension "
+          << a.n_rows << " not supported.";
+      return -1.0; // This line will not execute.
+      break;
+  }
+}
+
+}; // namespace kernel
+}; // namespace mlpack
+
+#endif




More information about the mlpack-svn mailing list