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

Provided IO capabilities for the Machines (fixed #1).

parent 48b65adf
......@@ -30,7 +30,6 @@ import scipy.optimize
class Boost:
""" The class to boost the features from a set of training samples.
......@@ -174,7 +173,7 @@ class Boost:
targets = targets[:,numpy.newaxis]
num_op = targets.shape[1]
machine = BoostMachine(num_op)
machine = BoostMachine()
num_samp = fset.shape[0]
pred_scores = numpy.zeros([num_samp,num_op])
loss_class = losses.LOSS_FUNCTIONS[self.loss_type]
......@@ -186,12 +185,11 @@ class Boost:
# For each round of boosting initialize a new weak trainer
if self.weak_trainer_type == 'LutTrainer':
weak_trainer = trainers.LutTrainer(self.num_entries, self.lut_selection, num_op )
elif self.weak_trainer_type == 'StumpTrainer':
weak_trainer = trainers.StumpTrainer()
#elif self.weak_trainer_type == 'GaussTrainer':
# weak_trainer = trainers.GaussianTrainer(3)
weak_trainer = {
'LutTrainer' : trainers.LutTrainer(self.num_entries, self.lut_selection, num_op),
'StumpTrainer' : trainers.StumpTrainer(),
# 'GaussTrainer' : trainers.GaussianTrainer(3)
} [self.weak_trainer_type]
# Start boosting iterations for num_rnds rounds
......@@ -237,11 +235,10 @@ class BoostMachine():
""" The class to perform the classification using the set of weak trainer """
def __init__(self, num_op):
def __init__(self):
""" Initialize the set of weak trainers and the alpha values (scale)"""
self.alpha = []
self.weak_trainer = []
self.num_op = num_op
......@@ -299,8 +296,9 @@ class BoostMachine():
# Initialization
num_trainer = len(self.weak_trainer)
num_samp = test_features.shape[0]
pred_labels = -numpy.ones([num_samp, self.num_op])
pred_scores = numpy.zeros([num_samp, self.num_op])
num_op = test_features.shape[1]
pred_labels = -numpy.ones([num_samp, num_op])
pred_scores = numpy.zeros([num_samp, num_op])
# For each round of boosting calculate the weak scores for that round and add to the total
......@@ -310,7 +308,7 @@ class BoostMachine():
pred_scores = pred_scores + self.alpha[i] * weak_scores
# predict the labels for test features based on score sign (for binary case) and score value (multivariate case)
if(self.num_op == 1):
if(num_op == 1):
pred_labels[pred_scores >=0] = 1
pred_labels = numpy.squeeze(pred_labels)
else:
......@@ -319,4 +317,33 @@ class BoostMachine():
return pred_scores, pred_labels
def save(self, hdf5File):
# hdf5File.set_attribute("MachineType", self.weak_trainer_type)
hdf5File.set_attribute("version", 0)
hdf5File.set("Weights", self.alpha)
for i in range(len(self.weak_trainer)):
dir_name = "WeakMachine%d"%i
hdf5File.create_group(dir_name)
hdf5File.cd(dir_name)
hdf5File.set_attribute("MachineType", self.weak_trainer[i].__class__.__name__)
self.weak_trainer[i].save(hdf5File)
hdf5File.cd('..')
def load(self, hdf5File):
# self.weak_trainer_type = hdf5File.get_attribute("MachineType")
self.alpha = hdf5File.read("Weights")
self.weak_trainer = []
for i in range(len(self.alpha)):
dir_name = "WeakMachine%d"%i
hdf5File.cd(dir_name)
weak_machine_type = hdf5File.get_attribute("MachineType")
weak_machine = {
"LutMachine" : trainers.LutMachine(),
"StumpMachine" : trainers.StumpMachine()
} [weak_machine_type]
weak_machine.load(hdf5File)
self.weak_trainer.append(weak_machine)
hdf5File.cd('..')
......@@ -18,11 +18,11 @@ class StumpMachine():
the polarity and the feature index corresponding to the weak classifier. """
def __init__(self):
def __init__(self, threshold = 0, polarity = 0, selected_indices = 0):
""" Initialize the stump classifier"""
self.threshold = 0
self.polarity = 0
self.selected_indices = 0
self.threshold = threshold
self.polarity = polarity
self.selected_indices = selected_indices
def get_weak_scores(self,test_features):
......@@ -51,6 +51,31 @@ class StumpMachine():
return weak_scores
def get_weak_score(self, feature):
"""Returns the weak score for the given single feature, assuming only a single output.
Input: a single feature vector of size No. of total features.
Output: a single number (+1/-1)
"""
# classify the features and compute the score
return self.polarity * (-1. if feature[self.selected_indices] < self.threshold else 1.)
def save(self, hdf5File):
"""Saves the current state of this machine to the given HDF5File."""
hdf5File.set("Indices", self.selected_indices)
hdf5File.set("Threshold", self.threshold)
hdf5File.set("Polarity", self.polarity)
def load(self, hdf5File):
"""Reads the state of this machine from the given HDF5File."""
self.selected_indices = hdf5File.read("Indices")
self.threshold = hdf5File.read("Threshold")
self.polarity = hdf5File.read("Polarity")
class StumpTrainer():
""" The weak trainer class for training stumps as classifiers. The trainer is parametrized
the threshold and the polarity.
......@@ -84,7 +109,6 @@ class StumpTrainer():
threshold = numpy.zeros([numFea])
polarity = numpy.zeros([numFea])
gain = numpy.zeros([numFea])
stump_machine = StumpMachine()
# For each feature find the optimum threshold, polarity and the gain
for i in range(numFea):
......@@ -94,10 +118,7 @@ class StumpTrainer():
# Find the optimum id and its corresponding trainer
opt_id = gain.argmax()
stump_machine.threshold = threshold[opt_id]
stump_machine.polarity = polarity[opt_id]
stump_machine.selected_indices = opt_id
return stump_machine
return StumpMachine(threshold[opt_id], polarity[opt_id], opt_id)
......@@ -163,7 +184,7 @@ class LutMachine():
""" The LUT machine consist of the core elements of the LUT weak classfier i.e. the LUT and
the feature index corresponding to the weak classifier. """
def __init__(self, num_outputs, num_entries):
def __init__(self, num_outputs = 0, num_entries = 0):
""" The function initializes the weak LUT machine.
The function initializes the look-up-table and the feature indices of the LUT machine.
......@@ -215,6 +236,18 @@ class LutMachine():
return self.luts[feature[self.selected_indices[0]],0]
def save(self, hdf5File):
"""Saves the current state of this machine to the given HDF5File."""
hdf5File.set("LUT", self.luts)
hdf5File.set("Indices", self.selected_indices)
def load(self, hdf5File):
"""Reads the state of this machine from the given HDF5File."""
self.luts = hdf5File.read("LUT")
self.selected_indices = hdf5File.read("Indices")
print self.selected_indices
class LutTrainer():
""" The LutTrainer class contain methods to learn weak trainer using LookUp Tables.
It can be used for multi-variate binary classification """
......@@ -289,7 +322,7 @@ class LutTrainer():
# indep (independent) feature selection is used if all the dimension of output use different feature
# each of the selected feature minimize a dimension of the loss function
selected_indices = [numpy.argmin(col) for col in numpy.transpose(sum_loss)]
# selected_indices = [numpy.argmin(col) for col in numpy.transpose(sum_loss)]
for output_index in range(self.num_outputs):
curr_id = sum_loss[:,output_index].argmin()
......
import unittest
import random
import xbob.boosting
import numpy
import bob
class TestMachines(unittest.TestCase):
"""Perform test on stump weak trainer"""
def test_stump_machine(self):
# test the stump machine
machine = xbob.boosting.core.trainers.StumpMachine(0, 1, 0)
scores = machine.get_weak_scores(numpy.ones((1,1), dtype=numpy.float64))
self.assertTrue(scores.shape == (1,1))
self.assertEqual(scores[0,0], 1)
score = machine.get_weak_score(numpy.ones((1,), dtype=numpy.float64))
self.assertEqual(scores, 1)
def test_lut_machine(self):
# test the LUT machine
machine = xbob.boosting.core.trainers.LutMachine(1, 1)
print machine.luts
print machine.selected_indices
scores = machine.get_weak_scores(numpy.zeros((1,1), dtype=numpy.uint8))
self.assertTrue(scores.shape == (1,1))
self.assertEqual(scores[0,0], 1)
score = machine.get_weak_score(numpy.zeros((1,), dtype=numpy.uint8))
self.assertEqual(scores, 1)
def test_boosted_machine(self):
# test the boosted machine, by adding two different machine types (doesn't usually make sense, though...)
stump_machine = xbob.boosting.core.trainers.StumpMachine(0, 1, 0)
lut_machine = xbob.boosting.core.trainers.LutMachine(1, 1)
boost_machine = xbob.boosting.core.boosting.BoostMachine()
boost_machine.add_weak_trainer(stump_machine, 1.)
boost_machine.add_weak_trainer(lut_machine, 1.)
# forward some features
scores, labels = boost_machine.classify(numpy.zeros((1,1), dtype=numpy.uint8))
self.assertTrue(scores.shape == (1,1))
self.assertEqual(scores[0,0], 2)
score = boost_machine(numpy.zeros((1,), dtype=numpy.uint8))
self.assertEqual(scores, 2)
# write the machine to file
import tempfile
f = tempfile.mkstemp(prefix = "xbobtest_")[1]
boost_machine.save(bob.io.HDF5File(f, 'w'))
new_machine = xbob.boosting.core.boosting.BoostMachine()
new_machine.load(bob.io.HDF5File(f))
self.assertTrue((new_machine.alpha == 1).all())
# forward some features with the new machine
scores, labels = new_machine.classify(numpy.zeros((1,1), dtype=numpy.uint8))
self.assertTrue(scores.shape == (1,1))
self.assertEqual(scores[0,0], 2)
score = new_machine(numpy.zeros((1,), dtype=numpy.uint8))
self.assertEqual(scores, 2)
Supports Markdown
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