// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_SVm_KERNEL #define DLIB_SVm_KERNEL #include "kernel_abstract.h" #include <cmath> #include <limits> #include <sstream> #include "../matrix.h" #include "../algs.h" #include "../serialize.h" namespace dlib { // ---------------------------------------------------------------------------------------- template < typename kernel_type > struct kernel_derivative; // ---------------------------------------------------------------------------------------- template < typename T > struct radial_basis_kernel { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; // T must be capable of representing a column vector. COMPILE_TIME_ASSERT(T::NC == 1 || T::NC == 0); radial_basis_kernel(const scalar_type g) : gamma(g) {} radial_basis_kernel() : gamma(0.1) {} radial_basis_kernel( const radial_basis_kernel& k ) : gamma(k.gamma) {} const scalar_type gamma; scalar_type operator() ( const sample_type& a, const sample_type& b ) const { const scalar_type d = trans(a-b)*(a-b); return std::exp(-gamma*d); } radial_basis_kernel& operator= ( const radial_basis_kernel& k ) { const_cast<scalar_type&>(gamma) = k.gamma; return *this; } bool operator== ( const radial_basis_kernel& k ) const { return gamma == k.gamma; } }; template < typename T > void serialize ( const radial_basis_kernel<T>& item, std::ostream& out ) { try { serialize(item.gamma, out); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while serializing object of type radial_basis_kernel"); } } template < typename T > void deserialize ( radial_basis_kernel<T>& item, std::istream& in ) { typedef typename T::type scalar_type; try { deserialize(const_cast<scalar_type&>(item.gamma), in); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while deserializing object of type radial_basis_kernel"); } } template < typename T > struct kernel_derivative<radial_basis_kernel<T> > { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; kernel_derivative(const radial_basis_kernel<T>& k_) : k(k_){} const sample_type& operator() (const sample_type& x, const sample_type& y) const { // return the derivative of the rbf kernel temp = 2*k.gamma*(x-y)*k(x,y); return temp; } const radial_basis_kernel<T>& k; mutable sample_type temp; }; // ---------------------------------------------------------------------------------------- template < typename T > struct polynomial_kernel { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; // T must be capable of representing a column vector. COMPILE_TIME_ASSERT(T::NC == 1 || T::NC == 0); polynomial_kernel(const scalar_type g, const scalar_type c, const scalar_type d) : gamma(g), coef(c), degree(d) {} polynomial_kernel() : gamma(1), coef(0), degree(1) {} polynomial_kernel( const polynomial_kernel& k ) : gamma(k.gamma), coef(k.coef), degree(k.degree) {} typedef T type; const scalar_type gamma; const scalar_type coef; const scalar_type degree; scalar_type operator() ( const sample_type& a, const sample_type& b ) const { return std::pow(gamma*(trans(a)*b) + coef, degree); } polynomial_kernel& operator= ( const polynomial_kernel& k ) { const_cast<scalar_type&>(gamma) = k.gamma; const_cast<scalar_type&>(coef) = k.coef; const_cast<scalar_type&>(degree) = k.degree; return *this; } bool operator== ( const polynomial_kernel& k ) const { return (gamma == k.gamma) && (coef == k.coef) && (degree == k.degree); } }; template < typename T > void serialize ( const polynomial_kernel<T>& item, std::ostream& out ) { try { serialize(item.gamma, out); serialize(item.coef, out); serialize(item.degree, out); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while serializing object of type polynomial_kernel"); } } template < typename T > void deserialize ( polynomial_kernel<T>& item, std::istream& in ) { typedef typename T::type scalar_type; try { deserialize(const_cast<scalar_type&>(item.gamma), in); deserialize(const_cast<scalar_type&>(item.coef), in); deserialize(const_cast<scalar_type&>(item.degree), in); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while deserializing object of type polynomial_kernel"); } } template < typename T > struct kernel_derivative<polynomial_kernel<T> > { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; kernel_derivative(const polynomial_kernel<T>& k_) : k(k_){} const sample_type& operator() (const sample_type& x, const sample_type& y) const { // return the derivative of the rbf kernel temp = k.degree*k.gamma*x*std::pow(k.gamma*(trans(x)*y) + k.coef, k.degree-1); return temp; } const polynomial_kernel<T>& k; mutable sample_type temp; }; // ---------------------------------------------------------------------------------------- template < typename T > struct sigmoid_kernel { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; // T must be capable of representing a column vector. COMPILE_TIME_ASSERT(T::NC == 1 || T::NC == 0); sigmoid_kernel(const scalar_type g, const scalar_type c) : gamma(g), coef(c) {} sigmoid_kernel() : gamma(0.1), coef(-1.0) {} sigmoid_kernel( const sigmoid_kernel& k ) : gamma(k.gamma), coef(k.coef) {} typedef T type; const scalar_type gamma; const scalar_type coef; scalar_type operator() ( const sample_type& a, const sample_type& b ) const { return std::tanh(gamma*(trans(a)*b) + coef); } sigmoid_kernel& operator= ( const sigmoid_kernel& k ) { const_cast<scalar_type&>(gamma) = k.gamma; const_cast<scalar_type&>(coef) = k.coef; return *this; } bool operator== ( const sigmoid_kernel& k ) const { return (gamma == k.gamma) && (coef == k.coef); } }; template < typename T > void serialize ( const sigmoid_kernel<T>& item, std::ostream& out ) { try { serialize(item.gamma, out); serialize(item.coef, out); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while serializing object of type sigmoid_kernel"); } } template < typename T > void deserialize ( sigmoid_kernel<T>& item, std::istream& in ) { typedef typename T::type scalar_type; try { deserialize(const_cast<scalar_type&>(item.gamma), in); deserialize(const_cast<scalar_type&>(item.coef), in); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while deserializing object of type sigmoid_kernel"); } } template < typename T > struct kernel_derivative<sigmoid_kernel<T> > { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; kernel_derivative(const sigmoid_kernel<T>& k_) : k(k_){} const sample_type& operator() (const sample_type& x, const sample_type& y) const { // return the derivative of the rbf kernel temp = k.gamma*x*(1-std::pow(k(x,y),2)); return temp; } const sigmoid_kernel<T>& k; mutable sample_type temp; }; // ---------------------------------------------------------------------------------------- template <typename T> struct linear_kernel { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; // T must be capable of representing a column vector. COMPILE_TIME_ASSERT(T::NC == 1 || T::NC == 0); scalar_type operator() ( const sample_type& a, const sample_type& b ) const { return trans(a)*b; } bool operator== ( const linear_kernel& ) const { return true; } }; template < typename T > void serialize ( const linear_kernel<T>& , std::ostream& ){} template < typename T > void deserialize ( linear_kernel<T>& , std::istream& ){} template < typename T > struct kernel_derivative<linear_kernel<T> > { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; kernel_derivative(const linear_kernel<T>& k_) : k(k_){} const sample_type& operator() (const sample_type& x, const sample_type& ) const { return x; } const linear_kernel<T>& k; }; // ---------------------------------------------------------------------------------------- template <typename T> struct histogram_intersection_kernel { typedef typename T::type scalar_type; typedef T sample_type; typedef typename T::mem_manager_type mem_manager_type; scalar_type operator() ( const sample_type& a, const sample_type& b ) const { scalar_type temp = 0; for (long i = 0; i < a.size(); ++i) { temp += std::min(a(i), b(i)); } return temp; } bool operator== ( const histogram_intersection_kernel& ) const { return true; } }; template < typename T > void serialize ( const histogram_intersection_kernel<T>& , std::ostream& ){} template < typename T > void deserialize ( histogram_intersection_kernel<T>& , std::istream& ){} // ---------------------------------------------------------------------------------------- template <typename T> struct offset_kernel { typedef typename T::scalar_type scalar_type; typedef typename T::sample_type sample_type; typedef typename T::mem_manager_type mem_manager_type; offset_kernel(const T& k, const scalar_type& offset_ ) : kernel(k), offset(offset_) {} offset_kernel() : kernel(T()), offset(0.01) {} offset_kernel( const offset_kernel& k ) : kernel(k.kernel), offset(k.offset) {} const T kernel; const scalar_type offset; scalar_type operator() ( const sample_type& a, const sample_type& b ) const { return kernel(a,b) + offset; } offset_kernel& operator= ( const offset_kernel& k ) { const_cast<T&>(kernel) = k.kernel; const_cast<scalar_type&>(offset) = k.offset; return *this; } bool operator== ( const offset_kernel& k ) const { return k.kernel == kernel && offset == k.offset; } }; template < typename T > void serialize ( const offset_kernel<T>& item, std::ostream& out ) { try { serialize(item.offset, out); serialize(item.kernel, out); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while serializing object of type offset_kernel"); } } template < typename T > void deserialize ( offset_kernel<T>& item, std::istream& in ) { typedef typename offset_kernel<T>::scalar_type scalar_type; try { deserialize(const_cast<scalar_type&>(item.offset), in); deserialize(const_cast<T&>(item.kernel), in); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while deserializing object of type offset_kernel"); } } template < typename T > struct kernel_derivative<offset_kernel<T> > { typedef typename T::scalar_type scalar_type; typedef typename T::sample_type sample_type; typedef typename T::mem_manager_type mem_manager_type; kernel_derivative(const offset_kernel<T>& k) : der(k.kernel){} const sample_type operator() (const sample_type& x, const sample_type& y) const { return der(x,y); } kernel_derivative<T> der; }; // ---------------------------------------------------------------------------------------- } #endif // DLIB_SVm_KERNEL