PointSetKernel.h
Go to the documentation of this file.
1 //===========================================================================
2 /*!
3  *
4  *
5  * \brief Applies a kernel to two pointsets and comptues the average response
6  *
7  *
8  *
9  * \author T.Glasmachers, O. Krause, M. Tuma
10  * \date 2010, 2011
11  *
12  *
13  * \par Copyright 1995-2017 Shark Development Team
14  *
15  * <BR><HR>
16  * This file is part of Shark.
17  * <http://shark-ml.org/>
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_POINT_SET_KERNEL_H
36 #define SHARK_MODELS_KERNELS_POINT_SET_KERNEL_H
37 
38 
40 
41 namespace shark {
42 
43 
44 /// \brief Normalized version of a kernel function
45 ///
46 /// For a positive definite kernel k, the normalized kernel
47 /// \f[ \tilde k(x, y) := \frac{k(x, y)}{\sqrt{k(x, x) \cdot k(y, y)}} \f]
48 /// is again a positive definite kernel function.
49 template<class InputType=RealVector>
50 class PointSetKernel : public AbstractKernelFunction<typename Batch<InputType>::type >
51 {
52 private:
54 
55  struct InternalState: public State{
56  std::vector<boost::shared_ptr<State> > state;
57 
58  void resize(std::size_t sizeX1,std::size_t sizeX2, AbstractKernelFunction<InputType> const* base){
59  state.resize(sizeX1 * sizeX2);
60 
61  for(std::size_t i = 0; i != state.size();++i){
62  state[i] = base->createState();
63  }
64  }
65  };
66 public:
70 
72  SHARK_ASSERT( base != NULL );
75  }
76 
77  std::string name() const
78  { return "PointSetKernel<" + m_base->name() + ">"; }
79 
80  RealVector parameterVector() const{
81  return m_base->parameterVector();
82  }
83 
84  void setParameterVector(RealVector const& newParameters){
85  m_base->setParameterVector(newParameters);
86  }
87 
88  std::size_t numberOfParameters() const{
89  return m_base->numberOfParameters();
90  }
91 
92  ///\brief creates the internal state of the kernel
93  boost::shared_ptr<State> createState()const{
94  InternalState* state = new InternalState();
95  return boost::shared_ptr<State>(state);
96  }
97 
98  ///evaluates \f$ k(x,y) \f$
99  ///
100  /// calculates
101  /// \f[ \tilde k(x, y) := \frac{k(x, y)}{\sqrt{k(x, x) \cdot k(y, y)}} \f]
102  double eval(ConstInputReference x1, ConstInputReference x2) const{
103  RealMatrix response = (*m_base)(x1,x2);
104 
105  return sum(response)/(response.size1() * response.size2());
106  }
107 
108 
109  void eval(ConstBatchInputReference const& batchX1, ConstBatchInputReference const& batchX2, RealMatrix& result, State& state) const{
110  InternalState& s = state.toState<InternalState>();
111 
112  std::size_t sizeX1 = batchSize(batchX1);
113  std::size_t sizeX2 = batchSize(batchX2);
114  s.resize(sizeX1,sizeX2,m_base);
115  result.resize(sizeX1,sizeX2);
116  RealMatrix response;
117  for(std::size_t i = 0; i != sizeX1; ++i){
118  for(std::size_t j = 0; j != sizeX2; ++j){
119  m_base->eval(getBatchElement(batchX1,i),getBatchElement(batchX2,j),response,*s.state[i*sizeX2+j]);
120  result(i,j) = sum(response)/(response.size1() * response.size2());
121  }
122  }
123  }
124 
125  void eval(ConstBatchInputReference const& batchX1, ConstBatchInputReference const& batchX2, RealMatrix& result) const{
126  std::size_t sizeX1 = batchSize(batchX1);
127  std::size_t sizeX2 = batchSize(batchX2);
128  result.resize(sizeX1,sizeX2);
129 
130  RealMatrix response;
131  for(std::size_t i = 0; i != sizeX1; ++i){
132  for(std::size_t j = 0; j != sizeX2; ++j){
133  m_base->eval(getBatchElement(batchX1,i),getBatchElement(batchX2,j),response);
134  result(i,j) = sum(response)/(response.size1() * response.size2());
135  }
136  }
137  }
138 
140  ConstBatchInputReference const& batchX1,
141  ConstBatchInputReference const& batchX2,
142  RealMatrix const& coefficients,
143  State const& state,
144  RealVector& gradient
145  ) const{
146  gradient.resize(numberOfParameters());
147  InternalState const& s = state.toState<InternalState>();
148  std::size_t sizeX1 = batchSize(batchX1);
149  std::size_t sizeX2 = batchSize(batchX2);
150 
151  for(std::size_t i = 0; i != sizeX1; ++i){
152  for(std::size_t j = 0; j != sizeX2; ++j){
153  auto x1 = getBatchElement(batchX1,i);
154  auto x2 = getBatchElement(batchX2,j);
155  std::size_t size1 = batchSize(x1);
156  std::size_t size2 = batchSize(x2);
157  RealMatrix setCoeff(size1,size2, coefficients(i,j)/(size1 * size2));
158  RealVector grad;
159  m_base->weightedParameterDerivative(x1,x2,setCoeff,*s.state[i*sizeX2+j],grad);
160  noalias(gradient) += grad;
161  }
162  }
163  }
164 
165 protected:
166  /// kernel to normalize
168 };
169 
170 }
171 #endif