1 // Copyright (C) 2007  Davis E. King (davis@dlib.net)
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 #undef DLIB_SVm_KERNEL_ABSTRACT_
4 #ifdef DLIB_SVm_KERNEL_ABSTRACT_
5 
6 #include <cmath>
7 #include <limits>
8 #include <sstream>
9 #include "../matrix/matrix_abstract.h"
10 #include "../algs.h"
11 #include "../serialize.h"
12 
13 namespace dlib
14 {
15 
16 // ----------------------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------------------
18 /*!A                               Kernel_Function_Objects                               */
19 // ----------------------------------------------------------------------------------------
20 // ----------------------------------------------------------------------------------------
21 
22     /*!
23         WHAT IS A KERNEL FUNCTION OBJECT?
24             In the context of the dlib library documentation a kernel function object
25             is an object with an interface with the following properties:
26                 - a public typedef named sample_type
27                 - a public typedef named scalar_type which should be a float, double, or
28                   long double type.
29                 - an overloaded operator() that operates on two items of sample_type
30                   and returns a scalar_type.
31                   (e.g. scalar_type val = kernel_function(sample1,sample2);
32                    would be a valid expression)
33                 - a public typedef named mem_manager_type that is an implementation of
34                   dlib/memory_manager/memory_manager_kernel_abstract.h or
35                   dlib/memory_manager_global/memory_manager_global_kernel_abstract.h or
36                   dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
37                 - an overloaded == operator that tells you if two kernels are
38                   identical or not.
39 
40         THREAD SAFETY
41             For a kernel function to be threadsafe it means that it must be safe to
42             evaluate an expression like val = kernel_function(sample1,sample2)
43             simultaneously from multiple threads, even when the threads operate on the same
44             object instances (i.e. kernel_function, sample1, and sample2).  The most common
45             way to make this safe is to ensure that the kernel function does not mutate any
46             data, either in itself or in its arguments.
47 
48         For examples of kernel functions see the following objects
49         (e.g. the radial_basis_kernel).
50     !*/
51 
52     template <
53         typename T
54         >
55     struct radial_basis_kernel
56     {
57         /*!
58             REQUIREMENTS ON T
59                 T must be a dlib::matrix object
60 
61             WHAT THIS OBJECT REPRESENTS
62                 This object represents a radial basis function kernel
63 
64             THREAD SAFETY
65                 This kernel is threadsafe.
66         !*/
67 
68         typedef typename T::type scalar_type;
69         typedef T sample_type;
70         typedef typename T::mem_manager_type mem_manager_type;
71 
72         const scalar_type gamma;
73 
74         radial_basis_kernel(
75         );
76         /*!
77             ensures
78                 - #gamma == 0.1
79         !*/
80 
81         radial_basis_kernel(
82             const radial_basis_kernel& k
83         );
84         /*!
85             ensures
86                 - #gamma == k.gamma
87         !*/
88 
89         radial_basis_kernel(
90             const scalar_type g
91         );
92         /*!
93             ensures
94                 - #gamma == g
95         !*/
96 
97         scalar_type operator() (
98             const sample_type& a,
99             const sample_type& b
100         ) const;
101         /*!
102             requires
103                 - a.nc() == 1
104                 - b.nc() == 1
105                 - a.nr() == b.nr()
106             ensures
107                 - returns exp(-gamma * ||a-b||^2)
108         !*/
109 
110         radial_basis_kernel& operator= (
111             const radial_basis_kernel& k
112         );
113         /*!
114             ensures
115                 - #gamma = k.gamma
116                 - returns *this
117         !*/
118 
119         bool operator== (
120             const radial_basis_kernel& k
121         ) const;
122         /*!
123             ensures
124                 - if (k and *this are identical) then
125                     - returns true
126                 - else
127                     - returns false
128         !*/
129 
130     };
131 
132     template <
133         typename T
134         >
135     void serialize (
136         const radial_basis_kernel<T>& item,
137         std::ostream& out
138     );
139     /*!
140         provides serialization support for radial_basis_kernel
141     !*/
142 
143     template <
144         typename T
145         >
146     void deserialize (
147         radial_basis_kernel<T>& item,
148         std::istream& in
149     );
150     /*!
151         provides deserialization support for radial_basis_kernel
152     !*/
153 
154 // ----------------------------------------------------------------------------------------
155 
156     template <
157         typename T
158         >
159     struct sigmoid_kernel
160     {
161         /*!
162             REQUIREMENTS ON T
163                 T must be a dlib::matrix object
164 
165             WHAT THIS OBJECT REPRESENTS
166                 This object represents a sigmoid kernel
167 
168             THREAD SAFETY
169                 This kernel is threadsafe.
170         !*/
171 
172         typedef typename T::type scalar_type;
173         typedef T sample_type;
174         typedef typename T::mem_manager_type mem_manager_type;
175 
176         const scalar_type gamma;
177         const scalar_type coef;
178 
179         sigmoid_kernel(
180         );
181         /*!
182             ensures
183                 - #gamma == 0.1
184                 - #coef == -1.0
185         !*/
186 
187         sigmoid_kernel(
188             const sigmoid_kernel& k
189         );
190         /*!
191             ensures
192                 - #gamma == k.gamma
193                 - #coef == k.coef
194         !*/
195 
196         sigmoid_kernel(
197             const scalar_type g,
198             const scalar_type c
199         );
200         /*!
201             ensures
202                 - #gamma == g
203                 - #coef == c
204         !*/
205 
206         scalar_type operator() (
207             const sample_type& a,
208             const sample_type& b
209         ) const;
210         /*!
211             requires
212                 - a.nc() == 1
213                 - b.nc() == 1
214                 - a.nr() == b.nr()
215             ensures
216                 - returns tanh(gamma*trans(a)*b + coef)
217         !*/
218 
219         sigmoid_kernel& operator= (
220             const sigmoid_kernel& k
221         );
222         /*!
223             ensures
224                 - #gamma = k.gamma
225                 - #coef = k.coef
226                 - returns *this
227         !*/
228 
229         bool operator== (
230             const sigmoid_kernel& k
231         ) const;
232         /*!
233             ensures
234                 - if (k and *this are identical) then
235                     - returns true
236                 - else
237                     - returns false
238         !*/
239     };
240 
241     template <
242         typename T
243         >
244     void serialize (
245         const sigmoid_kernel<T>& item,
246         std::ostream& out
247     );
248     /*!
249         provides serialization support for sigmoid_kernel
250     !*/
251 
252     template <
253         typename T
254         >
255     void deserialize (
256         sigmoid_kernel<T>& item,
257         std::istream& in
258     );
259     /*!
260         provides deserialization support for sigmoid_kernel
261     !*/
262 
263 
264 // ----------------------------------------------------------------------------------------
265 
266     template <
267         typename T
268         >
269     struct polynomial_kernel
270     {
271         /*!
272             REQUIREMENTS ON T
273                 T must be a dlib::matrix object
274 
275             WHAT THIS OBJECT REPRESENTS
276                 This object represents a polynomial kernel
277 
278             THREAD SAFETY
279                 This kernel is threadsafe.
280         !*/
281 
282         typedef typename T::type scalar_type;
283         typedef T sample_type;
284         typedef typename T::mem_manager_type mem_manager_type;
285 
286         const scalar_type gamma;
287         const scalar_type coef;
288         const scalar_type degree;
289 
290         polynomial_kernel(
291         );
292         /*!
293             ensures
294                 - #gamma == 1
295                 - #coef == 0
296                 - #degree == 1
297         !*/
298 
299         polynomial_kernel(
300             const polynomial_kernel& k
301         );
302         /*!
303             ensures
304                 - #gamma == k.gamma
305                 - #coef == k.coef
306                 - #degree == k.degree
307         !*/
308 
309         polynomial_kernel(
310             const scalar_type g,
311             const scalar_type c,
312             const scalar_type d
313         );
314         /*!
315             ensures
316                 - #gamma == g
317                 - #coef == c
318                 - #degree == d
319         !*/
320 
321         scalar_type operator() (
322             const sample_type& a,
323             const sample_type& b
324         ) const;
325         /*!
326             requires
327                 - a.nc() == 1
328                 - b.nc() == 1
329                 - a.nr() == b.nr()
330             ensures
331                 - returns pow(gamma*trans(a)*b + coef, degree)
332         !*/
333 
334         polynomial_kernel& operator= (
335             const polynomial_kernel& k
336         );
337         /*!
338             ensures
339                 - #gamma = k.gamma
340                 - #coef = k.coef
341                 - #degree = k.degree
342                 - returns *this
343         !*/
344 
345         bool operator== (
346             const polynomial_kernel& k
347         ) const;
348         /*!
349             ensures
350                 - if (k and *this are identical) then
351                     - returns true
352                 - else
353                     - returns false
354         !*/
355     };
356 
357     template <
358         typename T
359         >
360     void serialize (
361         const polynomial_kernel<T>& item,
362         std::ostream& out
363     );
364     /*!
365         provides serialization support for polynomial_kernel
366     !*/
367 
368     template <
369         typename T
370         >
371     void deserialize (
372         polynomial_kernel<T>& item,
373         std::istream& in
374     );
375     /*!
376         provides deserialization support for polynomial_kernel
377     !*/
378 
379 // ----------------------------------------------------------------------------------------
380 
381     template <
382         typename T
383         >
384     struct linear_kernel
385     {
386         /*!
387             REQUIREMENTS ON T
388                 T must be a dlib::matrix object
389 
390             WHAT THIS OBJECT REPRESENTS
391                 This object represents a linear function kernel
392 
393             THREAD SAFETY
394                 This kernel is threadsafe.
395         !*/
396 
397         typedef typename T::type scalar_type;
398         typedef T sample_type;
399         typedef typename T::mem_manager_type mem_manager_type;
400 
401         scalar_type operator() (
402             const sample_type& a,
403             const sample_type& b
404         ) const;
405         /*!
406             requires
407                 - a.nc() == 1
408                 - b.nc() == 1
409                 - a.nr() == b.nr()
410             ensures
411                 - returns trans(a)*b
412         !*/
413 
414         bool operator== (
415             const linear_kernel& k
416         ) const;
417         /*!
418             ensures
419                 - returns true
420         !*/
421     };
422 
423     template <
424         typename T
425         >
426     void serialize (
427         const linear_kernel<T>& item,
428         std::ostream& out
429     );
430     /*!
431         provides serialization support for linear_kernel
432     !*/
433 
434     template <
435         typename T
436         >
437     void deserialize (
438         linear_kernel<T>& item,
439         std::istream& in
440     );
441     /*!
442         provides deserialization support for linear_kernel
443     !*/
444 
445 // ----------------------------------------------------------------------------------------
446 
447     template <
448         typename T
449         >
450     struct histogram_intersection_kernel
451     {
452         /*!
453             REQUIREMENTS ON T
454                 T must be a dlib::matrix object
455 
456             WHAT THIS OBJECT REPRESENTS
457                 This object represents a histogram intersection kernel kernel
458 
459             THREAD SAFETY
460                 This kernel is threadsafe.
461         !*/
462 
463         typedef typename T::type scalar_type;
464         typedef T sample_type;
465         typedef typename T::mem_manager_type mem_manager_type;
466 
467         scalar_type operator() (
468             const sample_type& a,
469             const sample_type& b
470         ) const;
471         /*!
472             requires
473                 - is_vector(a)
474                 - is_vector(b)
475                 - a.size() == b.size()
476                 - min(a) >= 0
477                 - min(b) >= 0
478             ensures
479                 - returns sum over all i: std::min(a(i), b(i))
480         !*/
481 
482         bool operator== (
483             const histogram_intersection_kernel& k
484         ) const;
485         /*!
486             ensures
487                 - returns true
488         !*/
489     };
490 
491     template <
492         typename T
493         >
494     void serialize (
495         const histogram_intersection_kernel<T>& item,
496         std::ostream& out
497     );
498     /*!
499         provides serialization support for histogram_intersection_kernel
500     !*/
501 
502     template <
503         typename T
504         >
505     void deserialize (
506         histogram_intersection_kernel<T>& item,
507         std::istream& in
508     );
509     /*!
510         provides deserialization support for histogram_intersection_kernel
511     !*/
512 
513 // ----------------------------------------------------------------------------------------
514 
515     template <
516         typename T
517         >
518     struct offset_kernel
519     {
520         /*!
521             REQUIREMENTS ON T
522                 T must be a kernel object (e.g. radial_basis_kernel, polynomial_kernel, etc.)
523 
524             WHAT THIS OBJECT REPRESENTS
525                 This object represents a kernel with a fixed value offset
526                 added to it.
527 
528             THREAD SAFETY
529                 This kernel is threadsafe.
530         !*/
531 
532         typedef typename T::scalar_type scalar_type;
533         typedef typename T::sample_type sample_type;
534         typedef typename T::mem_manager_type mem_manager_type;
535 
536         const T kernel;
537         const scalar_type offset;
538 
539         offset_kernel(
540         );
541         /*!
542             ensures
543                 - #offset == 0.01
544         !*/
545 
546         offset_kernel(
547             const offset_kernel& k
548         );
549         /*!
550             ensures
551                 - #offset == k.offset
552                 - #kernel == k.kernel
553         !*/
554 
555         offset_kernel(
556             const T& k,
557             const scalar_type& off
558         );
559         /*!
560             ensures
561                 - #kernel == k
562                 - #offset == off
563         !*/
564 
565         scalar_type operator() (
566             const sample_type& a,
567             const sample_type& b
568         ) const;
569         /*!
570             ensures
571                 - returns kernel(a,b) + offset
572         !*/
573 
574         offset_kernel& operator= (
575             const offset_kernel& k
576         );
577         /*!
578             ensures
579                 - #offset == k.offset
580                 - #kernel == k.kernel
581         !*/
582 
583         bool operator== (
584             const offset_kernel& k
585         ) const;
586         /*!
587             ensures
588                 - if (k and *this are identical) then
589                     - returns true
590                 - else
591                     - returns false
592         !*/
593     };
594 
595     template <
596         typename T
597         >
598     void serialize (
599         const offset_kernel<T>& item,
600         std::ostream& out
601     );
602     /*!
603         provides serialization support for offset_kernel
604     !*/
605 
606     template <
607         typename T
608         >
609     void deserialize (
610         offset_kernel<T>& item,
611         std::istream& in
612     );
613     /*!
614         provides deserialization support for offset_kernel
615     !*/
616 
617 // ----------------------------------------------------------------------------------------
618 // ----------------------------------------------------------------------------------------
619 // ----------------------------------------------------------------------------------------
620 
621     template <
622         typename kernel_type
623         >
624     struct kernel_derivative
625     {
626         /*!
627             REQUIREMENTS ON kernel_type
628                 kernel_type must be one of the following kernel types:
629                     - radial_basis_kernel
630                     - polynomial_kernel
631                     - sigmoid_kernel
632                     - linear_kernel
633                     - offset_kernel
634 
635             WHAT THIS OBJECT REPRESENTS
636                 This is a function object that computes the derivative of a kernel
637                 function object.
638 
639             THREAD SAFETY
640                 It is always safe to use distinct instances of this object in different
641                 threads.  However, when a single instance is shared between threads then
642                 the following rules apply:
643                     Instances of this object are allowed to have a mutable cache which is
644                     used by const member functions.  Therefore, it is not safe to use one
645                     instance of this object from multiple threads (unless protected by a
646                     mutex).
647         !*/
648 
649         typedef typename kernel_type::scalar_type scalar_type;
650         typedef typename kernel_type::sample_type sample_type;
651         typedef typename kernel_type::mem_manager_type mem_manager_type;
652 
653         kernel_derivative(
654             const kernel_type& k_
655         );
656         /*!
657             ensures
658                 - this object will return derivatives of the kernel object k_
659                 - #k == k_
660         !*/
661 
662         const sample_type operator() (
663             const sample_type& x,
664             const sample_type& y
665         ) const;
666         /*!
667             ensures
668                 - returns the derivative of k with respect to y.
669         !*/
670 
671         const kernel_type& k;
672     };
673 
674 // ----------------------------------------------------------------------------------------
675 
676 }
677 
678 #endif // DLIB_SVm_KERNEL_ABSTRACT_
679 
680 
681 
682