[mlpack-git] master: Add a model for FastMKS, to be used by the command-line program for serialization. (48b4706)

gitdub at big.cc.gt.atl.ga.us gitdub at big.cc.gt.atl.ga.us
Tue Dec 22 18:34:45 EST 2015


Repository : https://github.com/mlpack/mlpack

On branch  : master
Link       : https://github.com/mlpack/mlpack/compare/eb41f4bc27b484c347acc006255104e2f8cc4eef...977afbec0648056124dcb206e0bf972a161d9b51

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

commit 48b470615a8f4106839c5449fbf89294ee529861
Author: ryan <ryan at ratml.org>
Date:   Tue Dec 22 18:23:26 2015 -0500

    Add a model for FastMKS, to be used by the command-line program for serialization.


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

48b470615a8f4106839c5449fbf89294ee529861
 src/mlpack/methods/fastmks/CMakeLists.txt         |   3 +
 src/mlpack/methods/fastmks/fastmks_model.cpp      | 203 ++++++++++++++++++++
 src/mlpack/methods/fastmks/fastmks_model.hpp      | 135 ++++++++++++++
 src/mlpack/methods/fastmks/fastmks_model_impl.hpp | 215 ++++++++++++++++++++++
 4 files changed, 556 insertions(+)

diff --git a/src/mlpack/methods/fastmks/CMakeLists.txt b/src/mlpack/methods/fastmks/CMakeLists.txt
index fac46b6..2472e9b 100644
--- a/src/mlpack/methods/fastmks/CMakeLists.txt
+++ b/src/mlpack/methods/fastmks/CMakeLists.txt
@@ -3,6 +3,9 @@
 set(SOURCES
   fastmks.hpp
   fastmks_impl.hpp
+  fastmks_model.hpp
+  fastmks_model_impl.hpp
+  fastmks_model.cpp
   fastmks_rules.hpp
   fastmks_rules_impl.hpp
 )
diff --git a/src/mlpack/methods/fastmks/fastmks_model.cpp b/src/mlpack/methods/fastmks/fastmks_model.cpp
new file mode 100644
index 0000000..d4c85c2
--- /dev/null
+++ b/src/mlpack/methods/fastmks/fastmks_model.cpp
@@ -0,0 +1,203 @@
+/**
+ * @file fastmks_model.cpp
+ * @author Ryan Curtin
+ *
+ * Implementation of non-templatized functions of FastMKSModel.
+ */
+#include "fastmks_model.hpp"
+
+namespace mlpack {
+namespace fastmks {
+
+FastMKSModel::FastMKSModel(const int kernelType) :
+    kernelType(kernelType),
+    linear(NULL),
+    polynomial(NULL),
+    cosine(NULL),
+    gaussian(NULL),
+    epan(NULL),
+    triangular(NULL),
+    hyptan(NULL)
+{
+  // Nothing to do.
+}
+
+FastMKSModel::~FastMKSModel()
+{
+  // Clean memory.
+  if (linear)
+    delete linear;
+  if (polynomial)
+    delete polynomial;
+  if (cosine)
+    delete cosine;
+  if (gaussian)
+    delete gaussian;
+  if (epan)
+    delete epan;
+  if (triangular)
+    delete triangular;
+  if (hyptan)
+    delete hyptan;
+}
+
+bool FastMKSModel::Naive() const
+{
+  switch (kernelType)
+  {
+    case LINEAR_KERNEL:
+      return linear->Naive();
+    case POLYNOMIAL_KERNEL:
+      return polynomial->Naive();
+    case COSINE_DISTANCE:
+      return cosine->Naive();
+    case GAUSSIAN_KERNEL:
+      return gaussian->Naive();
+    case EPANECHNIKOV_KERNEL:
+      return epan->Naive();
+    case TRIANGULAR_KERNEL:
+      return triangular->Naive();
+    case HYPTAN_KERNEL:
+      return hyptan->Naive();
+  }
+
+  throw std::runtime_error("invalid model type");
+}
+
+bool& FastMKSModel::Naive()
+{
+  switch (kernelType)
+  {
+    case LINEAR_KERNEL:
+      return linear->Naive();
+    case POLYNOMIAL_KERNEL:
+      return polynomial->Naive();
+    case COSINE_DISTANCE:
+      return cosine->Naive();
+    case GAUSSIAN_KERNEL:
+      return gaussian->Naive();
+    case EPANECHNIKOV_KERNEL:
+      return epan->Naive();
+    case TRIANGULAR_KERNEL:
+      return triangular->Naive();
+    case HYPTAN_KERNEL:
+      return hyptan->Naive();
+  }
+
+  throw std::runtime_error("invalid model type");
+}
+
+bool FastMKSModel::SingleMode() const
+{
+  switch (kernelType)
+  {
+    case LINEAR_KERNEL:
+      return linear->SingleMode();
+    case POLYNOMIAL_KERNEL:
+      return polynomial->SingleMode();
+    case COSINE_DISTANCE:
+      return cosine->SingleMode();
+    case GAUSSIAN_KERNEL:
+      return gaussian->SingleMode();
+    case EPANECHNIKOV_KERNEL:
+      return epan->SingleMode();
+    case TRIANGULAR_KERNEL:
+      return triangular->SingleMode();
+    case HYPTAN_KERNEL:
+      return hyptan->SingleMode();
+  }
+
+  throw std::runtime_error("invalid model type");
+}
+
+bool& FastMKSModel::SingleMode()
+{
+  switch (kernelType)
+  {
+    case LINEAR_KERNEL:
+      return linear->SingleMode();
+    case POLYNOMIAL_KERNEL:
+      return polynomial->SingleMode();
+    case COSINE_DISTANCE:
+      return cosine->SingleMode();
+    case GAUSSIAN_KERNEL:
+      return gaussian->SingleMode();
+    case EPANECHNIKOV_KERNEL:
+      return epan->SingleMode();
+    case TRIANGULAR_KERNEL:
+      return triangular->SingleMode();
+    case HYPTAN_KERNEL:
+      return hyptan->SingleMode();
+  }
+
+  throw std::runtime_error("invalid model type");
+}
+
+void FastMKSModel::Search(const arma::mat& querySet,
+                          const size_t k,
+                          arma::Mat<size_t>& indices,
+                          arma::mat& kernels,
+                          const double base)
+{
+  switch (kernelType)
+  {
+    case LINEAR_KERNEL:
+      Search(*linear, querySet, k, indices, kernels, base);
+      break;
+    case POLYNOMIAL_KERNEL:
+      Search(*polynomial, querySet, k, indices, kernels, base);
+      break;
+    case COSINE_DISTANCE:
+      Search(*cosine, querySet, k, indices, kernels, base);
+      break;
+    case GAUSSIAN_KERNEL:
+      Search(*gaussian, querySet, k, indices, kernels, base);
+      break;
+    case EPANECHNIKOV_KERNEL:
+      Search(*epan, querySet, k, indices, kernels, base);
+      break;
+    case TRIANGULAR_KERNEL:
+      Search(*triangular, querySet, k, indices, kernels, base);
+      break;
+    case HYPTAN_KERNEL:
+      Search(*hyptan, querySet, k, indices, kernels, base);
+      break;
+    default:
+      throw std::runtime_error("invalid model type");
+  }
+}
+
+void FastMKSModel::Search(const size_t k,
+                          arma::Mat<size_t>& indices,
+                          arma::mat& kernels)
+{
+  switch (kernelType)
+  {
+    case LINEAR_KERNEL:
+      linear->Search(k, indices, kernels);
+      break;
+    case POLYNOMIAL_KERNEL:
+      polynomial->Search(k, indices, kernels);
+      break;
+    case COSINE_DISTANCE:
+      cosine->Search(k, indices, kernels);
+      break;
+    case GAUSSIAN_KERNEL:
+      gaussian->Search(k, indices, kernels);
+      break;
+    case EPANECHNIKOV_KERNEL:
+      epan->Search(k, indices, kernels);
+      break;
+    case TRIANGULAR_KERNEL:
+      triangular->Search(k, indices, kernels);
+      break;
+    case HYPTAN_KERNEL:
+      hyptan->Search(k, indices, kernels);
+      break;
+    default:
+      throw std::invalid_argument("invalid model type");
+  }
+}
+
+} // namespace fastmks
+} // namespace mlpack
diff --git a/src/mlpack/methods/fastmks/fastmks_model.hpp b/src/mlpack/methods/fastmks/fastmks_model.hpp
new file mode 100644
index 0000000..4289d4b
--- /dev/null
+++ b/src/mlpack/methods/fastmks/fastmks_model.hpp
@@ -0,0 +1,135 @@
+/**
+ * @file fastmks_model.hpp
+ * @author Ryan Curtin
+ *
+ * A utility struct to contain all the possible FastMKS models.
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_FASTMKS_MODEL_HPP
+#define __MLPACK_METHODS_FASTMKS_FASTMKS_MODEL_HPP
+
+#include <mlpack/core.hpp>
+#include "fastmks.hpp"
+
+namespace mlpack {
+namespace fastmks {
+
+//! A utility struct to contain all the possible FastMKS models, for use by the
+//! mlpack_fastmks program.
+class FastMKSModel
+{
+ public:
+  //! A list of all the kernels we support.
+  enum KernelTypes
+  {
+    LINEAR_KERNEL,
+    POLYNOMIAL_KERNEL,
+    COSINE_DISTANCE,
+    GAUSSIAN_KERNEL,
+    EPANECHNIKOV_KERNEL,
+    TRIANGULAR_KERNEL,
+    HYPTAN_KERNEL
+  };
+
+  /**
+   * Create the FastMKSModel with the given kernel type.
+   */
+  FastMKSModel(const int kernelType = LINEAR_KERNEL);
+
+  /**
+   * Clean memory.
+   */
+  ~FastMKSModel();
+
+  /**
+   * Build the model on the given reference set.  Make sure kernelType is equal
+   * to the correct entry in KernelTypes for the given KernelType class!
+   */
+  template<typename KernelType>
+  void BuildModel(const arma::mat& referenceData,
+                  KernelType& kernel,
+                  const bool singleMode,
+                  const bool naive,
+                  const double base);
+
+  //! Get whether or not naive search is used.
+  bool Naive() const;
+  //! Set whether or not naive search is used.
+  bool& Naive();
+
+  //! Get whether or not single-tree search is used.
+  bool SingleMode() const;
+  //! Set whether or not single-tree search is used.
+  bool& SingleMode();
+
+  /**
+   * Search with a different query set.
+   *
+   * @param querySet Set to search with.
+   * @param k Number of max-kernel candidates to search for.
+   * @param indices A matrix in which to store the indices of max-kernel
+   *      candidates.
+   * @param kernels A matrix in which to store the max-kernel candidate kernel
+   *      values.
+   * @param base Base to use for cover tree building (if in dual-tree search
+   *      mode).
+   */
+  void Search(const arma::mat& querySet,
+              const size_t k,
+              arma::Mat<size_t>& indices,
+              arma::mat& kernels,
+              const double base);
+
+  /**
+   * Search with the reference set as the query set.
+   *
+   * @param k Number of max-kernel candidates to search for.
+   * @param indices A matrix in which to store the indices of max-kernel
+   *      candidates.
+   * @param kernels A matrix in which to store the max-kernel candidate kernel
+   *      values.
+   */
+  void Search(const size_t k,
+              arma::Mat<size_t>& indices,
+              arma::mat& kernels);
+
+  /**
+   * Serialize the model.
+   */
+  template<typename Archive>
+  void Serialize(Archive& ar, const unsigned int /* version */);
+
+ private:
+  //! The type of kernel we are using.
+  int kernelType;
+
+  //! This will only be non-NULL if this is the type of kernel we are using.
+  FastMKS<kernel::LinearKernel>* linear;
+  //! This will only be non-NULL if this is the type of kernel we are using.
+  FastMKS<kernel::PolynomialKernel>* polynomial;
+  //! This will only be non-NULL if this is the type of kernel we are using.
+  FastMKS<kernel::CosineDistance>* cosine;
+  //! This will only be non-NULL if this is the type of kernel we are using.
+  FastMKS<kernel::GaussianKernel>* gaussian;
+  //! This will only be non-NULL if this is the type of kernel we are using.
+  FastMKS<kernel::EpanechnikovKernel>* epan;
+  //! This will only be non-NULL if this is the type of kernel we are using.
+  FastMKS<kernel::TriangularKernel>* triangular;
+  //! This will only be non-NULL if this is the type of kernel we are using.
+  FastMKS<kernel::HyperbolicTangentKernel>* hyptan;
+
+  //! Build a query tree and execute the search.
+  template<typename FastMKSType>
+  void Search(FastMKSType& f,
+              const arma::mat& querySet,
+              const size_t k,
+              arma::Mat<size_t>& indices,
+              arma::mat& kernels,
+              const double base);
+};
+
+} // namespace fastmks
+} // namespace mlpack
+
+#include "fastmks_model_impl.hpp"
+
+#endif
diff --git a/src/mlpack/methods/fastmks/fastmks_model_impl.hpp b/src/mlpack/methods/fastmks/fastmks_model_impl.hpp
new file mode 100644
index 0000000..b9c02e5
--- /dev/null
+++ b/src/mlpack/methods/fastmks/fastmks_model_impl.hpp
@@ -0,0 +1,215 @@
+/**
+ * @file fastmks_model_impl.hpp
+ * @author Ryan Curtin
+ *
+ * Implementation of templated functions of FastMKSModel.
+ */
+#ifndef __MLPACK_METHODS_FASTMKS_FASTMKS_MODEL_IMPL_HPP
+#define __MLPACK_METHODS_FASTMKS_FASTMKS_MODEL_IMPL_HPP
+
+#include "fastmks_model.hpp"
+
+namespace mlpack {
+namespace fastmks {
+
+//! This is called when the KernelType is the same as the model.
+template<typename KernelType>
+void BuildFastMKSModel(FastMKS<KernelType>& f,
+                       KernelType& k,
+                       const arma::mat& referenceData,
+                       const double base)
+{
+  // Do we need to build the tree?
+  if (f.Naive())
+  {
+    f.Train(referenceData, k);
+  }
+  else
+  {
+    // Create the tree with the specified base.
+    Timer::Start("tree_building");
+    metric::IPMetric<KernelType> metric(k);
+    typename FastMKS<KernelType>::Tree* tree =
+        new typename FastMKS<KernelType>::Tree(referenceData, metric, base);
+    Timer::Stop("tree_building");
+
+    f.Train(tree);
+  }
+}
+
+//! This is only called when something goes wrong.
+template<typename KernelType,
+         typename FastMKSType>
+void BuildFastMKSModel(FastMKSType& f,
+                       KernelType& k,
+                       const arma::mat& referenceData,
+                       const double base)
+{
+  throw std::invalid_argument("FastMKSModel::BuildModel(): given kernel type is"
+      " not equal to kernel type of the model!");
+}
+
+template<typename KernelType>
+void FastMKSModel::BuildModel(const arma::mat& referenceData,
+                              KernelType& kernel,
+                              const bool singleMode,
+                              const bool naive,
+                              const double base)
+{
+  // Clean memory if necessary.
+  if (linear)
+    delete linear;
+  if (polynomial)
+    delete polynomial;
+  if (cosine)
+    delete cosine;
+  if (gaussian)
+    delete gaussian;
+  if (epan)
+    delete epan;
+  if (triangular)
+    delete triangular;
+  if (hyptan)
+    delete hyptan;
+
+  linear = NULL;
+  polynomial = NULL;
+  cosine = NULL;
+  gaussian = NULL;
+  epan = NULL;
+  triangular = NULL;
+  hyptan = NULL;
+
+  // Instantiate the right model.
+  switch (kernelType)
+  {
+    case LINEAR_KERNEL:
+      linear = new FastMKS<kernel::LinearKernel>(singleMode, naive);
+      BuildFastMKSModel(*linear, kernel, referenceData, base);
+      break;
+
+    case POLYNOMIAL_KERNEL:
+      polynomial = new FastMKS<kernel::PolynomialKernel>(singleMode, naive);
+      BuildFastMKSModel(*polynomial, kernel, referenceData, base);
+      break;
+
+    case COSINE_DISTANCE:
+      cosine = new FastMKS<kernel::CosineDistance>(singleMode, naive);
+      BuildFastMKSModel(*cosine, kernel, referenceData, base);
+      break;
+
+    case GAUSSIAN_KERNEL:
+      gaussian = new FastMKS<kernel::GaussianKernel>(singleMode, naive);
+      BuildFastMKSModel(*gaussian, kernel, referenceData, base);
+      break;
+
+    case EPANECHNIKOV_KERNEL:
+      epan = new FastMKS<kernel::EpanechnikovKernel>(singleMode, naive);
+      BuildFastMKSModel(*epan, kernel, referenceData, base);
+      break;
+
+    case TRIANGULAR_KERNEL:
+      triangular = new FastMKS<kernel::TriangularKernel>(singleMode, naive);
+      BuildFastMKSModel(*triangular, kernel, referenceData, base);
+      break;
+
+    case HYPTAN_KERNEL:
+      hyptan = new FastMKS<kernel::HyperbolicTangentKernel>(singleMode, naive);
+      BuildFastMKSModel(*hyptan, kernel, referenceData, base);
+      break;
+  }
+}
+
+template<typename Archive>
+void FastMKSModel::Serialize(Archive& ar, const unsigned int /* version */)
+{
+  using data::CreateNVP;
+
+  ar & CreateNVP(kernelType, "kernelType");
+
+  if (Archive::is_loading::value)
+  {
+    // Clean memory.
+    if (linear)
+      delete linear;
+    if (polynomial)
+      delete polynomial;
+    if (cosine)
+      delete cosine;
+    if (gaussian)
+      delete gaussian;
+    if (epan)
+      delete epan;
+    if (triangular)
+      delete triangular;
+    if (hyptan)
+      delete hyptan;
+
+    linear = NULL;
+    polynomial = NULL;
+    cosine = NULL;
+    gaussian = NULL;
+    epan = NULL;
+    triangular = NULL;
+    hyptan = NULL;
+  }
+
+  // Serialize the correct model.
+  switch (kernelType)
+  {
+    case LINEAR_KERNEL:
+      ar & CreateNVP(linear, "linear_fastmks");
+      break;
+
+    case POLYNOMIAL_KERNEL:
+      ar & CreateNVP(polynomial, "polynomial_fastmks");
+      break;
+
+    case COSINE_DISTANCE:
+      ar & CreateNVP(cosine, "cosine_fastmks");
+      break;
+
+    case GAUSSIAN_KERNEL:
+      ar & CreateNVP(gaussian, "gaussian_fastmks");
+      break;
+
+    case EPANECHNIKOV_KERNEL:
+      ar & CreateNVP(epan, "epan_fastmks");
+      break;
+
+    case TRIANGULAR_KERNEL:
+      ar & CreateNVP(triangular, "triangular_fastmks");
+      break;
+
+    case HYPTAN_KERNEL:
+      ar & CreateNVP(hyptan, "hyptan_fastmks");
+      break;
+  }
+}
+
+template<typename FastMKSType>
+void FastMKSModel::Search(FastMKSType& f,
+                          const arma::mat& querySet,
+                          const size_t k,
+                          arma::Mat<size_t>& indices,
+                          arma::mat& kernels,
+                          const double base)
+{
+  if (f.Naive() || f.SingleMode())
+  {
+    f.Search(querySet, k, indices, kernels);
+  }
+  else
+  {
+    Timer::Start("tree_building");
+    typename FastMKSType::Tree queryTree(querySet, base);
+    Timer::Stop("tree_building");
+
+    f.Search(&queryTree, k, indices, kernels);
+  }
+}
+
+} // namespace fastmks
+} // namespace mlpack
+
+#endif



More information about the mlpack-git mailing list