//=========================================================================== /*! * * * \brief Applies a kernel to two pointsets and comptues the average response * * * * \author T.Glasmachers, O. Krause, M. Tuma * \date 2010, 2011 * * * \par Copyright 1995-2017 Shark Development Team * *

* This file is part of Shark. * * * Shark is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Shark is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Shark. If not, see . * */ //=========================================================================== #ifndef SHARK_MODELS_KERNELS_POINT_SET_KERNEL_H #define SHARK_MODELS_KERNELS_POINT_SET_KERNEL_H #include namespace shark { /// \brief Normalized version of a kernel function /// /// For a positive definite kernel k, the normalized kernel /// \f[ \tilde k(x, y) := \frac{k(x, y)}{\sqrt{k(x, x) \cdot k(y, y)}} \f] /// is again a positive definite kernel function. template class PointSetKernel : public AbstractKernelFunction::type > { private: typedef AbstractKernelFunction::type> base_type; struct InternalState: public State{ std::vector > state; void resize(std::size_t sizeX1,std::size_t sizeX2, AbstractKernelFunction const* base){ state.resize(sizeX1 * sizeX2); for(std::size_t i = 0; i != state.size();++i){ state[i] = base->createState(); } } }; public: typedef typename base_type::BatchInputType BatchInputType; typedef typename base_type::ConstBatchInputReference ConstBatchInputReference; typedef typename base_type::ConstInputReference ConstInputReference; PointSetKernel(AbstractKernelFunction* base) : m_base(base){ SHARK_ASSERT( base != NULL ); if ( m_base->hasFirstParameterDerivative() ) this->m_features|=base_type::HAS_FIRST_PARAMETER_DERIVATIVE; } std::string name() const { return "PointSetKernel<" + m_base->name() + ">"; } RealVector parameterVector() const{ return m_base->parameterVector(); } void setParameterVector(RealVector const& newParameters){ m_base->setParameterVector(newParameters); } std::size_t numberOfParameters() const{ return m_base->numberOfParameters(); } ///\brief creates the internal state of the kernel boost::shared_ptr createState()const{ InternalState* state = new InternalState(); return boost::shared_ptr(state); } ///evaluates \f$ k(x,y) \f$ /// /// calculates /// \f[ \tilde k(x, y) := \frac{k(x, y)}{\sqrt{k(x, x) \cdot k(y, y)}} \f] double eval(ConstInputReference x1, ConstInputReference x2) const{ RealMatrix response = (*m_base)(x1,x2); return sum(response)/(response.size1() * response.size2()); } void eval(ConstBatchInputReference const& batchX1, ConstBatchInputReference const& batchX2, RealMatrix& result, State& state) const{ InternalState& s = state.toState(); std::size_t sizeX1 = batchSize(batchX1); std::size_t sizeX2 = batchSize(batchX2); s.resize(sizeX1,sizeX2,m_base); result.resize(sizeX1,sizeX2); RealMatrix response; for(std::size_t i = 0; i != sizeX1; ++i){ for(std::size_t j = 0; j != sizeX2; ++j){ m_base->eval(getBatchElement(batchX1,i),getBatchElement(batchX2,j),response,*s.state[i*sizeX2+j]); result(i,j) = sum(response)/(response.size1() * response.size2()); } } } void eval(ConstBatchInputReference const& batchX1, ConstBatchInputReference const& batchX2, RealMatrix& result) const{ std::size_t sizeX1 = batchSize(batchX1); std::size_t sizeX2 = batchSize(batchX2); result.resize(sizeX1,sizeX2); RealMatrix response; for(std::size_t i = 0; i != sizeX1; ++i){ for(std::size_t j = 0; j != sizeX2; ++j){ m_base->eval(getBatchElement(batchX1,i),getBatchElement(batchX2,j),response); result(i,j) = sum(response)/(response.size1() * response.size2()); } } } void weightedParameterDerivative( ConstBatchInputReference const& batchX1, ConstBatchInputReference const& batchX2, RealMatrix const& coefficients, State const& state, RealVector& gradient ) const{ gradient.resize(numberOfParameters()); InternalState const& s = state.toState(); std::size_t sizeX1 = batchSize(batchX1); std::size_t sizeX2 = batchSize(batchX2); for(std::size_t i = 0; i != sizeX1; ++i){ for(std::size_t j = 0; j != sizeX2; ++j){ auto x1 = getBatchElement(batchX1,i); auto x2 = getBatchElement(batchX2,j); std::size_t size1 = batchSize(x1); std::size_t size2 = batchSize(x2); RealMatrix setCoeff(size1,size2, coefficients(i,j)/(size1 * size2)); RealVector grad; m_base->weightedParameterDerivative(x1,x2,setCoeff,*s.state[i*sizeX2+j],grad); noalias(gradient) += grad; } } } protected: /// kernel to normalize AbstractKernelFunction* m_base; }; } #endif