Commit 0208357b authored by Manuel Günther's avatar Manuel Günther
Browse files

Changed datatype of indices to int32.

parent 6d4c1df8
......@@ -5,9 +5,13 @@
[buildout]
parts = xbob.boosting scripts
eggs = xbob.boosting
xbob.db.banca
xbob.db.mnist
newest = false
prefixes = /idiap/group/torch5spro/releases/bob-1.2.0/install/linux-x86_64-release
;prefixes = /idiap/group/torch5spro/releases/bob-1.2.0/install/linux-x86_64-release
prefixes = /idiap/user/mguenther/Bob/release
;prefixes = /idiap/user/mguenther/Bob/debug
[xbob.boosting]
......
......@@ -57,9 +57,7 @@ setup(
# privileges when using buildout.
install_requires=[
'setuptools',
'bob', # base signal proc./machine learning library
'xbob.db.mnist',
'xbob.db.banca'
'bob' # base signal proc./machine learning library
],
cmdclass={
......@@ -79,7 +77,7 @@ setup(
'bob-io',
],
include_dirs = [
"xbob/boosting/cpp"
"/idiap/user/mguenther/Bob/release/include",
],
# STUFF for DEBUGGING goes here (requires DEBUG bob version...):
# extra_compile_args = [
......
......@@ -14,7 +14,7 @@ class WeakMachine{
virtual void forward3(const blitz::Array<uint16_t, 2>& features, blitz::Array<double,2> predictions) const {throw std::runtime_error("This function is not implemented for the given data type in the current class.");}
virtual void forward3(const blitz::Array<double, 2>& features, blitz::Array<double,2> predictions) const {throw std::runtime_error("This function is not implemented for the given data type in the current class.");}
virtual blitz::Array<int,1> getIndices() const = 0;
virtual blitz::Array<int32_t,1> getIndices() const = 0;
virtual void save(bob::io::HDF5File& file) const = 0;
virtual void load(bob::io::HDF5File& file) = 0;
......@@ -31,7 +31,7 @@ class StumpMachine : public WeakMachine{
virtual double forward1(const blitz::Array<double, 1>& features) const;
virtual void forward2(const blitz::Array<double, 2>& features, blitz::Array<double,1> predictions) const;
virtual blitz::Array<int,1> getIndices() const;
virtual blitz::Array<int32_t,1> getIndices() const;
double getThreshold() const {return m_threshold;}
double getPolarity() const {return m_polarity;}
......@@ -45,7 +45,7 @@ class StumpMachine : public WeakMachine{
// the LUT for the multi-variate case
double m_threshold;
double m_polarity;
int m_index;
int32_t m_index;
};
......@@ -58,7 +58,7 @@ class LUTMachine : public WeakMachine{
virtual void forward2(const blitz::Array<uint16_t, 2>& features, blitz::Array<double,1> predictions) const;
virtual void forward3(const blitz::Array<uint16_t, 2>& features, blitz::Array<double,2> predictions) const;
virtual blitz::Array<int,1> getIndices() const;
virtual blitz::Array<int32_t,1> getIndices() const;
virtual void save(bob::io::HDF5File& file) const;
virtual void load(bob::io::HDF5File& file);
......@@ -68,10 +68,10 @@ class LUTMachine : public WeakMachine{
private:
// the LUT for the multi-variate case
blitz::Array<double,2> m_look_up_tables;
blitz::Array<int,1> m_indices;
blitz::Array<int32_t,1> m_indices;
// for speed reasons, we also keep the LUT for the uni-variate case
blitz::Array<double,1> m_look_up_table;
int m_index;
int32_t m_index;
};
......@@ -104,10 +104,12 @@ class BoostedMachine{
// predicts the output and the labels for the given features (multi-variate case)
void forward3(const blitz::Array<uint16_t, 2>& features, blitz::Array<double,2> predictions, blitz::Array<double,2> labels) const;
blitz::Array<int,1> getIndices() const;
blitz::Array<int32_t,1> getIndices(int start = 0, int end = -1) const;
const blitz::Array<double,2> getWeights() const {return m_weights;}
const std::vector<boost::shared_ptr<WeakMachine> >& getWeakMachines() const {return m_weak_machines;}
// writes the machine to file
void save(bob::io::HDF5File& file) const;
......
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
#include <bob/config.h>
#include <bob/python/ndarray.h>
#include <bob/python/gil.h>
#include "Machines.h"
......@@ -13,6 +16,47 @@ static void f12(StumpMachine& s, const blitz::Array<double,2>& f, blitz::Array<d
static double f21(StumpMachine& s, const blitz::Array<uint16_t,1>& f){return s.forward1(f);}
static void f22(StumpMachine& s, const blitz::Array<uint16_t,2>& f, blitz::Array<double,1> p){s.forward2(f,p);}
static double forward1(const BoostedMachine& self, const blitz::Array<uint16_t, 1>& features){
bob::python::no_gil t;
return self.forward1(features);
}
static void forward2(const BoostedMachine& self, const blitz::Array<uint16_t, 2>& features, blitz::Array<double,1> predictions, blitz::Array<double,1> labels){
bob::python::no_gil t;
self.forward2(features, predictions, labels);
}
static void forward3(const BoostedMachine& self, const blitz::Array<uint16_t, 2>& features, blitz::Array<double,2> predictions, blitz::Array<double,2> labels){
bob::python::no_gil t;
self.forward3(features, predictions, labels);
}
static boost::shared_ptr<BoostedMachine> init_from_vector_of_weak2(object weaks, const blitz::Array<double,1>& weights){
stl_input_iterator<boost::shared_ptr<WeakMachine> > dbegin(weaks), dend;
boost::shared_ptr<BoostedMachine> strong = boost::make_shared<BoostedMachine>();
for (int i = 0; dbegin != dend; ++dbegin, ++i){
strong->add_weak_machine2(*dbegin, weights(i));
}
return strong;
}
static object get_weak_machines(const BoostedMachine& self){
const std::vector<boost::shared_ptr<WeakMachine> >& weaks = self.getWeakMachines();
list ret;
for (std::vector<boost::shared_ptr<WeakMachine> >::const_iterator it = weaks.begin(); it != weaks.end(); ++it){
ret.append(*it);
}
return ret;
}
static blitz::Array<int32_t, 1> get_indices(const BoostedMachine& self){
return self.getIndices();
}
BOOST_PYTHON_MODULE(_boosting) {
bob::python::setup_python("Bindings for the xbob.boosting machines.");
......@@ -49,15 +93,22 @@ BOOST_PYTHON_MODULE(_boosting) {
class_<BoostedMachine, boost::shared_ptr<BoostedMachine> >("BoostedMachine", "A machine containing of several weak machines", no_init)
.def(init<>(arg("self"), "Creates an empty machine."))
.def(init<bob::io::HDF5File&>((arg("self"), arg("file")), "Creates a new machine from file"))
.def("__init__", make_constructor(&init_from_vector_of_weak2, default_call_policies(), (arg("weak_classifiers"), arg("weights"))), "Uses the given list of weak classifiers and their weights.")
.def("add_weak_machine", &BoostedMachine::add_weak_machine1, (arg("self"), arg("machine"), arg("weight")), "Adds the given weak machine with the given weight (uni-variate)")
.def("add_weak_machine", &BoostedMachine::add_weak_machine2, (arg("self"), arg("machine"), arg("weights")), "Adds the given weak machine with the given weights (multi-variate)")
.def("__call__", &BoostedMachine::forward1, (arg("self"), arg("features")), "Returns the prediction for the given feature vector.")
.def("__call__", &BoostedMachine::forward2, (arg("self"), arg("features"), arg("predictions"), arg("labels")), "Computes the predictions and the labels for the given feature set (uni-variate).")
.def("__call__", &BoostedMachine::forward3, (arg("self"), arg("features"), arg("predictions"), arg("labels")), "Computes the predictions and the labels for the given feature set (multi-variate).")
.def("forward_p", &forward1, (arg("self"), arg("features")), "Returns the prediction for the given feature vector.")
.def("forward_p", &forward2, (arg("self"), arg("features"), arg("predictions"), arg("labels")), "Computes the predictions and the labels for the given feature set (uni-variate).")
.def("forward_p", &forward3, (arg("self"), arg("features"), arg("predictions"), arg("labels")), "Computes the predictions and the labels for the given feature set (multi-variate).")
.def("load", &BoostedMachine::load, "Reads a Machine from file")
.def("save", &BoostedMachine::save, "Writes the machine to file")
.def("feature_indices", &BoostedMachine::getIndices, (arg("self")), "Returns the indices required for this machine.")
.def("alpha", &BoostedMachine::getWeights, (arg("self")), "Returns the weights for the weak machines.")
.def("feature_indices", &BoostedMachine::getIndices, (arg("self"), arg("start")=0, arg("end")=-1), "Get the indices required for this machine. If given, start and end limits the weak machines.")
.add_property("indices", &get_indices, "The indices required for this machine.")
.add_property("alpha", &BoostedMachine::getWeights, "The weights for the weak machines.")
.add_property("weights", &BoostedMachine::getWeights, "The weights for the weak machines.")
.add_property("weak_machines", &get_weak_machines, "The weak machines.")
;
}
......@@ -69,14 +69,15 @@ void BoostedMachine::forward3(const blitz::Array<uint16_t,2>& features, blitz::A
}
}
blitz::Array<int,1> BoostedMachine::getIndices() const{
std::set<int> indices;
for (unsigned i = 0; i < m_weak_machines.size(); ++i){
const blitz::Array<int,1>& ind = m_weak_machines[i]->getIndices();
blitz::Array<int,1> BoostedMachine::getIndices(int start, int end) const{
std::set<int32_t> indices;
if (end < 0) end = m_weak_machines.size();
for (int i = start; i < end; ++i){
const blitz::Array<int32_t,1>& ind = m_weak_machines[i]->getIndices();
indices.insert(ind.begin(), ind.end());
}
blitz::Array<int,1> ret(indices.size());
blitz::Array<int32_t,1> ret(indices.size());
std::copy(indices.begin(), indices.end(), ret.begin());
return ret;
}
......
......@@ -57,12 +57,12 @@ void LUTMachine::forward3(const blitz::Array<uint16_t,2>& features, blitz::Array
}
}
blitz::Array<int,1> LUTMachine::getIndices() const{
std::set<int> indices;
blitz::Array<int32_t,1> LUTMachine::getIndices() const{
std::set<int32_t> indices;
for (int i = 0; i < m_indices.extent(0); ++i){
indices.insert(m_indices(i));
}
blitz::Array<int, 1> ret(indices.size());
blitz::Array<int32_t, 1> ret(indices.size());
std::copy(indices.begin(), indices.end(), ret.begin());
return ret;
}
......@@ -71,12 +71,12 @@ void LUTMachine::load(bob::io::HDF5File& file){
try{
m_look_up_tables.reference(file.readArray<double,2>("LUT"));
}catch (std::exception){
m_look_up_tables.reference(bob::core::array::cast<double>(file.readArray<int64_t,2>("LUT")));
m_look_up_tables.reference(bob::core::array::cast<double>(file.readArray<int32_t,2>("LUT")));
}
try{
m_indices.reference(file.readArray<int,1>("Indices"));
}catch (std::exception){
m_indices.reference(bob::core::array::cast<int>(file.readArray<int64_t,1>("Indices")));
m_indices.reference(bob::core::array::cast<int>(file.readArray<int32_t,1>("Indices")));
}
m_look_up_table.reference(m_look_up_tables(blitz::Range::all(), 0));
......
......@@ -44,8 +44,8 @@ void StumpMachine::forward2(const blitz::Array<uint16_t, 2>& features, blitz::Ar
}
blitz::Array<int,1> StumpMachine::getIndices() const{
blitz::Array<int, 1> ret(1);
blitz::Array<int32_t,1> StumpMachine::getIndices() const{
blitz::Array<int32_t, 1> ret(1);
ret = m_index;
return ret;
}
......@@ -53,7 +53,7 @@ blitz::Array<int,1> StumpMachine::getIndices() const{
void StumpMachine::load(bob::io::HDF5File& file){
m_threshold = file.read<double>("Threshold");
m_polarity = file.read<double>("Polarity");
m_index = file.read<int>("Index");
m_index = file.read<int32_t>("Index");
}
void StumpMachine::save(bob::io::HDF5File& file) const{
......
......@@ -105,7 +105,7 @@ def test_cpp_machine():
# try to read the machine from the temp file, which was written with the python version
f = get_temp_file()
new_machine = xbob.boosting.BoostedMachine(bob.io.HDF5File(f))
assert (new_machine.alpha() == 1).all()
assert (new_machine.alpha == 1).all()
os.remove(get_temp_file())
......
import unittest
import random
import xbob.boosting
import numpy
class TestStumpTrainer(unittest.TestCase):
"""Perform test on stump weak trainer"""
def test_stump_trainer(self):
# test the stump trainer for basic linearly seperable case and check the conditions on stump parameters
trainer = xbob.boosting.core.trainers.StumpTrainer()
n_samples = 100
dim = 5
x_train1 = numpy.random.randn(n_samples, dim) + 4
x_train2 = numpy.random.randn(n_samples, dim) - 4
x_train = numpy.vstack((x_train1, x_train2))
y_train = numpy.hstack((numpy.ones(n_samples),-numpy.ones(n_samples)))
scores = numpy.zeros(2*n_samples)
t = y_train*scores
loss = -y_train*(numpy.exp(y_train*scores))
stump = trainer.compute_weak_trainer(x_train,loss)
self.assertTrue(stump.threshold <= numpy.max(x_train))
self.assertTrue(stump.threshold >= numpy.min(x_train))
self.assertTrue(stump.selected_indices >= 0)
self.assertTrue(stump.selected_indices < dim)
x_test1 = numpy.random.randn(n_samples, dim) + 4
x_test2 = numpy.random.randn(n_samples, dim) - 4
x_test = numpy.vstack((x_test1, x_test2))
y_test = numpy.hstack((numpy.ones(n_samples),-numpy.ones(n_samples)))
prediction = trainer.get_weak_scores(x_test) # return negative labels
self.assertTrue(numpy.all(prediction.T * y_test < 0) )
def test_stump_index(self):
# test the stump trainer if the correct feature indices are selected
trainer = xbob.boosting.core.trainers.StumpTrainer()
num_samples = 100
dim = 10
selected_index = 4
x_train1 = numpy.random.randn(num_samples, dim)
x_train2 = numpy.random.randn(num_samples, dim)
x_train = numpy.vstack((x_train1, x_train2))
x_train[0:num_samples,selected_index] = x_train[0:num_samples,selected_index] +2
x_train[num_samples+1:,selected_index] = x_train[num_samples +1:,selected_index] -2
y_train = numpy.hstack((numpy.ones(num_samples),-numpy.ones(num_samples)))
scores = numpy.zeros(2*num_samples)
t = y_train*scores
loss = -y_train*(numpy.exp(y_train*scores))
stump = trainer.compute_weak_trainer(x_train,loss)
self.assertEqual(stump.selected_indices, selected_index)
polarity = stump.polarity
# test the check on polarity when the labels are reversed
y_train = - y_train
t = y_train*scores
loss = -y_train*(numpy.exp(y_train*scores))
stump = trainer.compute_weak_trainer(x_train,loss)
polarity_rev = stump.polarity
self.assertEqual(polarity, -polarity_rev)
def test_threshold(self):
# test to check the threshold value of the weak trainer
trainer = xbob.boosting.core.trainers.StumpTrainer()
num_samples = 100
dim = 10
selected_index = 4
x_train1 = numpy.random.randn(num_samples, dim)
x_train2 = numpy.random.randn(num_samples, dim)
x_train = numpy.vstack((x_train1, x_train2))
x_train[0:num_samples,selected_index] = x_train[0:num_samples,selected_index] +4
x_train[num_samples+1:,selected_index] = x_train[num_samples +1:,selected_index] +2
y_train = numpy.hstack((numpy.ones(num_samples),-numpy.ones(num_samples)))
scores = numpy.zeros(2*num_samples)
t = y_train*scores
loss = -y_train*(numpy.exp(y_train*scores))
stump = trainer.compute_weak_trainer(x_train,loss)
self.assertTrue(stump.threshold > 2)
self.assertTrue(stump.threshold < 4)
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