Skip to content

Commit

Permalink
added multi kernel permutation test cross validation
Browse files Browse the repository at this point in the history
  • Loading branch information
lambday authored and karlnapf committed Jul 3, 2016
1 parent aaf6d6f commit 37f34f6
Show file tree
Hide file tree
Showing 8 changed files with 466 additions and 61 deletions.
7 changes: 2 additions & 5 deletions src/shogun/kernel/ShiftInvariantKernel.h
Expand Up @@ -41,10 +41,7 @@ namespace shogun

namespace internal
{
namespace mmd
{
class MultiKernelMMD;
}
class KernelManager;
}

/** @brief Base class for the family of kernel functions that only depend on
Expand All @@ -58,7 +55,7 @@ namespace internal
class CShiftInvariantKernel: public CKernel
{

friend class internal::mmd::MultiKernelMMD;
friend class internal::KernelManager;

public:
/** Default constructor. */
Expand Down
36 changes: 9 additions & 27 deletions src/shogun/statistical_testing/QuadraticTimeMMD.cpp
Expand Up @@ -35,8 +35,7 @@
#include <shogun/kernel/Kernel.h>
#include <shogun/kernel/CustomKernel.h>
#include <shogun/kernel/ShiftInvariantKernel.h>
#include <shogun/distance/EuclideanDistance.h>
#include <shogun/distance/ManhattanMetric.h>
#include <shogun/distance/Distance.h>
#include <shogun/mathematics/eigen3.h>
#include <shogun/mathematics/Statistics.h>
#include <shogun/statistical_testing/QuadraticTimeMMD.h>
Expand Down Expand Up @@ -550,39 +549,22 @@ void CQuadraticTimeMMD::precompute_kernel_matrix(bool precompute)
SGVector<float64_t> CQuadraticTimeMMD::compute_statistic(const internal::KernelManager& kernel_mgr)
{
SG_DEBUG("Entering");
REQUIRE(kernel_mgr.same_distance_type(), "The kernels have to have same distance type!\n");
REQUIRE(kernel_mgr.num_kernels()>0, "Number of kernels (%d) have to be greater than 0!\n", kernel_mgr.num_kernels());
const auto& data_mgr=get_data_mgr();
const index_t nx=data_mgr.num_samples_at(0);
const index_t ny=data_mgr.num_samples_at(1);
MultiKernelMMD compute(nx, ny, get_statistic_type());

CDistance* distance=nullptr;
CShiftInvariantKernel* kernel_0=dynamic_cast<CShiftInvariantKernel*>(kernel_mgr.kernel_at(0));
REQUIRE(kernel_0, "Kernel (%s) must be of CShiftInvariantKernel type!\n", kernel_mgr.kernel_at(0)->get_name());
if (kernel_0->get_distance_type()==D_EUCLIDEAN)
{
auto euclidean_distance=new CEuclideanDistance();
euclidean_distance->set_disable_sqrt(true);
distance=euclidean_distance;
}
else if (kernel_0->get_distance_type()==D_MANHATTAN)
{
auto manhattan_distance=new CManhattanMetric();
distance=manhattan_distance;
}
else
{
SG_ERROR("Unsupported distance type!\n");
}

CDistance* distance=kernel_mgr.get_distance_instance();
SG_REF(distance);

const index_t nx=get_num_samples_p();
const index_t ny=get_num_samples_q();

MultiKernelMMD compute(nx, ny, get_statistic_type());
compute.set_distance(compute_joint_distance(distance));
SGVector<float64_t> result=compute(kernel_mgr);
SG_UNREF(distance);

for (auto i=0; i<result.vlen; ++i)
result[i]=normalize_statistic(result[i]);

SG_UNREF(distance);
SG_DEBUG("Leaving");
return result;
}
Expand Down
53 changes: 53 additions & 0 deletions src/shogun/statistical_testing/internals/KernelManager.cpp
Expand Up @@ -34,6 +34,8 @@
#include <shogun/distance/Distance.h>
#include <shogun/kernel/Kernel.h>
#include <shogun/kernel/CustomKernel.h>
#include <shogun/distance/EuclideanDistance.h>
#include <shogun/distance/ManhattanMetric.h>
#include <shogun/kernel/ShiftInvariantKernel.h>
#include <shogun/statistical_testing/internals/KernelManager.h>

Expand Down Expand Up @@ -162,3 +164,54 @@ bool KernelManager::same_distance_type() const
}
return same;
}

CDistance* KernelManager::get_distance_instance() const
{
REQUIRE(same_distance_type(), "Distance types for all the kernels are not the same!\n");

CDistance* distance=nullptr;
CShiftInvariantKernel* kernel_0=dynamic_cast<CShiftInvariantKernel*>(kernel_at(0));
REQUIRE(kernel_0, "Kernel (%s) must be of CShiftInvariantKernel type!\n", kernel_at(0)->get_name());
if (kernel_0->get_distance_type()==D_EUCLIDEAN)
{
auto euclidean_distance=new CEuclideanDistance();
euclidean_distance->set_disable_sqrt(true);
distance=euclidean_distance;
}
else if (kernel_0->get_distance_type()==D_MANHATTAN)
{
auto manhattan_distance=new CManhattanMetric();
distance=manhattan_distance;
}
else
{
SG_SERROR("Unsupported distance type!\n");
}
return distance;
}

void KernelManager::set_precomputed_distance(CCustomDistance* distance) const
{
for (size_t i=0; i<num_kernels(); ++i)
{
CKernel* kernel=kernel_at(i);
CShiftInvariantKernel* shift_inv_kernel=dynamic_cast<CShiftInvariantKernel*>(kernel);
REQUIRE(shift_inv_kernel!=nullptr, "Kernel instance (was %s) must be of CShiftInvarintKernel type!\n", kernel->get_name());
shift_inv_kernel->m_precomputed_distance=distance;
shift_inv_kernel->num_lhs=distance->get_num_vec_lhs();
shift_inv_kernel->num_rhs=distance->get_num_vec_rhs();
}
}

void KernelManager::unset_precomputed_distance() const
{
for (size_t i=0; i<num_kernels(); ++i)
{
CKernel* kernel=kernel_at(i);
CShiftInvariantKernel* shift_inv_kernel=dynamic_cast<CShiftInvariantKernel*>(kernel);
REQUIRE(shift_inv_kernel!=nullptr, "Kernel instance (was %s) must be of CShiftInvarintKernel type!\n", kernel->get_name());
shift_inv_kernel->m_precomputed_distance=nullptr;
shift_inv_kernel->num_lhs=0;
shift_inv_kernel->num_rhs=0;
}
}
5 changes: 5 additions & 0 deletions src/shogun/statistical_testing/internals/KernelManager.h
Expand Up @@ -40,6 +40,8 @@ namespace shogun
{

class CKernel;
class CDistance;
class CCustomDistance;
class CCustomKernel;

namespace internal
Expand All @@ -63,6 +65,9 @@ class KernelManager

void clear();
bool same_distance_type() const;
CDistance* get_distance_instance() const;
void set_precomputed_distance(CCustomDistance* distance) const;
void unset_precomputed_distance() const;
private:
std::vector<std::shared_ptr<CKernel> > m_kernels;
std::vector<std::shared_ptr<CCustomKernel> > m_precomputed_kernels;
Expand Down
22 changes: 3 additions & 19 deletions src/shogun/statistical_testing/internals/mmd/MultiKernelMMD.cpp
Expand Up @@ -85,15 +85,8 @@ void MultiKernelMMD::add_term(terms_t& t, float32_t val, index_t i, index_t j) c
SGVector<float64_t> MultiKernelMMD::operator()(const KernelManager& kernel_mgr) const
{
SG_SDEBUG("Entering!\n");
for (size_t i=0; i<kernel_mgr.num_kernels(); ++i)
{
CShiftInvariantKernel* kernel=dynamic_cast<CShiftInvariantKernel*>(kernel_mgr.kernel_at(i));
REQUIRE(kernel!=nullptr, "Kernel instance (was %s) must be of CShiftInvarintKernel type!\n",
kernel_mgr.kernel_at(i)->get_name());
kernel->m_precomputed_distance=m_distance.get();
kernel->num_lhs=n_x+n_y;
kernel->num_rhs=n_x+n_y;
}
REQUIRE(m_distance, "Distance instace is not set!\n");
kernel_mgr.set_precomputed_distance(m_distance.get());

SGVector<float64_t> result(kernel_mgr.num_kernels());
#pragma omp parallel for
Expand Down Expand Up @@ -145,16 +138,7 @@ SGVector<float64_t> MultiKernelMMD::operator()(const KernelManager& kernel_mgr)
SG_SDEBUG("result[%d] = %f!\n", k, result[k]);
}

for (size_t i=0; i<kernel_mgr.num_kernels(); ++i)
{
CShiftInvariantKernel* kernel=dynamic_cast<CShiftInvariantKernel*>(kernel_mgr.kernel_at(i));
REQUIRE(kernel!=nullptr, "Kernel instance (was %s) must be of CShiftInvarintKernel type!\n",
kernel_mgr.kernel_at(i)->get_name());
kernel->m_precomputed_distance=nullptr;
kernel->num_lhs=0;
kernel->num_rhs=0;
}

kernel_mgr.unset_precomputed_distance();
SG_SDEBUG("Leaving!\n");
return result;
}

0 comments on commit 37f34f6

Please sign in to comment.