1 // Copyright (C) 2013 Davis E. King (davis@dlib.net)
2 // License: Boost Software License See LICENSE.txt for the full license.
3
4 #include "opaque_types.h"
5 #include <dlib/python.h>
6 #include "testing_results.h"
7 #include <dlib/svm.h>
8 #include <chrono>
9
10 using namespace dlib;
11 using namespace std;
12
13 namespace py = pybind11;
14
15 typedef matrix<double,0,1> sample_type;
16 typedef std::vector<std::pair<unsigned long,double> > sparse_vect;
17
np_to_cpp(const numpy_image<double> & x_,std::vector<matrix<double,0,1>> & samples)18 void np_to_cpp (
19 const numpy_image<double>& x_,
20 std::vector<matrix<double,0,1>>& samples
21 )
22 {
23 auto x = make_image_view(x_);
24 DLIB_CASSERT(x.nc() > 0);
25 DLIB_CASSERT(x.nr() > 0);
26 samples.resize(x.nr());
27 for (long r = 0; r < x.nr(); ++r)
28 {
29 samples[r].set_size(x.nc());
30 for (long c = 0; c < x.nc(); ++c)
31 {
32 samples[r](c) = x[r][c];
33 }
34 }
35 }
36
np_to_cpp(const numpy_image<double> & x_,const py::array_t<double> & y,std::vector<matrix<double,0,1>> & samples,std::vector<double> & labels)37 void np_to_cpp (
38 const numpy_image<double>& x_,
39 const py::array_t<double>& y,
40 std::vector<matrix<double,0,1>>& samples,
41 std::vector<double>& labels
42 )
43 {
44 DLIB_CASSERT(y.ndim() == 1 && y.size() > 0);
45 labels.assign(y.data(), y.data()+y.size());
46 auto x = make_image_view(x_);
47 DLIB_CASSERT(x.nr() == y.size(), "The x matrix must have as many rows as y has elements.");
48 DLIB_CASSERT(x.nc() > 0);
49 samples.resize(x.nr());
50 for (long r = 0; r < x.nr(); ++r)
51 {
52 samples[r].set_size(x.nc());
53 for (long c = 0; c < x.nc(); ++c)
54 {
55 samples[r](c) = x[r][c];
56 }
57 }
58 }
59
60
61 template <typename decision_function>
predict(const decision_function & df,const typename decision_function::kernel_type::sample_type & samp)62 double predict (
63 const decision_function& df,
64 const typename decision_function::kernel_type::sample_type& samp
65 )
66 {
67 typedef typename decision_function::kernel_type::sample_type T;
68 if (df.basis_vectors.size() == 0)
69 {
70 return 0;
71 }
72 else if (is_matrix<T>::value && df.basis_vectors(0).size() != samp.size())
73 {
74 std::ostringstream sout;
75 sout << "Input vector should have " << df.basis_vectors(0).size()
76 << " dimensions, not " << samp.size() << ".";
77 PyErr_SetString( PyExc_ValueError, sout.str().c_str() );
78 throw py::error_already_set();
79 }
80 return df(samp);
81 }
82
np_to_mat(const py::array_t<double> & samp)83 inline matrix<double,0,1> np_to_mat(
84 const py::array_t<double>& samp
85 )
86 {
87 matrix<double,0,1> temp(samp.size());
88
89 const auto data = samp.data();
90 for (long i = 0; i < temp.size(); ++i)
91 temp(i) = data[i];
92 return temp;
93 }
94
95 template <typename decision_function>
normalized_predict(const normalized_function<decision_function> & df,const typename decision_function::kernel_type::sample_type & samp)96 double normalized_predict (
97 const normalized_function<decision_function>& df,
98 const typename decision_function::kernel_type::sample_type& samp
99 )
100 {
101 typedef typename decision_function::kernel_type::sample_type T;
102 if (df.function.basis_vectors.size() == 0)
103 {
104 return 0;
105 }
106 else if (is_matrix<T>::value && df.function.basis_vectors(0).size() != samp.size())
107 {
108 std::ostringstream sout;
109 sout << "Input vector should have " << df.function.basis_vectors(0).size()
110 << " dimensions, not " << samp.size() << ".";
111 PyErr_SetString( PyExc_ValueError, sout.str().c_str() );
112 throw py::error_already_set();
113 }
114 return df(samp);
115 }
116
117 template <typename decision_function>
normalized_predict_vec(const normalized_function<decision_function> & df,const std::vector<typename decision_function::kernel_type::sample_type> & samps)118 std::vector<double> normalized_predict_vec (
119 const normalized_function<decision_function>& df,
120 const std::vector<typename decision_function::kernel_type::sample_type>& samps
121 )
122 {
123 std::vector<double> out;
124 out.reserve(samps.size());
125 for (const auto& x : samps)
126 out.push_back(normalized_predict(df,x));
127 return out;
128 }
129
130 template <typename decision_function>
normalized_predict_np_vec(const normalized_function<decision_function> & df,const numpy_image<double> & samps_)131 py::array_t<double> normalized_predict_np_vec (
132 const normalized_function<decision_function>& df,
133 const numpy_image<double>& samps_
134 )
135 {
136 auto samps = make_image_view(samps_);
137
138 if (df.function.basis_vectors(0).size() != samps.nc())
139 {
140 std::ostringstream sout;
141 sout << "Input vector should have " << df.function.basis_vectors(0).size()
142 << " dimensions, not " << samps.nc() << ".";
143 PyErr_SetString( PyExc_ValueError, sout.str().c_str() );
144 throw py::error_already_set();
145 }
146
147 py::array_t<double, py::array::c_style> out((size_t)samps.nr());
148 matrix<double,0,1> temp(samps.nc());
149 auto data = out.mutable_data();
150 for (long r = 0; r < samps.nr(); ++r)
151 {
152 for (long c = 0; c < samps.nc(); ++c)
153 temp(c) = samps[r][c];
154 *data++ = df(temp);
155 }
156 return out;
157 }
158
159 template <typename decision_function>
normalized_predict_np(const normalized_function<decision_function> & df,const py::array_t<double> & samp)160 double normalized_predict_np (
161 const normalized_function<decision_function>& df,
162 const py::array_t<double>& samp
163 )
164 {
165 typedef typename decision_function::kernel_type::sample_type T;
166 if (df.function.basis_vectors.size() == 0)
167 {
168 return 0;
169 }
170 else if (is_matrix<T>::value && df.function.basis_vectors(0).size() != samp.size())
171 {
172 std::ostringstream sout;
173 sout << "Input vector should have " << df.function.basis_vectors(0).size()
174 << " dimensions, not " << samp.size() << ".";
175 PyErr_SetString( PyExc_ValueError, sout.str().c_str() );
176 throw py::error_already_set();
177 }
178 return df(np_to_mat(samp));
179 }
180
181 template <typename kernel_type>
add_df(py::module & m,const std::string name)182 void add_df (
183 py::module& m,
184 const std::string name
185 )
186 {
187 typedef decision_function<kernel_type> df_type;
188 py::class_<df_type>(m, name.c_str())
189 .def("__call__", &predict<df_type>)
190 .def_property_readonly("alpha", [](const df_type& df) {return df.alpha;})
191 .def_property_readonly("b", [](const df_type& df) {return df.b;})
192 .def_property_readonly("kernel_function", [](const df_type& df) {return df.kernel_function;})
193 .def_property_readonly("basis_vectors", [](const df_type& df) {
194 std::vector<matrix<double,0,1>> temp;
195 for (long i = 0; i < df.basis_vectors.size(); ++i)
196 temp.push_back(sparse_to_dense(df.basis_vectors(i)));
197 return temp;
198 })
199 .def(py::pickle(&getstate<df_type>, &setstate<df_type>));
200 }
201
202 template <typename kernel_type>
add_normalized_df(py::module & m,const std::string name)203 void add_normalized_df (
204 py::module& m,
205 const std::string name
206 )
207 {
208 using df_type = normalized_function<decision_function<kernel_type>>;
209
210 py::class_<df_type>(m, name.c_str())
211 .def("__call__", &normalized_predict<decision_function<kernel_type>>)
212 .def("__call__", &normalized_predict_np<decision_function<kernel_type>>)
213 .def("batch_predict", &normalized_predict_vec<decision_function<kernel_type>>)
214 .def("batch_predict", &normalized_predict_np_vec<decision_function<kernel_type>>)
215 .def_property_readonly("alpha", [](const df_type& df) {return df.function.alpha;})
216 .def_property_readonly("b", [](const df_type& df) {return df.function.b;})
217 .def_property_readonly("kernel_function", [](const df_type& df) {return df.function.kernel_function;})
218 .def_property_readonly("basis_vectors", [](const df_type& df) {
219 std::vector<matrix<double,0,1>> temp;
220 for (long i = 0; i < df.function.basis_vectors.size(); ++i)
221 temp.push_back(sparse_to_dense(df.function.basis_vectors(i)));
222 return temp;
223 })
224 .def_property_readonly("means", [](const df_type& df) {return df.normalizer.means();},
225 "Input vectors are normalized by the equation, (x-means)*invstd_devs, before being passed to the underlying RBF function.")
226 .def_property_readonly("invstd_devs", [](const df_type& df) {return df.normalizer.std_devs();},
227 "Input vectors are normalized by the equation, (x-means)*invstd_devs, before being passed to the underlying RBF function.")
228 .def(py::pickle(&getstate<df_type>, &setstate<df_type>));
229 }
230
231 template <typename df_type>
get_weights(const df_type & df)232 typename df_type::sample_type get_weights(
233 const df_type& df
234 )
235 {
236 if (df.basis_vectors.size() == 0)
237 {
238 PyErr_SetString( PyExc_ValueError, "Decision function is empty." );
239 throw py::error_already_set();
240 }
241 df_type temp = simplify_linear_decision_function(df);
242 return temp.basis_vectors(0);
243 }
244
245 template <typename df_type>
get_bias(const df_type & df)246 typename df_type::scalar_type get_bias(
247 const df_type& df
248 )
249 {
250 if (df.basis_vectors.size() == 0)
251 {
252 PyErr_SetString( PyExc_ValueError, "Decision function is empty." );
253 throw py::error_already_set();
254 }
255 return df.b;
256 }
257
258 template <typename df_type>
set_bias(df_type & df,double b)259 void set_bias(
260 df_type& df,
261 double b
262 )
263 {
264 if (df.basis_vectors.size() == 0)
265 {
266 PyErr_SetString( PyExc_ValueError, "Decision function is empty." );
267 throw py::error_already_set();
268 }
269 df.b = b;
270 }
271
272 template <typename kernel_type>
add_linear_df(py::module & m,const std::string name)273 void add_linear_df (
274 py::module &m,
275 const std::string name
276 )
277 {
278 typedef decision_function<kernel_type> df_type;
279 py::class_<df_type>(m, name.c_str())
280 .def("__call__", predict<df_type>)
281 .def_property_readonly("weights", &get_weights<df_type>)
282 .def_property("bias", get_bias<df_type>, set_bias<df_type>)
283 .def(py::pickle(&getstate<df_type>, &setstate<df_type>));
284 }
285
286 // ----------------------------------------------------------------------------------------
287
radial_basis_kernel__repr__(const radial_basis_kernel<sample_type> & item)288 std::string radial_basis_kernel__repr__(const radial_basis_kernel<sample_type>& item)
289 {
290 std::ostringstream sout;
291 sout << "radial_basis_kernel(gamma="<< item.gamma<<")";
292 return sout.str();
293 }
294
linear_kernel__repr__(const linear_kernel<sample_type> & item)295 std::string linear_kernel__repr__(const linear_kernel<sample_type>& item)
296 {
297 std::ostringstream sout;
298 sout << "linear_kernel()";
299 return sout.str();
300 }
301
302 // ----------------------------------------------------------------------------------------
303
binary_test__str__(const binary_test & item)304 std::string binary_test__str__(const binary_test& item)
305 {
306 std::ostringstream sout;
307 sout << "class1_accuracy: "<< item.class1_accuracy << " class2_accuracy: "<< item.class2_accuracy;
308 return sout.str();
309 }
binary_test__repr__(const binary_test & item)310 std::string binary_test__repr__(const binary_test& item) { return "< " + binary_test__str__(item) + " >";}
311
regression_test__str__(const regression_test & item)312 std::string regression_test__str__(const regression_test& item)
313 {
314 std::ostringstream sout;
315 sout << "mean_squared_error: "<< item.mean_squared_error << " R_squared: "<< item.R_squared;
316 sout << " mean_average_error: "<< item.mean_average_error << " mean_error_stddev: "<< item.mean_error_stddev;
317 return sout.str();
318 }
regression_test__repr__(const regression_test & item)319 std::string regression_test__repr__(const regression_test& item) { return "< " + regression_test__str__(item) + " >";}
320
ranking_test__str__(const ranking_test & item)321 std::string ranking_test__str__(const ranking_test& item)
322 {
323 std::ostringstream sout;
324 sout << "ranking_accuracy: "<< item.ranking_accuracy << " mean_ap: "<< item.mean_ap;
325 return sout.str();
326 }
ranking_test__repr__(const ranking_test & item)327 std::string ranking_test__repr__(const ranking_test& item) { return "< " + ranking_test__str__(item) + " >";}
328
329 // ----------------------------------------------------------------------------------------
330
331 template <typename K>
_normalized_test_binary_decision_function(const normalized_function<decision_function<K>> & dec_funct,const std::vector<typename K::sample_type> & x_test,const std::vector<double> & y_test)332 binary_test _normalized_test_binary_decision_function (
333 const normalized_function<decision_function<K>>& dec_funct,
334 const std::vector<typename K::sample_type>& x_test,
335 const std::vector<double>& y_test
336 ) { return binary_test(test_binary_decision_function(dec_funct, x_test, y_test)); }
337
338 template <typename K>
_normalized_test_binary_decision_function_np(const normalized_function<decision_function<K>> & dec_funct,const numpy_image<double> & x_test_,const py::array_t<double> & y_test_)339 binary_test _normalized_test_binary_decision_function_np (
340 const normalized_function<decision_function<K>>& dec_funct,
341 const numpy_image<double>& x_test_,
342 const py::array_t<double>& y_test_
343 )
344 {
345 std::vector<typename K::sample_type> x_test;
346 std::vector<double> y_test;
347 np_to_cpp(x_test_,y_test_, x_test,y_test);
348 return binary_test(test_binary_decision_function(dec_funct, x_test, y_test));
349 }
350
351 template <typename K>
_test_binary_decision_function(const decision_function<K> & dec_funct,const std::vector<typename K::sample_type> & x_test,const std::vector<double> & y_test)352 binary_test _test_binary_decision_function (
353 const decision_function<K>& dec_funct,
354 const std::vector<typename K::sample_type>& x_test,
355 const std::vector<double>& y_test
356 ) { return binary_test(test_binary_decision_function(dec_funct, x_test, y_test)); }
357
358 template <typename K>
_test_regression_function(const decision_function<K> & reg_funct,const std::vector<typename K::sample_type> & x_test,const std::vector<double> & y_test)359 regression_test _test_regression_function (
360 const decision_function<K>& reg_funct,
361 const std::vector<typename K::sample_type>& x_test,
362 const std::vector<double>& y_test
363 ) { return regression_test(test_regression_function(reg_funct, x_test, y_test)); }
364
365 template < typename K >
_test_ranking_function1(const decision_function<K> & funct,const std::vector<ranking_pair<typename K::sample_type>> & samples)366 ranking_test _test_ranking_function1 (
367 const decision_function<K>& funct,
368 const std::vector<ranking_pair<typename K::sample_type> >& samples
369 ) { return ranking_test(test_ranking_function(funct, samples)); }
370
371 template < typename K >
_test_ranking_function2(const decision_function<K> & funct,const ranking_pair<typename K::sample_type> & sample)372 ranking_test _test_ranking_function2 (
373 const decision_function<K>& funct,
374 const ranking_pair<typename K::sample_type>& sample
375 ) { return ranking_test(test_ranking_function(funct, sample)); }
376
377 // ----------------------------------------------------------------------------------------
378
379
setup_auto_train_rbf_classifier(py::module & m)380 void setup_auto_train_rbf_classifier (py::module& m)
381 {
382 m.def("auto_train_rbf_classifier", [](
383 const std::vector<matrix<double,0,1>>& x,
384 const std::vector<double>& y,
385 double max_runtime_seconds,
386 bool be_verbose
387 ) { return auto_train_rbf_classifier(x,y,std::chrono::microseconds((uint64_t)(max_runtime_seconds*1e6)),be_verbose); },
388 py::arg("x"), py::arg("y"), py::arg("max_runtime_seconds"), py::arg("be_verbose")=true,
389 "requires \n\
390 - y contains at least 6 examples of each class. Moreover, every element in y \n\
391 is either +1 or -1. \n\
392 - max_runtime_seconds >= 0 \n\
393 - len(x) == len(y) \n\
394 - all the vectors in x have the same dimension. \n\
395 ensures \n\
396 - This routine trains a radial basis function SVM on the given binary \n\
397 classification training data. It uses the svm_c_trainer to do this. It also \n\
398 uses find_max_global() and 6-fold cross-validation to automatically determine \n\
399 the best settings of the SVM's hyper parameters. \n\
400 - Note that we interpret y[i] as the label for the vector x[i]. Therefore, the \n\
401 returned function, df, should generally satisfy sign(df(x[i])) == y[i] as \n\
402 often as possible. \n\
403 - The hyperparameter search will run for about max_runtime and will print \n\
404 messages to the screen as it runs if be_verbose==true."
405 /*!
406 requires
407 - y contains at least 6 examples of each class. Moreover, every element in y
408 is either +1 or -1.
409 - max_runtime_seconds >= 0
410 - len(x) == len(y)
411 - all the vectors in x have the same dimension.
412 ensures
413 - This routine trains a radial basis function SVM on the given binary
414 classification training data. It uses the svm_c_trainer to do this. It also
415 uses find_max_global() and 6-fold cross-validation to automatically determine
416 the best settings of the SVM's hyper parameters.
417 - Note that we interpret y[i] as the label for the vector x[i]. Therefore, the
418 returned function, df, should generally satisfy sign(df(x[i])) == y[i] as
419 often as possible.
420 - The hyperparameter search will run for about max_runtime and will print
421 messages to the screen as it runs if be_verbose==true.
422 !*/
423 );
424
425 m.def("auto_train_rbf_classifier", [](
426 const numpy_image<double>& x_,
427 const py::array_t<double>& y_,
428 double max_runtime_seconds,
429 bool be_verbose
430 ) {
431 std::vector<matrix<double,0,1>> x;
432 std::vector<double> y;
433 np_to_cpp(x_,y_, x, y);
434 return auto_train_rbf_classifier(x,y,std::chrono::microseconds((uint64_t)(max_runtime_seconds*1e6)),be_verbose); },
435 py::arg("x"), py::arg("y"), py::arg("max_runtime_seconds"), py::arg("be_verbose")=true,
436 "requires \n\
437 - y contains at least 6 examples of each class. Moreover, every element in y \n\
438 is either +1 or -1. \n\
439 - max_runtime_seconds >= 0 \n\
440 - len(x.shape(0)) == len(y) \n\
441 - x.shape(1) > 0 \n\
442 ensures \n\
443 - This routine trains a radial basis function SVM on the given binary \n\
444 classification training data. It uses the svm_c_trainer to do this. It also \n\
445 uses find_max_global() and 6-fold cross-validation to automatically determine \n\
446 the best settings of the SVM's hyper parameters. \n\
447 - Note that we interpret y[i] as the label for the vector x[i]. Therefore, the \n\
448 returned function, df, should generally satisfy sign(df(x[i])) == y[i] as \n\
449 often as possible. \n\
450 - The hyperparameter search will run for about max_runtime and will print \n\
451 messages to the screen as it runs if be_verbose==true."
452 /*!
453 requires
454 - y contains at least 6 examples of each class. Moreover, every element in y
455 is either +1 or -1.
456 - max_runtime_seconds >= 0
457 - len(x.shape(0)) == len(y)
458 - x.shape(1) > 0
459 ensures
460 - This routine trains a radial basis function SVM on the given binary
461 classification training data. It uses the svm_c_trainer to do this. It also
462 uses find_max_global() and 6-fold cross-validation to automatically determine
463 the best settings of the SVM's hyper parameters.
464 - Note that we interpret y[i] as the label for the vector x[i]. Therefore, the
465 returned function, df, should generally satisfy sign(df(x[i])) == y[i] as
466 often as possible.
467 - The hyperparameter search will run for about max_runtime and will print
468 messages to the screen as it runs if be_verbose==true.
469 !*/
470 );
471
472
473 m.def("reduce", [](const normalized_function<decision_function<radial_basis_kernel<matrix<double,0,1>>>>& df,
474 const std::vector<matrix<double,0,1>>& x,
475 long num_bv,
476 double eps)
477 {
478 auto out = df;
479 // null_trainer doesn't use y so we can leave it empty.
480 std::vector<double> y;
481 out.function = reduced2(null_trainer(df.function),num_bv,eps).train(x,y);
482 return out;
483 }, py::arg("df"), py::arg("x"), py::arg("num_basis_vectors"), py::arg("eps")=1e-3
484 );
485
486 m.def("reduce", [](const normalized_function<decision_function<radial_basis_kernel<matrix<double,0,1>>>>& df,
487 const numpy_image<double>& x_,
488 long num_bv,
489 double eps)
490 {
491 std::vector<matrix<double,0,1>> x;
492 np_to_cpp(x_, x);
493 // null_trainer doesn't use y so we can leave it empty.
494 std::vector<double> y;
495 auto out = df;
496 out.function = reduced2(null_trainer(df.function),num_bv,eps).train(x,y);
497 return out;
498 }, py::arg("df"), py::arg("x"), py::arg("num_basis_vectors"), py::arg("eps")=1e-3,
499 "requires \n\
500 - eps > 0 \n\
501 - num_bv > 0 \n\
502 ensures \n\
503 - This routine takes a learned radial basis function and tries to find a \n\
504 new RBF function with num_basis_vectors basis vectors that approximates \n\
505 the given df() as closely as possible. In particular, it finds a \n\
506 function new_df() such that new_df(x[i])==df(x[i]) as often as possible. \n\
507 - This is accomplished using a reduced set method that begins by using a \n\
508 projection, in kernel space, onto a random set of num_basis_vectors \n\
509 vectors in x. Then, L-BFGS is used to further optimize new_df() to match \n\
510 df(). The eps parameter controls how long L-BFGS will run, smaller \n\
511 values of eps possibly giving better solutions but taking longer to \n\
512 execute."
513 /*!
514 requires
515 - eps > 0
516 - num_bv > 0
517 ensures
518 - This routine takes a learned radial basis function and tries to find a
519 new RBF function with num_basis_vectors basis vectors that approximates
520 the given df() as closely as possible. In particular, it finds a
521 function new_df() such that new_df(x[i])==df(x[i]) as often as possible.
522 - This is accomplished using a reduced set method that begins by using a
523 projection, in kernel space, onto a random set of num_basis_vectors
524 vectors in x. Then, L-BFGS is used to further optimize new_df() to match
525 df(). The eps parameter controls how long L-BFGS will run, smaller
526 values of eps possibly giving better solutions but taking longer to
527 execute.
528 !*/
529 );
530 }
531
532 // ----------------------------------------------------------------------------------------
533
bind_decision_functions(py::module & m)534 void bind_decision_functions(py::module &m)
535 {
536 add_linear_df<linear_kernel<sample_type> >(m, "_decision_function_linear");
537 add_linear_df<sparse_linear_kernel<sparse_vect> >(m, "_decision_function_sparse_linear");
538
539 add_df<histogram_intersection_kernel<sample_type> >(m, "_decision_function_histogram_intersection");
540 add_df<sparse_histogram_intersection_kernel<sparse_vect> >(m, "_decision_function_sparse_histogram_intersection");
541
542 add_df<polynomial_kernel<sample_type> >(m, "_decision_function_polynomial");
543 add_df<sparse_polynomial_kernel<sparse_vect> >(m, "_decision_function_sparse_polynomial");
544
545
546 py::class_<radial_basis_kernel<sample_type>>(m, "_radial_basis_kernel")
547 .def("__repr__", radial_basis_kernel__repr__)
548 .def_property_readonly("gamma", [](const radial_basis_kernel<sample_type>& k){return k.gamma; });
549
550 py::class_<linear_kernel<sample_type>>(m, "_linear_kernel")
551 .def("__repr__", linear_kernel__repr__);
552
553 add_df<radial_basis_kernel<sample_type> >(m, "_decision_function_radial_basis");
554 add_df<sparse_radial_basis_kernel<sparse_vect> >(m, "_decision_function_sparse_radial_basis");
555 add_normalized_df<radial_basis_kernel<sample_type>>(m, "_normalized_decision_function_radial_basis");
556
557 setup_auto_train_rbf_classifier(m);
558
559
560 add_df<sigmoid_kernel<sample_type> >(m, "_decision_function_sigmoid");
561 add_df<sparse_sigmoid_kernel<sparse_vect> >(m, "_decision_function_sparse_sigmoid");
562
563 m.def("test_binary_decision_function", _normalized_test_binary_decision_function<radial_basis_kernel<sample_type> >,
564 py::arg("function"), py::arg("samples"), py::arg("labels"));
565 m.def("test_binary_decision_function", _normalized_test_binary_decision_function_np<radial_basis_kernel<sample_type> >,
566 py::arg("function"), py::arg("samples"), py::arg("labels"));
567
568 m.def("test_binary_decision_function", _test_binary_decision_function<linear_kernel<sample_type> >,
569 py::arg("function"), py::arg("samples"), py::arg("labels"));
570 m.def("test_binary_decision_function", _test_binary_decision_function<sparse_linear_kernel<sparse_vect> >,
571 py::arg("function"), py::arg("samples"), py::arg("labels"));
572 m.def("test_binary_decision_function", _test_binary_decision_function<radial_basis_kernel<sample_type> >,
573 py::arg("function"), py::arg("samples"), py::arg("labels"));
574 m.def("test_binary_decision_function", _test_binary_decision_function<sparse_radial_basis_kernel<sparse_vect> >,
575 py::arg("function"), py::arg("samples"), py::arg("labels"));
576 m.def("test_binary_decision_function", _test_binary_decision_function<polynomial_kernel<sample_type> >,
577 py::arg("function"), py::arg("samples"), py::arg("labels"));
578 m.def("test_binary_decision_function", _test_binary_decision_function<sparse_polynomial_kernel<sparse_vect> >,
579 py::arg("function"), py::arg("samples"), py::arg("labels"));
580 m.def("test_binary_decision_function", _test_binary_decision_function<histogram_intersection_kernel<sample_type> >,
581 py::arg("function"), py::arg("samples"), py::arg("labels"));
582 m.def("test_binary_decision_function", _test_binary_decision_function<sparse_histogram_intersection_kernel<sparse_vect> >,
583 py::arg("function"), py::arg("samples"), py::arg("labels"));
584 m.def("test_binary_decision_function", _test_binary_decision_function<sigmoid_kernel<sample_type> >,
585 py::arg("function"), py::arg("samples"), py::arg("labels"));
586 m.def("test_binary_decision_function", _test_binary_decision_function<sparse_sigmoid_kernel<sparse_vect> >,
587 py::arg("function"), py::arg("samples"), py::arg("labels"));
588
589 m.def("test_regression_function", _test_regression_function<linear_kernel<sample_type> >,
590 py::arg("function"), py::arg("samples"), py::arg("targets"));
591 m.def("test_regression_function", _test_regression_function<sparse_linear_kernel<sparse_vect> >,
592 py::arg("function"), py::arg("samples"), py::arg("targets"));
593 m.def("test_regression_function", _test_regression_function<radial_basis_kernel<sample_type> >,
594 py::arg("function"), py::arg("samples"), py::arg("targets"));
595 m.def("test_regression_function", _test_regression_function<sparse_radial_basis_kernel<sparse_vect> >,
596 py::arg("function"), py::arg("samples"), py::arg("targets"));
597 m.def("test_regression_function", _test_regression_function<histogram_intersection_kernel<sample_type> >,
598 py::arg("function"), py::arg("samples"), py::arg("targets"));
599 m.def("test_regression_function", _test_regression_function<sparse_histogram_intersection_kernel<sparse_vect> >,
600 py::arg("function"), py::arg("samples"), py::arg("targets"));
601 m.def("test_regression_function", _test_regression_function<sigmoid_kernel<sample_type> >,
602 py::arg("function"), py::arg("samples"), py::arg("targets"));
603 m.def("test_regression_function", _test_regression_function<sparse_sigmoid_kernel<sparse_vect> >,
604 py::arg("function"), py::arg("samples"), py::arg("targets"));
605 m.def("test_regression_function", _test_regression_function<polynomial_kernel<sample_type> >,
606 py::arg("function"), py::arg("samples"), py::arg("targets"));
607 m.def("test_regression_function", _test_regression_function<sparse_polynomial_kernel<sparse_vect> >,
608 py::arg("function"), py::arg("samples"), py::arg("targets"));
609
610 m.def("test_ranking_function", _test_ranking_function1<linear_kernel<sample_type> >,
611 py::arg("function"), py::arg("samples"));
612 m.def("test_ranking_function", _test_ranking_function1<sparse_linear_kernel<sparse_vect> >,
613 py::arg("function"), py::arg("samples"));
614 m.def("test_ranking_function", _test_ranking_function2<linear_kernel<sample_type> >,
615 py::arg("function"), py::arg("sample"));
616 m.def("test_ranking_function", _test_ranking_function2<sparse_linear_kernel<sparse_vect> >,
617 py::arg("function"), py::arg("sample"));
618
619
620 py::class_<binary_test>(m, "_binary_test")
621 .def("__str__", binary_test__str__)
622 .def("__repr__", binary_test__repr__)
623 .def_readwrite("class1_accuracy", &binary_test::class1_accuracy,
624 "A value between 0 and 1, measures accuracy on the +1 class.")
625 .def_readwrite("class2_accuracy", &binary_test::class2_accuracy,
626 "A value between 0 and 1, measures accuracy on the -1 class.");
627
628 py::class_<ranking_test>(m, "_ranking_test")
629 .def("__str__", ranking_test__str__)
630 .def("__repr__", ranking_test__repr__)
631 .def_readwrite("ranking_accuracy", &ranking_test::ranking_accuracy,
632 "A value between 0 and 1, measures the fraction of times a relevant sample was ordered before a non-relevant sample.")
633 .def_readwrite("mean_ap", &ranking_test::mean_ap,
634 "A value between 0 and 1, measures the mean average precision of the ranking.");
635
636 py::class_<regression_test>(m, "_regression_test")
637 .def("__str__", regression_test__str__)
638 .def("__repr__", regression_test__repr__)
639 .def_readwrite("mean_average_error", ®ression_test::mean_average_error,
640 "The mean average error of a regression function on a dataset.")
641 .def_readwrite("mean_error_stddev", ®ression_test::mean_error_stddev,
642 "The standard deviation of the absolute value of the error of a regression function on a dataset.")
643 .def_readwrite("mean_squared_error", ®ression_test::mean_squared_error,
644 "The mean squared error of a regression function on a dataset.")
645 .def_readwrite("R_squared", ®ression_test::R_squared,
646 "A value between 0 and 1, measures the squared correlation between the output of a \n"
647 "regression function and the target values.");
648 }
649
650
651
652