SubrangeKernel.h
Go to the documentation of this file.
1//===========================================================================
2/*!
3 *
4 *
5 * \brief Variant of WeightedSumKernel which works on subranges of Vector inputs
6 *
7 *
8 *
9 * \author S., O.Krause
10 * \date 2012
11 *
12 *
13 * \par Copyright 1995-2017 Shark Development Team
14 *
15 * <BR><HR>
16 * This file is part of Shark.
17 * <https://shark-ml.github.io/Shark/>
18 *
19 * Shark is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU Lesser General Public License as published
21 * by the Free Software Foundation, either version 3 of the License, or
22 * (at your option) any later version.
23 *
24 * Shark is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU Lesser General Public License for more details.
28 *
29 * You should have received a copy of the GNU Lesser General Public License
30 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
31 *
32 */
33//===========================================================================
34
35#ifndef SHARK_MODELS_KERNELS_SUBRANGE_KERNEL_H
36#define SHARK_MODELS_KERNELS_SUBRANGE_KERNEL_H
37
38
40namespace shark {
41namespace detail{
42/// \brief given two vectors of input x = (x_1,...,x_n), y = (y_1,...,y_n), a subrange 1<=k<l<=n and a kernel k, computes the result of
43/// the subrange k((x_k,...x_l),(y_k,...,y_l))
44/// \ingroup kernels
45template<class InputType>
46class SubrangeKernelWrapper : public AbstractKernelFunction<InputType>{
47private:
48 typedef AbstractKernelFunction<InputType> base_type;
49public:
53
54 SubrangeKernelWrapper(AbstractKernelFunction<InputType>* kernel,std::size_t start, std::size_t end)
55 :m_kernel(kernel),m_start(start),m_end(end){
56 if(kernel->hasFirstParameterDerivative())
58 if(kernel->hasFirstInputDerivative())
60 }
61
62 /// \brief From INameable: return the class name.
63 std::string name() const
64 { return "SubrangeKernelWrapper"; }
65
66 RealVector parameterVector() const {
67 return m_kernel->parameterVector();
68 }
69
70 void setParameterVector(RealVector const& newParameters) {
71 m_kernel->setParameterVector(newParameters);
72 }
73
74 std::size_t numberOfParameters() const {
75 return m_kernel->numberOfParameters();
76 }
77
78 ///\brief creates the internal state of the kernel
79 boost::shared_ptr<State> createState()const{
80 return m_kernel->createState();
81 }
82
83 double eval(ConstInputReference x1, ConstInputReference x2) const{
84 return m_kernel->eval(blas::subrange(x1,m_start,m_end),blas::subrange(x2,m_start,m_end));
85 }
86
87 void eval(ConstBatchInputReference batchX1, ConstBatchInputReference batchX2, RealMatrix& result, State& state) const{
88 m_kernel->eval(columns(batchX1,m_start,m_end),columns(batchX2,m_start,m_end),result,state);
89 }
90
91 void eval(ConstBatchInputReference batchX1, ConstBatchInputReference batchX2, RealMatrix& result) const{
92 m_kernel->eval(columns(batchX1,m_start,m_end),columns(batchX2,m_start,m_end),result);
93 }
94
96 ConstBatchInputReference batchX1,
97 ConstBatchInputReference batchX2,
98 RealMatrix const& coefficients,
99 State const& state,
100 RealVector& gradient
101 ) const{
102 m_kernel->weightedParameterDerivative(
103 columns(batchX1,m_start,m_end),
104 columns(batchX2,m_start,m_end),
105 coefficients,
106 state,
107 gradient
108 );
109 }
111 ConstBatchInputReference batchX1,
112 ConstBatchInputReference batchX2,
113 RealMatrix const& coefficientsX2,
114 State const& state,
115 BatchInputType& gradient
116 ) const{
117 BatchInputType temp(gradient.size1(),m_end-m_start);
118 m_kernel->weightedInputDerivative(
119 columns(batchX1,m_start,m_end),
120 columns(batchX2,m_start,m_end),
121 coefficientsX2,
122 state,
123 temp
124 );
125 ensure_size(gradient,batchX1.size1(),batchX2.size2());
126 gradient.clear();
127 noalias(columns(gradient,m_start,m_end)) = temp;
128 }
129
130 //w don't need serializing here, this is done by the implementing Kernel
131 void read(InArchive& ar){
132 }
133 void write(OutArchive& ar) const{
134 }
135
136private:
137 AbstractKernelFunction<InputType>* m_kernel;
138 std::size_t m_start;
139 std::size_t m_end;
140};
141
142template<class InputType>
143class SubrangeKernelBase
144{
145public:
146
147 template<class Kernels,class Ranges>
148 SubrangeKernelBase(Kernels const& kernels, Ranges const& ranges){
149 SIZE_CHECK(kernels.size() == ranges.size());
150 for(std::size_t i = 0; i != kernels.size(); ++i){
151 m_kernelWrappers.push_back(
152 SubrangeKernelWrapper<InputType>(kernels[i],ranges[i].first,ranges[i].second)
153 );
154 }
155 }
156
157 std::vector<AbstractKernelFunction<InputType>* > makeKernelVector(){
158 std::vector<AbstractKernelFunction<InputType>* > kernels(m_kernelWrappers.size());
159 for(std::size_t i = 0; i != m_kernelWrappers.size(); ++i)
160 kernels[i] = & m_kernelWrappers[i];
161 return kernels;
162 }
163
164 std::vector<SubrangeKernelWrapper <InputType> > m_kernelWrappers;
165};
166}
167
168/// \brief Weighted sum of kernel functions
169///
170/// For a set of positive definite kernels \f$ k_1, \dots, k_n \f$
171/// with positive coeffitients \f$ w_1, \dots, w_n \f$ the sum
172/// \f[ \tilde k(x_1, x_2) := \sum_{i=1}^{n} w_i \cdot k_i(x_1, x_2) \f]
173/// is again a positive definite kernel function. This still holds when
174/// the sub-kernels only operate of a subset of features, that is, when
175/// we have a direct sum kernel ( see e.g. the UCSC Technical Report UCSC-CRL-99-10:
176/// Convolution Kernels on Discrete Structures by David Haussler ).
177///
178/// This class is very similar to the #WeightedSumKernel , except that it assumes it's
179/// inputs to be tuples of values \f$ x=(x_1,\dots, x_n) \f$ and we calculate the direct
180/// sum of kernels
181/// \f[ \tilde k(x, y) := \sum_{i=1}^{n} w_i \cdot k_i(x_i, y_i) \f]
182///
183/// Internally, the weights are represented as \f$ w_i = \exp(\xi_i) \f$
184/// to allow for unconstrained optimization.
185///
186/// The result of the kernel evaluation is devided by the sum of the
187/// kernel weights, so that in total, this amounts to fixing the sum
188/// of the weights to one.
189template<class InputType, class InnerKernel=WeightedSumKernel<InputType> >
191: private detail::SubrangeKernelBase<InputType>//order is important!
192, public InnerKernel
193{
194private:
195 typedef detail::SubrangeKernelBase<InputType> base_type1;
196public:
197
198 /// \brief From INameable: return the class name.
199 std::string name() const
200 { return "SubrangeKernel"; }
201
202 template<class Kernels,class Ranges>
203 SubrangeKernel(Kernels const& kernels, Ranges const& ranges)
204 : base_type1(kernels,ranges)
205 , InnerKernel(base_type1::makeKernelVector()){}
206};
207
210
211}
212#endif