iRoCS Toolbox  1.1.0
Kernel_MATRIX.hh
Go to the documentation of this file.
1 /**************************************************************************
2  *
3  * Copyright (C) 2004-2015 Olaf Ronneberger, Florian Pigorsch, Jörg Mechnich,
4  * Thorsten Falk
5  *
6  * Image Analysis Lab, University of Freiburg, Germany
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  **************************************************************************/
23 
24 /**************************************************************************
25 ** Title: kernel caching complete kernel matrix
26 ** $RCSfile$
27 ** $Revision: 5096 $$Name$
28 ** $Date: 2013-12-05 16:15:41 +0100 (Thu, 05 Dec 2013) $
29 ** Copyright: GPL $Author: tschmidt $
30 ** Description:
31 **
32 **
33 **
34 **-------------------------------------------------------------------------
35 **
36 ** $Log$
37 ** Revision 1.7 2007/01/10 09:50:26 fehr
38 ** cache size bug sixed
39 **
40 ** Revision 1.6 2005/07/19 13:03:59 haasdonk
41 ** removed redundant cout-messages, erroneous filename and added a new function
42 ** for computing a training-kernel matrix in BasicSVMAdapter*
43 **
44 ** Revision 1.5 2005/06/06 21:23:31 haasdonk
45 ** added updateCache() with two FV-lists, required for classification with precomputed kernel-matrices
46 **
47 ** Revision 1.4 2005/03/29 17:55:35 ronneber
48 ** - renamed freeCache () to clearCache()
49 ** - clearCache() now also calls clearCache() of underlying Kernel. This
50 ** should fix problems with training/classification using Kernel_MATRIX
51 ** together with Kernel_SCALE
52 **
53 ** Revision 1.3 2004/09/08 14:29:13 ronneber
54 ** - adapted to new ParamInfo class
55 **
56 ** Revision 1.2 2004/09/03 07:10:32 ronneber
57 ** - updateCache now takes an Accessor
58 ** - updateCache now calls updateCache of underlying kernel
59 **
60 ** Revision 1.1 2004/08/26 08:36:59 ronneber
61 ** initital import
62 **
63 **
64 **
65 **************************************************************************/
66 
67 #ifndef KERNEL_MATRIX_HH
68 #define KERNEL_MATRIX_HH
69 
70 #ifdef HAVE_CONFIG_H
71 #include <config.hh>
72 #endif
73 
74 // std includes
75 #include <map>
76 #include <set>
77 #include <string>
78 
79 // libsvmtl includes
80 #include "svm_defines.hh"
81 #include "SVMError.hh"
82 #include "ProgressReporter.hh"
83 
84 // requirements of template parameters
89 
90 namespace svt
91 {
92  template< typename KERNEL>
94  {
97 
98  public:
100  : _data(0),
101  _rowStarts(0),
102  _width(0),
103  _cacheIsUpToDate( false)
104  {}
105 
106  Kernel_MATRIX( const KERNEL& kernel)
107  : _kernel(kernel),
108  _data(0),
109  _rowStarts(0),
110  _width(0),
111  _cacheIsUpToDate( false)
112  {}
113 
114 /*-------------------------------------------------------------------------
115  * if you really want to copy Kernel_MATRIX's, which might be very
116  * expensive, you can define ALLOW_KERNEL_MATRIX_COPY
117  *-------------------------------------------------------------------------*/
118 #ifdef ALLOW_KERNEL_MATRIX_COPY
119  public:
120 #else
121  private:
122 #endif
123 
125  : _data(0),
126  _rowStarts(0),
127  _width(0)
128  {
129  operator=( orig);
130  }
131 
132  void operator=( const Kernel_MATRIX<KERNEL>& orig)
133  {
134  _cacheIsUpToDate = orig._cacheIsUpToDate;
135  resizeCache( orig._width);
136  if( orig._width != 0)
137  {
138  unsigned int size = _width*_width;
139  std::copy( orig._data, orig._data + size, _data);
140  }
141 
142 
143  }
144 
145  public:
146 
147 
149  {
150  clearCache();
151  };
152 
153  void resizeCache( long width) const
154  {
155  if( width == _width) return;
156 
157  clearCache();
158 
159  _width = width;
160  if( _width != 0)
161  {
162  _data = new double[width*width];
163  _rowStarts = new double*[width];
164 
165  for(long i = 0; i < width; ++i)
166  {
167  _rowStarts[i] = _data + i*width;
168  }
169  }
170  else
171  {
172  _data = 0;
173  _rowStarts = 0;
174  }
175 
176  }
177 
178  void clearCache() const
179  {
180  if( _data != 0)
181  {
182  delete[] _data;
183  _data = 0;
184  }
185 
186  if( _rowStarts != 0)
187  {
188  delete[] _rowStarts;
189  _rowStarts = 0;
190  }
191  _width = 0;
192  _cacheIsUpToDate = false;
193 
194  /*--------------------------------------------------------------
195  * clear cache of underlying kernel (e.g. if it is a
196  * Kernel_SCALE)
197  *--------------------------------------------------------------*/
198  _kernel.clearCache();
199  }
200 
201 
202 
203  template< typename ForwardIter, typename Accessor>
204  void updateCache( const ForwardIter& fvBegin,
205  const ForwardIter& fvEnd,
206  Accessor accessor,
207  ProgressReporter* pr = 0) const
208  {
209  /*--------------------------------------------------------------
210  * update cache of underlying kernel (e.g. if it is a
211  * Kernel_SCALE )
212  *--------------------------------------------------------------*/
213  _kernel.updateCache( fvBegin, fvEnd, accessor, pr);
214 
215 
216  /*---------------------------------------------------------------
217  * search max uid
218  *---------------------------------------------------------------*/
219  unsigned int maxUID = 0;
220 
221  for( ForwardIter p = fvBegin; p != fvEnd; ++p)
222  {
223  if( accessor(p).uniqueID() > maxUID)
224  {
225  maxUID = accessor(p).uniqueID();
226  }
227  }
229 
230  /*--------------------------------------------------------------
231  * fill matrix with kernel results
232  *--------------------------------------------------------------*/
233  resizeCache( maxUID+1);
234  size_t nFeatureVectors = fvEnd - fvBegin;
235  ForwardIter p = fvBegin;
236  int nKernelEvaluations =
237  static_cast<int>(nFeatureVectors * (nFeatureVectors + 1) / 2);
238  int reportProgressEveryNthEval = nKernelEvaluations / 100;
239  if( reportProgressEveryNthEval == 0) reportProgressEveryNthEval = 1;
240  int nKernelEvaluationsFinished = 0;
241  int silentProgressCounter = reportProgressEveryNthEval;
242 
243  for( unsigned int i = 0; i < nFeatureVectors; ++i, ++p)
244  {
245  unsigned int row = accessor(p).uniqueID();
246  ForwardIter q = fvBegin + i;
247  for( unsigned int j = i; j < nFeatureVectors; ++j, ++q)
248  {
249  unsigned int col = accessor(q).uniqueID();
250  double val = _kernel.k_function( accessor(p), accessor(q));
251  _rowStarts[row][col] = val;
252  _rowStarts[col][row] = val;
253  ++nKernelEvaluationsFinished;
254  --silentProgressCounter;
255  if( silentProgressCounter <= 0)
256  {
257  silentProgressCounter = reportProgressEveryNthEval;
258  if( pr != 0)
259  {
260  pr->reportProgress(
262  "calculating full kernel matrix",
263  static_cast<float>(nKernelEvaluationsFinished) /
264  static_cast<float>(nKernelEvaluations), "");
265  }
266  }
267 
268  }
269  }
270  if( pr != 0)
271  {
272  pr->reportProgress( TASK_LEVEL_CROSS_VAL,
273  "full kernel matrix calculated", 1.0,
274  "");
275  }
276  _cacheIsUpToDate = true;
277  }
278 
279 
280  // new updateCache-Syntax:
281  template< typename ForwardIter1, typename Accessor1,
282  typename ForwardIter2, typename Accessor2 >
283  void updateCache( const ForwardIter1&,
284  const ForwardIter1&,
285  Accessor1,
286  const ForwardIter2&,
287  const ForwardIter2&,
288  Accessor2,
289  ProgressReporter* = 0) const
290  {
291  // nothing to be done or can be implemented later
292  }
293 
294  template< typename FV>
295  double k_function( const FV& x, const FV& y) const
296  {
298  if( _cacheIsUpToDate == false)
299  {
300  return _kernel.k_function( x, y);
301  }
302 
303  long row = static_cast<long>(x.uniqueID());
304  long col = static_cast<long>(y.uniqueID());
305 
306  SVM_ASSERT( row < _width);
307  SVM_ASSERT( col < _width);
308 
309  return _rowStarts[row][col];
310  }
311 
312  template<typename STDATA>
313  void loadParameters( STDATA& stData)
314  {
316  _kernel.loadParameters( stData);
317  }
318 
319  template<typename STDATA>
320  void saveParameters( STDATA& stData) const
321  {
323  _kernel.saveParameters( stData);
324  stData.setValue( "kernel_type", name());
325  }
326 
327  static std::string name()
328  {
329  return std::string( "kmatrix_") + KERNEL::name();
330  }
331 
332  static std::string description()
333  {
334  return std::string( "cached kernel matrix for ") + KERNEL::description();
335  }
336 
337  /*======================================================================*/
346  /*======================================================================*/
347  static void getParamInfos( std::vector<ParamInfo>& p)
348  {
349  KERNEL::getParamInfos( p);
350  }
351 
352  private:
353  KERNEL _kernel;
354  mutable double* _data;
355  mutable double** _rowStarts;
356  mutable long _width;
357  mutable bool _cacheIsUpToDate;
358 
359 
360 
361  };
362 
363 }
364 
365 #endif
static std::string description()
double k_function(const FV &x, const FV &y) const
#define CHECK_MEMBER_TEMPLATE(c)
void resizeCache(long width) const
#define SVM_ASSERT(condition)
Definition: SVMError.hh:176
const unsigned int MAX_BELIEVABLE_UNIQUE_ID
Definition: svm_defines.hh:63
#define CHECK_CLASS_TEMPLATE1(c)
Kernel_MATRIX(const KERNEL &kernel)
void saveParameters(STDATA &stData) const
#define CHECK_CLASS_TEMPLATE2(c)
Ensure that TESTCLASS provides a loadParameters() and saveParamters() method.
void clearCache() const
void loadParameters(STDATA &stData)
void updateCache(const ForwardIter &fvBegin, const ForwardIter &fvEnd, Accessor accessor, ProgressReporter *pr=0) const
static void getParamInfos(std::vector< ParamInfo > &p)
get information about the parameters, that are used in loadParameters() and saveParameters().
const int TASK_LEVEL_CROSS_VAL
static std::string name()
void updateCache(const ForwardIter1 &, const ForwardIter1 &, Accessor1, const ForwardIter2 &, const ForwardIter2 &, Accessor2, ProgressReporter *=0) const