Skip to content

Commit

Permalink
Refactored GaussianKernel as a subclass of ShiftInvariantKernel
Browse files Browse the repository at this point in the history
  • Loading branch information
lambday committed Jun 16, 2016
1 parent 8798d99 commit 6c56709
Show file tree
Hide file tree
Showing 7 changed files with 358 additions and 227 deletions.
2 changes: 2 additions & 0 deletions src/interfaces/modular/Kernel.i
Expand Up @@ -59,6 +59,7 @@ PROTOCOLS_CUSTOMKERNEL(CustomKernel, float32_t, "f\0", NPY_FLOAT32)
%rename(DistanceKernel) CDistanceKernel;
%rename(FixedDegreeStringKernel) CFixedDegreeStringKernel;
%rename(GaussianKernel) CGaussianKernel;
%rename(ShiftInvariantKernel) CShiftInvariantKernel;
%rename(GaussianCompactKernel) CGaussianCompactKernel;
%rename(DirectorKernel) CDirectorKernel;
%rename(WaveletKernel) CWaveletKernel;
Expand Down Expand Up @@ -187,6 +188,7 @@ namespace shogun
%include <shogun/kernel/ExponentialKernel.h>
%include <shogun/kernel/string/FixedDegreeStringKernel.h>
%include <shogun/kernel/GaussianKernel.h>
%include <shogun/kernel/ShiftInvariantKernel.h>
%include <shogun/kernel/DirectorKernel.h>
%include <shogun/kernel/GaussianShiftKernel.h>
%include <shogun/kernel/GaussianShortRealKernel.h>
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/modular/Kernel_includes.i
Expand Up @@ -26,6 +26,7 @@
#include <shogun/kernel/DistanceKernel.h>
#include <shogun/kernel/string/FixedDegreeStringKernel.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/kernel/ShiftInvariantKernel.h>
#include <shogun/kernel/DirectorKernel.h>
#include <shogun/kernel/GaussianShiftKernel.h>
#include <shogun/kernel/GaussianShortRealKernel.h>
Expand Down
1 change: 1 addition & 0 deletions src/shogun/kernel/GaussianCompactKernel.cpp
@@ -1,4 +1,5 @@
#include <shogun/kernel/GaussianCompactKernel.h>
#include <shogun/features/DotFeatures.h>

using namespace shogun;

Expand Down
149 changes: 71 additions & 78 deletions src/shogun/kernel/GaussianKernel.cpp
Expand Up @@ -7,6 +7,7 @@
* Written (W) 1999-2010 Soeren Sonnenburg
* Written (W) 2011 Abhinav Maurya
* Written (W) 2012 Heiko Strathmann
* Written (W) 2016 Soumyajit De
* Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
* Copyright (C) 2010 Berlin Institute of Technology
*/
Expand All @@ -15,45 +16,36 @@
#include <shogun/base/Parameter.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/distance/EuclideanDistance.h>
#include <shogun/io/SGIO.h>
#include <shogun/mathematics/Math.h>

using namespace shogun;

void CGaussianKernel::set_width(float64_t w)
CGaussianKernel::CGaussianKernel() : CShiftInvariantKernel()
{
REQUIRE(w>0, "width (%f) must be positive\n",w);
m_log_width=CMath::log(w/2.0)/2.0;
register_params();
}

float64_t CGaussianKernel::get_width() const
CGaussianKernel::CGaussianKernel(float64_t w) : CShiftInvariantKernel()
{
return CMath::exp(m_log_width*2.0)*2.0;
}

CGaussianKernel::CGaussianKernel() : CDotKernel()
{
init();
}

CGaussianKernel::CGaussianKernel(float64_t w) : CDotKernel()
{
init();
register_params();
set_width(w);
}

CGaussianKernel::CGaussianKernel(int32_t size, float64_t w) : CDotKernel(size)
CGaussianKernel::CGaussianKernel(int32_t size, float64_t w) : CShiftInvariantKernel()
{
init();
register_params();
set_cache_size(size);
set_width(w);
}

CGaussianKernel::CGaussianKernel(CDotFeatures* l, CDotFeatures* r,
float64_t w, int32_t size) : CDotKernel(size)
CGaussianKernel::CGaussianKernel(CDotFeatures* l, CDotFeatures* r, float64_t w, int32_t size) : CShiftInvariantKernel(l, r)
{
init();
register_params();
set_cache_size(size);
set_width(w);
init(l,r);
init(l, r);
}

CGaussianKernel::~CGaussianKernel()
Expand All @@ -74,94 +66,68 @@ CGaussianKernel* CGaussianKernel::obtain_from_generic(CKernel* kernel)
return (CGaussianKernel*)kernel;
}

#include <typeinfo>
CSGObject *CGaussianKernel::shallow_copy() const
{
// TODO: remove this after all the classes get shallow_copy properly implemented
// this assert is to avoid any subclass of CGaussianKernel accidentally called
// with the implement here
ASSERT(typeid(*this) == typeid(CGaussianKernel))
CGaussianKernel *ker = new CGaussianKernel(cache_size, get_width());
if (lhs)
{
ker->init(lhs, rhs);
}
return ker;
}

void CGaussianKernel::cleanup()
{
if (sq_lhs != sq_rhs)
SG_FREE(sq_rhs);
sq_rhs = NULL;

SG_FREE(sq_lhs);
sq_lhs = NULL;

m_distance->reset_precompute();
CKernel::cleanup();
}

void CGaussianKernel::precompute_squared_helper(float64_t* &buf, CDotFeatures* df)
bool CGaussianKernel::init(CFeatures* l, CFeatures* r)
{
ASSERT(df)
int32_t num_vec=df->get_num_vectors();
buf=SG_MALLOC(float64_t, num_vec);
CShiftInvariantKernel::init(l, r);
m_distance->reset_precompute();

for (int32_t i=0; i<num_vec; i++)
buf[i]=df->dot(i,df, i);
}
REQUIRE(l->has_property(FP_DOT), "Left hand side (%s) must be a subclass of DotFeatures!\n", l->get_name());
REQUIRE(r->has_property(FP_DOT), "Right hand side (%s) must be a subclass of DotFeatures!\n", r->get_name())

bool CGaussianKernel::init(CFeatures* l, CFeatures* r)
{
///free sq_{r,l}hs first
cleanup();
int32_t lhs_dim_feature_space=static_cast<CDotFeatures*>(l)->get_dim_feature_space();
int32_t rhs_dim_feature_space=static_cast<CDotFeatures*>(r)->get_dim_feature_space();

CDotKernel::init(l, r);
precompute_squared();
REQUIRE(lhs_dim_feature_space==rhs_dim_feature_space,
"Train or test features #dimension mismatch (l:%d vs. r:%d)\n",
lhs_dim_feature_space, rhs_dim_feature_space);

precompute_squared_norms();
return init_normalizer();
}

float64_t CGaussianKernel::compute(int32_t idx_a, int32_t idx_b)
{
float64_t result=distance(idx_a,idx_b);
float64_t result=distance(idx_a, idx_b);
return CMath::exp(-result);
}

void CGaussianKernel::load_serializable_post() throw (ShogunException)
{
CKernel::load_serializable_post();
precompute_squared();
precompute_squared_norms();
}

void CGaussianKernel::precompute_squared()
void CGaussianKernel::precompute_squared_norms()
{
if (!lhs || !rhs)
return;

precompute_squared_helper(sq_lhs, (CDotFeatures*) lhs);

if (lhs==rhs)
sq_rhs=sq_lhs;
else
precompute_squared_helper(sq_rhs, (CDotFeatures*) rhs);
if (lhs && rhs)
{
m_distance->precompute_lhs();
m_distance->precompute_rhs();
}
}

SGMatrix<float64_t> CGaussianKernel::get_parameter_gradient(
const TParameter* param, index_t index)
SGMatrix<float64_t> CGaussianKernel::get_parameter_gradient(const TParameter* param, index_t index)
{
REQUIRE(lhs && rhs, "Features not set!\n")
REQUIRE(lhs, "The left hand side feature instance cannot be NULL!\n");
REQUIRE(rhs, "The right hand side feature instance cannot be NULL!\n");

if (!strcmp(param->m_name, "log_width"))
{
SGMatrix<float64_t> derivative=SGMatrix<float64_t>(num_lhs, num_rhs);

for (int j=0; j<num_lhs; j++)
{
for (int k=0; k<num_rhs; k++)
{
float64_t element=distance(j,k);
derivative(j,k)=exp(-element)*element*2.0;
}

}
return derivative;
}
else
Expand All @@ -171,15 +137,42 @@ SGMatrix<float64_t> CGaussianKernel::get_parameter_gradient(
}
}

void CGaussianKernel::init()
void CGaussianKernel::register_params()
{
set_width(1.0);
sq_lhs=NULL;
sq_rhs=NULL;
set_cache_size(10);
m_distance=new CEuclideanDistance();
SG_REF(m_distance);
SG_ADD(&m_log_width, "log_width", "Kernel width in log domain", MS_AVAILABLE, GRADIENT_AVAILABLE);
}

float64_t CGaussianKernel::distance(int32_t idx_a, int32_t idx_b)
void CGaussianKernel::set_width(float64_t w)
{
return (sq_lhs[idx_a]+sq_rhs[idx_b]-2*CDotKernel::compute(idx_a,idx_b))/get_width();
REQUIRE(w>0, "width (%f) must be positive\n",w);
m_log_width=CMath::log(w/2.0)/2.0;
}

float64_t CGaussianKernel::get_width() const
{
return CMath::exp(m_log_width*2.0)*2.0;
}

float64_t CGaussianKernel::distance(int32_t idx_a, int32_t idx_b) const
{
float64_t distance=CShiftInvariantKernel::distance(idx_a, idx_b);
return distance*distance/get_width();
}

#include <typeinfo>
CSGObject *CGaussianKernel::shallow_copy() const
{
// TODO: remove this after all the classes get shallow_copy properly implemented
// this assert is to avoid any subclass of CGaussianKernel accidentally called
// with the implement here
ASSERT(typeid(*this) == typeid(CGaussianKernel))
CGaussianKernel *ker = new CGaussianKernel(cache_size, get_width());
if (lhs)
ker->init(lhs, rhs);

return ker;
}

0 comments on commit 6c56709

Please sign in to comment.