UFJF - Machine Learning Toolkit  0.51.8
Kernel.hpp
Go to the documentation of this file.
1 
5 #pragma once
6 
7 #include <vector>
8 #include <memory>
9 #include <cmath>
10 #include <utility>
11 
12 #include "Data.hpp"
13 #include "Utils.hpp"
14 
15 namespace mltk{
16  enum KernelType {INVALID_TYPE = -1, INNER_PRODUCT, POLYNOMIAL, GAUSSIAN, CUSTOM};
17 
21  template<typename T = double>
22  class Kernel {
23  // Attributes
24  private :
25  template<typename U>
26  struct FunctionType
27  {
28  typedef std::function<double(mltk::Point<U>& a, mltk::Point<U>& b, double param)> Type ;
29  } ;
30 
31  typename FunctionType<T>::Type func{nullptr};
32  bool computed = false;
34  int type{};
36  double param{};
38  mltk::dMatrix K;
40  mltk::dMatrix H;
42  mltk::dMatrix HwithoutDim;
43  public :
47  Kernel(int type = 0, double param = 0);
52  mltk::dMatrix* getKernelMatrixPointer();
57  Kernel(mltk::dMatrix kernel_matrix);
62  void setType(int type);
67  void setParam(double param);
72  int getType();
77  double getParam();
82  void setKernelMatrix(mltk::dMatrix K);
87  mltk::dMatrix getKernelMatrix();
88  void recompute(){ this->computed = false;}
93  void compute(std::shared_ptr<Data< T > > samples,
94  typename FunctionType<T>::Type f = nullptr);
100  mltk::dMatrix* generateMatrixH(std::shared_ptr<Data< T > > samples);
107  mltk::dMatrix* generateMatrixHwithoutDim(std::shared_ptr<Data< T > > samples, int dim);
115  double function(std::shared_ptr<Point< T > > one, std::shared_ptr<Point< T > > two, int dim,
116  typename FunctionType<T>::Type f = nullptr) const;
125  double functionWithoutDim(std::shared_ptr<Point< T > > one, std::shared_ptr<Point< T > > two, int j, int dim);
131  double norm(Data< T > data);
137  double featureSpaceNorm(std::shared_ptr<Data< T > > data);
138 
139  size_t size() const { return K.size(); }
140 
141  double operator()(const Point<T>& a, const Point<T>& b) const{
142  assert(a.size() == b.size());
143  return function(make_point<T>(a), make_point<T>(b), a.size());
144  }
145 
146  void operator()(const Data<T>& samples, typename FunctionType<T>::Type f = nullptr){
147  if(this->type == mltk::CUSTOM){
148  assert(f && "A function must be provided for a custom kernel.");
149  }
150  compute(make_data<T>(samples), f);
151  }
152 
153  std::vector<double> operator[](const size_t& idx) const {
154  assert(idx < K.size());
155  return K[idx];
156  }
157  };
158 
159  template < typename T >
160  void Kernel<T>::compute(const std::shared_ptr<Data< T > > samples, typename FunctionType<T>::Type f){
161  size_t i, j, size = samples->size(), dim = samples->dim();
162 
163  if(computed) return;
164  if(this->type == mltk::CUSTOM) this->func = f;
165  K.assign(size, std::vector<double>(size, 0.0));
166 
167  //Calculating Matrix
168  for(i = 0; i < size; ++i){
169  for(j = i; j < size; ++j){
170  K[i][j] = function((*samples)[i], (*samples)[j], dim, f);
171  K[j][i] = K[i][j];
172  }
173  }
174  computed = true;
175  }
176 
177  template < typename T >
178  mltk::dMatrix* Kernel<T>::generateMatrixH(const std::shared_ptr<Data< T > > samples) {
179  int i = 0, j = 0;
180  size_t size = samples->size(), dim = samples->dim();
181 
182  H.resize(size, std::vector<double>(size));
183 
184  /* Calculating Matrix */
185  for(i = 0; i < size; ++i) {
186  for (j = i; j < size; ++j) {
187  H[i][j] = function(samples->point(i), samples->point(j), dim) * samples->point(i)->Y() *
188  samples->point(j)->Y();
189  H[j][i] = H[i][j];
190  }
191  }
192  return &H;
193  }
194 
195  template < typename T >
196  mltk::dMatrix* Kernel<T>::generateMatrixHwithoutDim(const DataPointer<T> samples, int dim) {
197  int i = 0, j = 0;
198  size_t size = samples->size();
199 
200  for(auto& row: HwithoutDim){
201  row.clear();
202  }
203  HwithoutDim.clear();
204  HwithoutDim = mltk::dMatrix(size, std::vector<double>(size, 0.0));
205 
206  /* Calculating Matrix */
207  for(i = 0; i < size; ++i) {
208  for (j = i; j < size; ++j) {
209  HwithoutDim[i][j] = functionWithoutDim(samples->point(i), samples->point(j), dim, samples->dim());
210  HwithoutDim[j][i] = HwithoutDim[i][j]*samples->point(i)->Y() * samples->point(j)->Y();
211  }
212  }
213  // clog << "\nH matrix without dim generated.\n";
214  return &HwithoutDim;
215  }
216 
217  template < typename T >
218  double Kernel<T>::function(std::shared_ptr<Point< T > > one, std::shared_ptr<Point< T > > two, int dim,
219  typename FunctionType<T>::Type f) const{
220  int i = 0;
221  double t, sum = 0.0;
222  std::vector< T > a = one->X(), b = two->X();
223 
224  // a.erase(a.end());
225  //b.erase(b.end());
226 
227  switch(type)
228  {
229  case mltk::INNER_PRODUCT: //Produto Interno
230  for(i = 0; i < dim; ++i)
231  sum += a[i] * b[i];
232  break;
233  case mltk::POLYNOMIAL: //Polinomial
234  for(i = 0; i < dim; ++i)
235  sum += a[i] * b[i];
236  // sum = (param > 1) ? std::pow(sum+1, param) : sum;
237  sum = (param > 1) ? std::pow(sum, param) : sum;
238  break;
239 
240  case mltk::GAUSSIAN: //Gaussiano
241  for(i = 0; i < dim; ++i)
242  { t = a[i] - b[i]; sum += t * t; }
243  sum = std::exp(-1 * sum * param);
244  break;
245 
246  case mltk::CUSTOM:
247  if(f) sum = f(*one, *two, param);
248  else sum = this->func(*one, *two, param);
249  break;
250  }
251 
252  /*The '+1' here accounts for the bias term "b" in SVM formulation since
253  <w,x> = \sum_i \alpha_i y_i k(x_i,x) + b and b=\sum_i \alpha_i y_i*/
254 
255  return sum;// + 1.0f;
256  }
257 
258  template < typename T >
259  double Kernel<T>::functionWithoutDim(const PointPointer<T> one, const PointPointer<T> two, int j, int dim) {
260  int i = 0;
261  double t, sum = 0.0;
262 
263  switch(type)
264  {
265  case mltk::INNER_PRODUCT: //Produto Interno
266  for(i = 0; i < dim; ++i)
267  if(i != j)
268  sum += (*one)[i] * (*two)[i];
269  break;
270 
271  case mltk::POLYNOMIAL: //Polinomial
272  for(i = 0; i < dim; ++i)
273  if(i != j)
274  sum += (*one)[i] * (*two)[i];
275  sum = (param > 1) ? std::pow(sum+1, param) : sum;
276  break;
277 
278  case mltk::GAUSSIAN: //Gaussiano
279  for(i = 0; i < dim; ++i) {
280  if (i != j) {
281  t = (*one)[i] - (*two)[i];
282  sum += t * t;
283  }
284  }
285  sum = std::exp(-1 * sum * param);
286  break;
287  case mltk::CUSTOM:
288  sum = this->func(*one, *two, param);
289  break;
290  }
291  /*The '+1' here accounts for the bias term "b" in SVM formulation since
292  <w,x> = \sum_i \alpha_i y_i k(x_i,x) + b and b=\sum_i \alpha_i y_i*/
293  return sum;// + 1.0f;
294  }
295 
296  template < typename T >
298  size_t i, j, size = data.size();
299  double sum, sum1;
300  auto points = data.points();
301 
302  sum = sum1 = 0;
303 
304  for(i = 0; i < size; ++i){
305  for(j = 0; j < size; j++){
306  sum1 += points[j]->Alpha() * points[j]->Y() * K[i][j];
307  sum += points[i]->Y() * points[i]->Alpha() * sum1;
308  }
309  }
310 
311  return sqrt(sum);
312  }
313 
314  template < typename T >
315  double Kernel<T>::featureSpaceNorm(std::shared_ptr<Data< T > > data) {
316  size_t i = 0, j = 0, size = data->size();
317  double sum1 = 0.0;
318  double sum = 0.0;
319 
320  for(i = 0; i < size; ++i)
321  {
322  if((*data)[i]->Alpha() > 0)
323  {
324  sum1 = 0.0;
325  for(j = 0; j < size; ++j)
326  {
327  if((*data)[j]->Alpha() > 0)
328  sum1 += (*data)[j]->Y() * (*data)[j]->Alpha() * K[j][i];
329  }
330  sum += (*data)[i]->Alpha() * (*data)[i]->Y() * sum1;
331  }
332  }
333  sum = sqrt(sum);
334 
335  return sum;
336  }
337 
338  template < typename T >
339  Kernel<T>::Kernel(int type, double param){
340  this->type = type;
341  this->param = param;
342  }
343 
344  template < typename T >
345  Kernel<T>::Kernel(mltk::dMatrix kernel_matrix){
346  this->K = std::move(kernel_matrix);
347  }
348 
349  template < typename T >
351  return type;
352  }
353 
354  template < typename T >
356  return param;
357  }
358 
359  template < typename T >
360  void Kernel<T>::setType(int _type){
361  this->type = _type;
362  this->computed = false;
363  }
364 
365  template < typename T >
366  void Kernel<T>::setParam(double _param){
367  this->param = _param;
368  this->computed = false;
369  }
370 
371  template < typename T >
372  void Kernel<T>::setKernelMatrix(mltk::dMatrix _K){
373  this->K = std::move(_K);
374  }
375 
376  template < typename T >
377  mltk::dMatrix Kernel<T>::getKernelMatrix(){
378  return K;
379  }
380 
381  template < typename T >
383  return &K;
384  }
385 }
size_t size() const
Returns the size of the dataset.
Definition: Data.hpp:208
std::vector< std::shared_ptr< Point< T > > > points()
Returns a shared pointer to the vector of Points of the sample.
Definition: Data.hpp:1685
Class for the kernel computations.
Definition: Kernel.hpp:22
void setParam(double param)
setParam Set the kernel parameter used in the kernel computations.
Definition: Kernel.hpp:366
mltk::dMatrix * getKernelMatrixPointer()
getKernelMatrixPointer Returns a reference to the kernel matrix.
Definition: Kernel.hpp:382
mltk::dMatrix getKernelMatrix()
getKernelMatrix Get the kernel matrix.
Definition: Kernel.hpp:377
Kernel(mltk::dMatrix kernel_matrix)
Class constructor.
Definition: Kernel.hpp:345
void setType(int type)
setType Set the kernel type used in the kernel computations.
Definition: Kernel.hpp:360
int getType()
getType Returns the kernel type used in the kernel computations.
Definition: Kernel.hpp:350
double getParam()
getParam Returns the kernel parameter used in the kernel computations.
Definition: Kernel.hpp:355
void setKernelMatrix(mltk::dMatrix K)
setKernelMatrix Set a pre computed kernel matrix.
Definition: Kernel.hpp:372
double functionWithoutDim(std::shared_ptr< Point< T > > one, std::shared_ptr< Point< T > > two, int j, int dim)
function Compute the kernel function between two points without a dimension.
Definition: Kernel.hpp:259
void compute(std::shared_ptr< Data< T > > samples, typename FunctionType< T >::Type f=nullptr)
compute Compute the kernel matrix with the given type and parameter.
Definition: Kernel.hpp:160
double featureSpaceNorm(std::shared_ptr< Data< T > > data)
featureSpaceNorm Computes the norm in the feature space (Dual).
Definition: Kernel.hpp:315
mltk::dMatrix * generateMatrixHwithoutDim(std::shared_ptr< Data< T > > samples, int dim)
compute Compute the H matrix without a dimension, with the computed kernel matrix and given samples.
Definition: Kernel.hpp:196
double norm(Data< T > data)
norm Computes norm in dual variables.
Definition: Kernel.hpp:297
Kernel(int type=0, double param=0)
Class constructor.
Definition: Kernel.hpp:339
mltk::dMatrix * generateMatrixH(std::shared_ptr< Data< T > > samples)
compute Compute the H matrix with the computed kernel matrix and given samples.
Definition: Kernel.hpp:178
Wrapper for the point data.
Definition: Point.hpp:42
Rep const & X() const
Returns the attributes representation of the point (std::vector by default).
Definition: Point.hpp:139
std::size_t size() const
Returns the dimension of the point.
Definition: Point.hpp:133
UFJF-MLTK main namespace for core functionalities.
Definition: classifier/Classifier.hpp:11