summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/svm/kernel_matrix.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/svm/kernel_matrix.h')
-rw-r--r--ml/dlib/dlib/svm/kernel_matrix.h268
1 files changed, 268 insertions, 0 deletions
diff --git a/ml/dlib/dlib/svm/kernel_matrix.h b/ml/dlib/dlib/svm/kernel_matrix.h
new file mode 100644
index 000000000..f6e1e0b90
--- /dev/null
+++ b/ml/dlib/dlib/svm/kernel_matrix.h
@@ -0,0 +1,268 @@
+// Copyright (C) 2009 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#ifndef DLIB_SVm_KERNEL_MATRIX_
+#define DLIB_SVm_KERNEL_MATRIX_
+
+#include <vector>
+#include "kernel_matrix_abstract.h"
+#include "../matrix.h"
+#include "../algs.h"
+
+namespace dlib
+{
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ namespace impl
+ {
+ template <typename kernel_type, typename T>
+ inline const typename T::type& access ( const matrix_exp<T>& m, long i)
+ {
+ return m(i);
+ }
+
+ // bind to anything that looks like an array and isn't a matrix
+ template <typename kernel_type, typename T>
+ inline const typename disable_if<is_matrix<T>,typename T::type>::type& access ( const T& m, long i)
+ {
+ return m[i];
+ }
+
+ // Only use this function if T isn't a std::pair because in that case the entire vector is
+ // probably itself a sparse sample.
+ template <typename kernel_type, typename T, typename alloc>
+ inline typename disable_if<is_pair<T>,const T&>::type access ( const std::vector<T,alloc>& m, long i)
+ {
+ return m[i];
+ }
+
+ // Only use this function if T isn't a std::pair because in that case the entire vector is
+ // probably a sparse sample.
+ template <typename kernel_type, typename T, typename alloc>
+ inline typename disable_if<is_pair<T>,const T&>::type access ( const std_vector_c<T,alloc>& m, long i)
+ {
+ return m[i];
+ }
+
+ template <typename kernel_type>
+ inline const typename kernel_type::sample_type& access (
+ const typename kernel_type::sample_type& samp,
+ long
+ )
+ {
+ return samp;
+ }
+
+ // --------------------------------------------
+
+ template <typename kernel_type, typename T>
+ inline typename disable_if<is_same_type<T,typename kernel_type::sample_type>,unsigned long>::type
+ size ( const T& m)
+ {
+ return m.size();
+ }
+
+ template <typename kernel_type>
+ inline size_t size (
+ const typename kernel_type::sample_type&
+ )
+ {
+ return 1;
+ }
+
+ // --------------------------------------------
+
+ template <typename T>
+ typename disable_if<is_matrix<T> >::type assert_is_vector(const T&)
+ {}
+
+ template <typename T>
+ // This funny #ifdef thing is here because gcc sometimes gives a warning
+ // about v being unused otherwise.
+#ifdef ENABLE_ASSERTS
+ void assert_is_vector(const matrix_exp<T>& v)
+#else
+ void assert_is_vector(const matrix_exp<T>& )
+#endif
+ {
+ // make sure requires clause is not broken
+ DLIB_ASSERT(is_vector(v) == true,
+ "\tconst matrix_exp kernel_matrix()"
+ << "\n\t You have to supply this function with row or column vectors"
+ << "\n\t v.nr(): " << v.nr()
+ << "\n\t v.nc(): " << v.nc()
+ );
+ }
+
+ }
+
+ template <typename K, typename vect_type1, typename vect_type2>
+ struct op_kern_mat
+ {
+ op_kern_mat(
+ const K& kern_,
+ const vect_type1& vect1_,
+ const vect_type2& vect2_
+ ) :
+ kern(kern_),
+ vect1(vect1_),
+ vect2(vect2_)
+ {
+ // make sure the requires clauses get checked eventually
+ impl::assert_is_vector(vect1);
+ impl::assert_is_vector(vect2);
+ }
+
+ const K& kern;
+ const vect_type1& vect1;
+ const vect_type2& vect2;
+
+ typedef typename K::scalar_type type;
+
+ const static long cost = 100;
+ const static long NR = (is_same_type<vect_type1,typename K::sample_type>::value) ? 1 : 0;
+ const static long NC = (is_same_type<vect_type2,typename K::sample_type>::value) ? 1 : 0;
+
+ typedef const type const_ret_type;
+ typedef typename K::mem_manager_type mem_manager_type;
+ typedef row_major_layout layout_type;
+
+ const_ret_type apply (long r, long c ) const
+ {
+ return kern(impl::access<K>(vect1,r), impl::access<K>(vect2,c));
+ }
+
+ long nr () const { return impl::size<K>(vect1); }
+ long nc () const { return impl::size<K>(vect2); }
+
+ template <typename U> bool aliases ( const matrix_exp<U>& item ) const { return alias_helper(item.ref()); }
+ template <typename U> bool destructively_aliases ( const matrix_exp<U>& item ) const { return alias_helper(item.ref()); }
+
+ template <typename U> bool alias_helper ( const U& ) const { return false; }
+
+ typedef typename K::sample_type samp_type;
+
+ // Say we destructively alias if one of the vect* objects is actually item.
+ bool alias_helper (const samp_type& item ) const { return are_same(item, vect1) || are_same(item, vect2); }
+ template <typename U> bool are_same (const samp_type& , const U& ) const { return false; }
+ bool are_same (const samp_type& a, const samp_type& b) const { return (&a == &b); }
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename K,
+ typename V1,
+ typename V2
+ >
+ const matrix_op<op_kern_mat<K,V1,V2> > kernel_matrix (
+ const K& kern,
+ const V1& v1,
+ const V2& v2
+ )
+ {
+ typedef op_kern_mat<K,V1,V2> op;
+ return matrix_op<op>(op(kern,v1,v2));
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ /*
+ It is possible to implement the kernel_matrix() operator with just one operator
+ class but treating the version that takes only a single vector separately
+ leads to more efficient output by gcc in certain instances.
+ */
+ template <typename K, typename vect_type1>
+ struct op_kern_mat_single
+ {
+ op_kern_mat_single(
+ const K& kern_,
+ const vect_type1& vect1_
+ ) :
+ kern(kern_),
+ vect1(vect1_)
+ {
+ // make sure the requires clauses get checked eventually
+ impl::assert_is_vector(vect1);
+ }
+
+ const K& kern;
+ const vect_type1& vect1;
+
+ typedef typename K::scalar_type type;
+
+ const static long cost = 100;
+ const static long NR = (is_same_type<vect_type1,typename K::sample_type>::value) ? 1 : 0;
+ const static long NC = (is_same_type<vect_type1,typename K::sample_type>::value) ? 1 : 0;
+
+ typedef const type const_ret_type;
+ typedef typename K::mem_manager_type mem_manager_type;
+ typedef row_major_layout layout_type;
+
+ const_ret_type apply (long r, long c ) const
+ {
+ return kern(impl::access<K>(vect1,r), impl::access<K>(vect1,c));
+ }
+
+ long nr () const { return impl::size<K>(vect1); }
+ long nc () const { return impl::size<K>(vect1); }
+
+ template <typename U> bool aliases ( const matrix_exp<U>& item ) const { return alias_helper(item.ref()); }
+ template <typename U> bool destructively_aliases ( const matrix_exp<U>& item ) const { return alias_helper(item.ref()); }
+
+ template <typename U> bool alias_helper ( const U& ) const { return false; }
+
+ typedef typename K::sample_type samp_type;
+
+ // Say we destructively alias if vect1 is actually item.
+ bool alias_helper (const samp_type& item ) const { return are_same(item, vect1); }
+ template <typename U> bool are_same (const samp_type& , const U& ) const { return false; }
+ bool are_same (const samp_type& a, const samp_type& b) const { return (&a == &b); }
+ };
+
+ template <
+ typename K,
+ typename V
+ >
+ const matrix_op<op_kern_mat_single<K,V> > kernel_matrix (
+ const K& kern,
+ const V& v
+ )
+ {
+ typedef op_kern_mat_single<K,V> op;
+ return matrix_op<op>(op(kern,v));
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename matrix_dest_type,
+ typename K,
+ typename V
+ >
+ inline void matrix_assign (
+ matrix_dest_type& dest,
+ const matrix_exp<matrix_op<op_kern_mat_single<K,V> > >& src
+ )
+ /*!
+ Overload matrix assignment so that when a kernel_matrix expression
+ gets assigned it only evaluates half the kernel matrix (since it is symmetric)
+ !*/
+ {
+ for (long r = 0; r < src.nr(); ++r)
+ {
+ for (long c = r; c < src.nc(); ++c)
+ {
+ dest(r,c) = dest(c,r) = src(r,c);
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+}
+
+#endif // DLIB_SVm_KERNEL_MATRIX_
+