Commit 871c2c0d authored by André Anjos's avatar André Anjos 💬

Increase test coverage

parent ce0f1064
......@@ -42,8 +42,8 @@ the import function:
The include directory can be discovered using
:py:func:`xbob.learn.libsvm.get_include`.
LIBSVM File Interface
----------------------
File Interface
--------------
.. cpp:type:: PyBobLearnLibsvmFileObject
......@@ -67,8 +67,8 @@ LIBSVM File Interface
Checks if the input object ``o`` is a ``PyBobLearnLibsvmFileObject``.
Returns ``1`` if it is, and ``0`` otherwise.
LIBSVM Machine Interface
------------------------
Machine Interface
-----------------
.. cpp:type:: PyBobLearnLibsvmMachineObject
......@@ -84,7 +84,99 @@ LIBSVM Machine Interface
.. cpp:member:: bob::learn::libsvm::Machine* cxx
A pointer to the C++ file implementation.
A pointer to the C++ machine implementation.
.. cpp:function:: int PyBobLearnLibsvmMachine_Check(PyObject* o)
Checks if the input object ``o`` is a ``PyBobLearnLibsvmMachineObject``.
Returns ``1`` if it is, and ``0`` otherwise.
.. cpp:function:: PyObject* PyBobLearnLibsvmMachine_NewFromMachine(bob::learn::libsvm::Machine* m)
Builds a new Python object from an existing :cpp:class:`Machine`. The
machine object ``m`` is **stolen** from the user, which should not delete it
anymore.
Trainer Interface
-----------------
.. cpp:type:: PyBobLearnLibsvmTrainerObject
The pythonic object representation for a ``bob::learn::libsvm::Trainer``
object.
.. code-block:: cpp
typedef struct {
PyObject_HEAD
bob::learn::libsvm::Trainer* cxx;
} PyBobLearnLibsvmTrainerObject
.. cpp:member:: bob::learn::libsvm::Trainer* cxx
A pointer to the C++ trainer implementation.
.. cpp:function:: int PyBobLearnLibsvmTrainer_Check(PyObject* o)
Checks if the input object ``o`` is a ``PyBobLearnLibsvmTrainerObject``.
Returns ``1`` if it is, and ``0`` otherwise.
Other Utilities
---------------
.. cpp:function:: PyObject* PyBobLearnLibsvm_MachineTypeAsString(bob::learn::libsvm::machine_t s)
Returns a Python string representing given a machine type. Returns ``NULL``
and sets an :py:class:`RuntimeError` if the enumeration provided is not
supported.
This function will return a proper :c:type:`PyStringObject` on Python 2.x
and a :c:type:`PyUnicodeObject` on Python 3.x.
.. cpp:function:: bob::learn::libsvm::machine_t PyBobLearnLibsvm_StringAsMachineType(PyObject* o)
Decodes the machine type enumeration from a pythonic string. Works with any
string type or subtype. A :py:class:`RuntimeError` is set if the string
cannot be encoded as one of the available enumerations. You must check for
:c:func:`PyErr_Occurred` after a call to this function to make sure that the
conversion was correctly performed.
.. cpp:function:: bob::learn::libsvm::machine_t PyBobLearnLibsvm_CStringAsMachineType(const char* s)
This function works the same as
:cpp:func:`PyBobLearnLibsvm_StringAsMachineType`, but accepts a C-style
string instead of a Python object as input. A :py:class:`RuntimeError` is
set if the string cannot be encoded as one of the available enumerations.
You must check for :c:func:`PyErr_Occurred` after a call to this function to
make sure that the conversion was correctly performed.
.. cpp:function:: PyObject* PyBobLearnLibsvm_KernelTypeAsString(bob::learn::libsvm::kernel_t s)
Returns a Python string representing given a kernel type. Returns ``NULL``
and sets an :py:class:`RuntimeError` if the enumeration provided is not
supported.
This function will return a proper :c:type:`PyStringObject` on Python 2.x
and a :c:type:`PyUnicodeObject` on Python 3.x.
.. cpp:function:: bob::learn::libsvm::kernel_t PyBobLearnLibsvm_StringAsKernelType(PyObject* o)
Decodes the kernel type enumeration from a pythonic string. Works with any
string type or subtype. A :py:class:`RuntimeError` is set if the string
cannot be encoded as one of the available enumerations. You must check for
:c:func:`PyErr_Occurred` after a call to this function to make sure that the
conversion was correctly performed.
.. cpp:function:: bob::learn::libsvm::kernel_t PyBobLearnLibsvm_CStringAsKernelType(const char* s)
This function works the same as
:cpp:func:`PyBobLearnLibsvm_StringAsKernelType`, but accepts a C-style
string instead of a Python object as input. A :py:class:`RuntimeError` is
set if the string cannot be encoded as one of the available enumerations.
You must check for :c:func:`PyErr_Occurred` after a call to this function to
make sure that the conversion was correctly performed.
.. include:: links.rst
......@@ -4,6 +4,24 @@
..
.. Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
.. testsetup::
import os
import numpy
import xbob.learn.libsvm
def F(m, f):
from pkg_resources import resource_filename
return resource_filename(m, os.path.join('data', f))
heart_model = F('xbob.learn.libsvm', 'heart.svmmodel')
svm = xbob.learn.libsvm.Machine(heart_model)
heart_data = F('xbob.learn.libsvm', 'heart.svmdata')
f = xbob.learn.libsvm.File(heart_data)
======================================
Support Vector Machines and Trainers
======================================
......@@ -43,28 +61,14 @@ using the application ``svm-train`` with default parameters). The ``shape``
attribute, indicates how many features a machine from this module can input and
how many it outputs (typically, just 1):
.. testsetup:: machine
import os
import xbob.learn.libsvm
import numpy
def F(m, f):
from pkg_resources import resource_filename
return resource_filename(m, os.path.join('data', f))
heart_model = F('xbob.learn.libsvm', 'heart.svmmodel')
svm = xbob.learn.libsvm.Machine(heart_model)
.. doctest:: machine
.. doctest::
>>> svm.shape
(13, 1)
To run a single example through the SVM, just use the ``()`` operator:
.. doctest:: machine
.. doctest::
>> svm(numpy.ones((13,), 'float64'))
1
......@@ -81,25 +85,7 @@ Below is a quick example: Suppose the variable ``f`` contains an object of
type :py:class:`xbob.learn.libsvm.File`. Then, you could read data (and labels)
from the file like this:
.. testsetup:: file
import os
import numpy
import xbob.learn.libsvm
def F(m, f):
from pkg_resources import resource_filename
return resource_filename('%s.test' % m, os.path.join('data', f))
heart_data = F('xbob.learn.libsvm', 'heart.svmdata')
f = xbob.learn.libsvm.File(heart_data)
heart_model = F('machine', 'heart.svmmodel')
svm = xbob.learn.libsvm.Machine(heart_model)
.. doctest:: file
.. doctest::
:options: +NORMALIZE_WHITESPACE
>>> labels, data = f.read_all()
......@@ -108,7 +94,7 @@ from the file like this:
Then you can throw the data into the ``svm`` machine you trained earlier like
this:
.. doctest:: file
.. doctest::
:options: +NORMALIZE_WHITESPACE
>>> predicted_labels = svm(data)
......@@ -122,7 +108,7 @@ training samples for the given class and the second dimension is the
dimensionality of the feature. For instance, let's consider the following
training set for a two class problem:
.. doctest:: trainer
.. doctest::
:options: +NORMALIZE_WHITESPACE
>>> pos = numpy.array([[1,-1,1], [0.5,-0.5,0.5], [0.75,-0.75,0.8]], 'float64')
......@@ -140,7 +126,7 @@ training set for a two class problem:
Then, an SVM [1]_ can be trained easily using the
:py:class:`xbob.learn.libsvm.Trainer` class.
.. doctest:: trainer
.. doctest::
:options: +NORMALIZE_WHITESPACE
>>> trainer = xbob.learn.libsvm.Trainer()
......@@ -149,22 +135,22 @@ Then, an SVM [1]_ can be trained easily using the
This returns a :py:class:`xbob.learn.libsvm.Machine` which can later be used
for classification, as explained before.
.. doctest:: trainer
.. doctest::
:options: +NORMALIZE_WHITESPACE
>>> predicted_label = machine(numpy.array([1.,-1.,1.]))
>>> print(predicted_label)
1
[1]
The `training` procedure allows setting several different options. For
instance, the default `kernel` is an `RBF`. If we would like a `linear SVM`
instead, this can be set before calling the
:py:meth:`xbob.learn.libsvm.Trainer.train` method.
.. doctest:: trainer
.. doctest::
:options: +NORMALIZE_WHITESPACE
>>> trainer.kernel_type = xbob.learn.libsvm.svm_kernel_type.LINEAR
>>> trainer.kernel_type = 'LINEAR'
Acknowledgements
......
......@@ -86,7 +86,7 @@ namespace bob { namespace learn { namespace libsvm {
double getCoef0() const { return m_param.coef0; }
void setCoef0(double v) { m_param.coef0 = v; }
double getCacheSizeInMB() const { return m_param.cache_size; }
double getCacheSizeInMb() const { return m_param.cache_size; }
void setCacheSizeInMb(double v) { m_param.cache_size = v; }
double getStopEpsilon() const { return m_param.eps; }
......
......@@ -224,7 +224,7 @@ PyObject* PyBobLearnLibsvmFile_reset(PyBobLearnLibsvmFileObject* self) {
PyDoc_STRVAR(s_good_str, "good");
PyDoc_STRVAR(s_good_doc,
"o.good() -> None\n\
"o.good() -> bool\n\
\n\
Returns if the file is in a good state for readout.\n\
It is ``True`` if the current file it has neither the\n\
......@@ -249,7 +249,7 @@ PyObject* PyBobLearnLibsvmFile_good(PyBobLearnLibsvmFileObject* self) {
PyDoc_STRVAR(s_fail_str, "fail");
PyDoc_STRVAR(s_fail_doc,
"o.fail() -> None\n\
"o.fail() -> bool\n\
\n\
Returns ``True`` if the file has a ``fail`` condition or\n\
``bad`` bit sets. It means the read operation has found a\n\
......@@ -276,7 +276,7 @@ PyObject* PyBobLearnLibsvmFile_fail(PyBobLearnLibsvmFileObject* self) {
PyDoc_STRVAR(s_eof_str, "eof");
PyDoc_STRVAR(s_eof_doc,
"o.eof() -> None\n\
"o.eof() -> bool\n\
\n\
Returns ``True`` if the file has reached its end. To start\n\
reading from the file again, you must call :py:meth:`File.reset`\n\
......
This diff is collapsed.
......@@ -43,6 +43,60 @@ def test_initialization():
# all defaults
trainer = Trainer()
# check defaults are right
nose.tools.eq_(trainer.machine_type, 'C_SVC')
nose.tools.eq_(trainer.kernel_type, 'RBF')
nose.tools.eq_(trainer.cache_size, 100.)
nose.tools.eq_(trainer.stop_epsilon, 1e-3)
assert trainer.shrinking
assert not trainer.probability
def test_get_and_set():
trainer = Trainer()
# now tries setting the various properties
trainer.machine_type = 'NU_SVC'
nose.tools.eq_(trainer.machine_type, 'NU_SVC')
trainer.kernel_type = 'LINEAR'
nose.tools.eq_(trainer.kernel_type, 'LINEAR')
trainer.cache_size = 2
nose.tools.eq_(trainer.cache_size, 2)
trainer.coef0 = 2
nose.tools.eq_(trainer.coef0, 2)
trainer.cost = 2
nose.tools.eq_(trainer.cost, 2)
trainer.degree = 2
nose.tools.eq_(trainer.degree, 2)
trainer.gamma = 2
nose.tools.eq_(trainer.gamma, 2)
trainer.nu = 2
nose.tools.eq_(trainer.nu, 2)
trainer.stop_epsilon = 2
nose.tools.eq_(trainer.stop_epsilon, 2)
trainer.shrinking = False
nose.tools.eq_(trainer.shrinking, False)
trainer.probability = True
nose.tools.eq_(trainer.probability, True)
@nose.tools.raises(ValueError)
def test_set_machine_raises():
trainer = Trainer()
trainer.machine_type = 'wrong'
@nose.tools.raises(ValueError)
def test_set_kernel_raises():
trainer = Trainer()
trainer.kernel_type = 'wrong'
@nose.tools.raises(TypeError)
def test_cannot_delete():
trainer = Trainer()
del trainer.kernel_type
def test_training():
# For this example I'm using an SVM file because of convinience. You only
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment