iCub-main
LSSVMLearner.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2011 RobotCub Consortium, European Commission FP6 Project IST-004370
3  * author: Arjan Gijsberts
4  * email: arjan.gijsberts@iit.it
5  * website: www.robotcub.org
6  * Permission is granted to copy, distribute, and/or modify this program
7  * under the terms of the GNU General Public License, version 2 or any
8  * later version published by the Free Software Foundation.
9  *
10  * A copy of the license can be found at
11  * http://www.robotcub.org/icub/license/gpl.txt
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details
17  */
18 
19 #include <cassert>
20 #include <sstream>
21 #include <cmath>
22 
23 #include <yarp/math/Math.h>
24 #include <yarp/math/SVD.h>
25 
28 
29 using namespace yarp::math;
31 
32 namespace iCub {
33 namespace learningmachine {
34 
35 double RBFKernel::evaluate(const yarp::sig::Vector& v1, const yarp::sig::Vector& v2) {
36  assert(v1.size() == v2.size());
37  double result = 0.0;
38  double diff;
39 
40  for(size_t i = 0; i < v1.size(); i++) {
41  diff = v1(i) - v2(i);
42  result += diff * diff;
43  }
44  result *= -1 * this->gamma;
45  return std::exp(result);
46 }
47 
48 
49 LSSVMLearner::LSSVMLearner(unsigned int dom, unsigned int cod, double c) {
50  this->setName("LSSVM");
51  this->kernel = new RBFKernel();
52  // make sure to not use initialization list to constructor of base for
53  // domain and codomain size, as it will not use overloaded mutators
54  this->setDomainSize(dom);
55  this->setCoDomainSize(cod);
56  this->setC(c);
57 }
58 
59 LSSVMLearner::LSSVMLearner(const LSSVMLearner& other)
60  : IFixedSizeLearner(other), inputs(other.inputs), outputs(other.outputs),
61  alphas(other.alphas), bias(other.bias), LOO(other.LOO), C(other.C),
62  kernel(new RBFKernel(*other.kernel)) {
63 
64 }
65 
67  delete this->kernel;
68 }
69 
71  if(this == &other) return *this; // handle self initialization
72 
73  this->IFixedSizeLearner::operator=(other);
74  this->inputs = other.inputs;
75  this->outputs = other.outputs;
76  this->alphas = other.alphas;
77  this->bias = other.bias;
78  this->LOO = other.LOO;
79  this->C = other.C;
80  delete this->kernel;
81  this->kernel = new RBFKernel(*other.kernel);
82 
83  return *this;
84 }
85 
86 void LSSVMLearner::feedSample(const yarp::sig::Vector& input, const yarp::sig::Vector& output) {
87  // call parent method to let it do some validation for us
88  this->IFixedSizeLearner::feedSample(input, output);
89 
90  this->inputs.push_back(input);
91  this->outputs.push_back(output);
92 }
93 
95  assert(this->inputs.size() == this->outputs.size());
96 
97  // save wasting some time
98  if(inputs.size() == 0) {
99  return;
100  }
101 
102  // create kernel matrix
103  yarp::sig::Matrix K(inputs.size() + 1, inputs.size() + 1);
104  for(int r = 0; r < K.rows() - 1; r++) {
105  // symmetric matrix
106  for(int c = 0; c <= r; c++) {
107  K(r, c) = K(c, r) = this->kernel->evaluate(this->inputs[r], this->inputs[c]);
108  if(r == c) K(r, c) += (1.0 / this->C);
109  }
110  }
111  for(int i = 0; i < K.rows() - 1; i++) {
112  K(i, K.cols() - 1) = K(K.rows() - 1, i) = 1.;
113  }
114  K(K.rows() - 1, K.cols() - 1) = 0.;
115 
116  // invert kernel matrix
117  yarp::sig::Matrix Kinv = luinv(K);
118 
119  // compute solution
120  yarp::sig::Matrix Y = zeros(this->outputs.size() + 1, this->getCoDomainSize());
121  for(int r = 0; r < Y.rows() - 1; r++) {
122  for(int c = 0; c < Y.cols(); c++) {
123  Y(r, c) = this->outputs[r](c);
124  }
125  }
126 
127  yarp::sig::Matrix result = Kinv * Y;
128  this->alphas = result.submatrix(0, result.rows() - 2, 0, result.cols() - 1);
129  this->bias = result.getRow(result.rows() - 1);
130 
131  // compute LOO
132  this->LOO = zeros(this->getCoDomainSize());
133 
134  for(unsigned int i = 0; i < this->getCoDomainSize(); i++) {
135  yarp::sig::Vector alphas_i = this->alphas.getCol(i);
136  for(size_t j = 0; j < alphas_i.size(); j++) {
137  double err = alphas_i(j) / Kinv(j, j);
138  this->LOO(i) += err * err;
139  }
140  this->LOO(i) /= alphas_i.size();
141  }
142 
143 }
144 
145 Prediction LSSVMLearner::predict(const yarp::sig::Vector& input) {
146  this->checkDomainSize(input);
147 
148  if(this->inputs.size() == 0) {
149  return zeros(this->getCoDomainSize());
150  }
151 
152  // compute kernel expansion
153  yarp::sig::Vector k(this->inputs.size());
154  for(size_t i = 0; i < k.size(); i++) {
155  k(i) = this->kernel->evaluate(this->inputs[i], input);
156  }
157 
158  return Prediction((this->alphas.transposed() * k) + this->bias);
159 }
160 
162  this->inputs.clear();
163  this->outputs.clear();
164  this->alphas = yarp::sig::Matrix();
165  this->LOO.clear();
166  this->bias.clear();
167 }
168 
170  return new LSSVMLearner(*this);
171 }
172 
174  std::ostringstream buffer;
175  buffer << this->IFixedSizeLearner::getInfo();
176  buffer << "C: " << this->getC() << " | ";
177  buffer << "Collected Samples: " << this->inputs.size() << " | ";
178  buffer << "Training Samples: " << this->alphas.rows() << " | ";
179  buffer << "Kernel: " << this->kernel->getInfo() << std::endl;
180  buffer << "LOO: " << this->LOO.toString() << std::endl;
181  return buffer.str();
182 }
183 
185  std::ostringstream buffer;
186  buffer << this->IFixedSizeLearner::getConfigHelp();
187  //buffer << " kernel idx|all cfg Kernel configuration" << std::endl;
188  buffer << " c val Tradeoff parameter C" << std::endl;
189  buffer << this->kernel->getConfigHelp() << std::endl;
190  return buffer.str();
191 }
192 
193 void LSSVMLearner::writeBottle(yarp::os::Bottle& bot) {
194  // write kernel gamma
195  bot << this->kernel->getGamma() << this->getC() << this->bias
196  << this->alphas;
197 
198  // write inputs
199  for(unsigned int i = 0; i < this->inputs.size(); i++) {
200  for(unsigned int d = 0; d < this->getDomainSize(); d++) {
201  bot.addFloat64(this->inputs[i](d));
202  }
203  }
204  bot.addInt32(this->inputs.size());
205 
206  // write outputs
207  for(unsigned int i = 0; i < this->outputs.size(); i++) {
208  for(unsigned int d = 0; d < this->getCoDomainSize(); d++) {
209  bot.addFloat64(this->outputs[i](d));
210  }
211  }
212  bot.addInt32(this->outputs.size());
213 
214  // make sure to call the superclass's method
216 }
217 
218 void LSSVMLearner::readBottle(yarp::os::Bottle& bot) {
219  // make sure to call the superclass's method
221 
222  // read outputs
223  this->outputs.resize(bot.pop().asInt32());
224  for(int i = this->outputs.size() - 1; i >= 0; i--) {
225  this->outputs[i].resize(this->getCoDomainSize());
226  for(int d = this->getCoDomainSize() - 1; d >= 0; d--) {
227  this->outputs[i](d) = bot.pop().asFloat64();
228  }
229  }
230 
231  // read inputs
232  this->inputs.resize(bot.pop().asInt32());
233  for(int i = this->inputs.size() - 1; i >= 0; i--) {
234  this->inputs[i].resize(this->getDomainSize());
235  for(int d = this->getDomainSize() - 1; d >= 0; d--) {
236  this->inputs[i](d) = bot.pop().asFloat64();
237  }
238  }
239 
240  double c;
241  double gamma;
242  bot >> this->alphas >> this->bias >> c >> gamma;
243  this->setC(c);
244  this->kernel->setGamma(gamma);
245 }
246 
247 void LSSVMLearner::setDomainSize(unsigned int size) {
249 }
250 
251 void LSSVMLearner::setCoDomainSize(unsigned int size) {
253  //this->initAll(this->getCoDomainSize());
254 }
255 
256 bool LSSVMLearner::configure(yarp::os::Searchable& config) {
257  bool success = this->IFixedSizeLearner::configure(config);
258 
259  // format: set c dbl
260  if(config.find("c").isFloat64() || config.find("c").isInt32()) {
261  double val = config.find("c").asFloat64();
262  if(val > 0) {
263  this->setC(config.find("c").asFloat64());
264  success = true;
265  }
266  }
267 
268  success |= this->kernel->configure(config);
269 
270  return success;
271 }
272 
273 } // learningmachine
274 } // iCub
275 
276 
iCub::learningmachine::RBFKernel::configure
virtual bool configure(yarp::os::Searchable &config)
Definition: LSSVMLearner.h:82
iCub::learningmachine::serialization
Definition: Serialization.h:28
iCub
This file contains the definition of unique IDs for the body parts and the skin parts of the robot.
Definition: emotionInterface.h:17
iCub::learningmachine::IFixedSizeLearner::getDomainSize
unsigned int getDomainSize() const
Returns the size (dimensionality) of the input domain.
Definition: IFixedSizeLearner.h:115
iCub::learningmachine::LSSVMLearner::~LSSVMLearner
virtual ~LSSVMLearner()
Destructor.
Definition: LSSVMLearner.cpp:66
iCub::learningmachine::LSSVMLearner::operator=
virtual LSSVMLearner & operator=(const LSSVMLearner &other)
Assignment operator.
Definition: LSSVMLearner.cpp:70
iCub::learningmachine::LSSVMLearner::getC
virtual double getC()
Accessor for the regularization parameter C.
Definition: LSSVMLearner.h:258
iCub::learningmachine::LSSVMLearner::feedSample
virtual void feedSample(const yarp::sig::Vector &input, const yarp::sig::Vector &output)
Provide the learning machine with an example of the desired mapping.
Definition: LSSVMLearner.cpp:86
iCub::learningmachine::IFixedSizeLearner::writeBottle
virtual void writeBottle(yarp::os::Bottle &bot) const
Writes a serialization of the machine into a bottle.
Definition: IFixedSizeLearner.cpp:68
LSSVMLearner.h
iCub::learningmachine::IFixedSizeLearner::setDomainSize
virtual void setDomainSize(unsigned int size)
Mutator for the domain size.
Definition: IFixedSizeLearner.h:129
iCub::learningmachine::IFixedSizeLearner::getCoDomainSize
unsigned int getCoDomainSize() const
Returns the size (dimensionality) of the output domain (codomain).
Definition: IFixedSizeLearner.h:122
iCub::learningmachine::LSSVMLearner::predict
Prediction predict(const yarp::sig::Vector &input)
Ask the learning machine to predict the output for a given input.
Definition: LSSVMLearner.cpp:145
iCub::learningmachine::LSSVMLearner::getConfigHelp
virtual std::string getConfigHelp()
Asks the learning machine to return a string containing the list of configuration options that it sup...
Definition: LSSVMLearner.cpp:184
iCub::learningmachine::LSSVMLearner::setCoDomainSize
void setCoDomainSize(unsigned int size)
Mutator for the codomain size.
Definition: LSSVMLearner.cpp:251
iCub::learningmachine::LSSVMLearner::train
virtual void train()
Train the learning machine on the examples that have been supplied so far.
Definition: LSSVMLearner.cpp:94
iCub::learningmachine::LSSVMLearner::reset
void reset()
Forget everything and start over.
Definition: LSSVMLearner.cpp:161
iCub::learningmachine::LSSVMLearner::writeBottle
virtual void writeBottle(yarp::os::Bottle &bot)
Definition: LSSVMLearner.cpp:193
iCub::learningmachine::IFixedSizeLearner::checkDomainSize
virtual bool checkDomainSize(const yarp::sig::Vector &input)
Checks whether the input is of the desired dimensionality.
Definition: IFixedSizeLearner.cpp:51
iCub::learningmachine::RBFKernel::evaluate
virtual double evaluate(const yarp::sig::Vector &v1, const yarp::sig::Vector &v2)
Definition: LSSVMLearner.cpp:35
iCub::learningmachine::LSSVMLearner::readBottle
virtual void readBottle(yarp::os::Bottle &bot)
Unserializes a machine from a bottle.
Definition: LSSVMLearner.cpp:218
iCub::learningmachine::RBFKernel::setGamma
virtual void setGamma(double g)
Definition: LSSVMLearner.h:71
iCub::learningmachine::LSSVMLearner::setC
virtual void setC(double C)
Mutator for the regularization parameter C.
Definition: LSSVMLearner.h:249
iCub::learningmachine::IFixedSizeLearner::feedSample
virtual void feedSample(const yarp::sig::Vector &input, const yarp::sig::Vector &output)
Provide the learning machine with an example of the desired mapping.
Definition: IFixedSizeLearner.cpp:28
iCub::learningmachine::RBFKernel
Definition: LSSVMLearner.h:60
iCub::learningmachine::IFixedSizeLearner::getInfo
virtual std::string getInfo()
Asks the learning machine to return a string containing information on its operation so far.
Definition: IFixedSizeLearner.cpp:78
Serialization.h
iCub::learningmachine::IFixedSizeLearner::configure
virtual bool configure(yarp::os::Searchable &config)
Definition: IFixedSizeLearner.cpp:35
iCub::learningmachine::LSSVMLearner::LSSVMLearner
LSSVMLearner(unsigned int dom=1, unsigned int cod=1, double c=1.0)
Constructor.
Definition: LSSVMLearner.cpp:49
string
string(REPLACE "-rdynamic" "" CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS}") include_directories($
Definition: CMakeLists.txt:9
iCub::learningmachine::Prediction
Definition: Prediction.h:44
iCub::learningmachine::test::Prediction
PortablePair< Vector, Vector > Prediction
Definition: test.cpp:52
iCub::learningmachine::RBFKernel::getInfo
virtual std::string getInfo()
Definition: LSSVMLearner.h:99
iCub::learningmachine::IFixedSizeLearner::setCoDomainSize
virtual void setCoDomainSize(unsigned int size)
Mutator for the codomain size.
Definition: IFixedSizeLearner.h:136
iCub::learningmachine::RBFKernel::getConfigHelp
virtual std::string getConfigHelp()
Definition: LSSVMLearner.h:92
iCub::learningmachine::IFixedSizeLearner
Definition: IFixedSizeLearner.h:44
iCub::learningmachine::LSSVMLearner
Definition: LSSVMLearner.h:121
iCub::learningmachine::LSSVMLearner::configure
virtual bool configure(yarp::os::Searchable &config)
Definition: LSSVMLearner.cpp:256
zeros
zeros(2, 2) eye(2
exp
exp(-x3 *T)]
iCub::learningmachine::IFixedSizeLearner::readBottle
virtual void readBottle(yarp::os::Bottle &bot)
Unserializes a machine from a bottle.
Definition: IFixedSizeLearner.cpp:73
iCub::learningmachine::LSSVMLearner::getInfo
virtual std::string getInfo()
Asks the learning machine to return a string containing information on its operation so far.
Definition: LSSVMLearner.cpp:173
iCub::learningmachine::LSSVMLearner::setDomainSize
void setDomainSize(unsigned int size)
Mutator for the domain size.
Definition: LSSVMLearner.cpp:247
iCub::learningmachine::IFixedSizeLearner::getConfigHelp
virtual std::string getConfigHelp()
Asks the learning machine to return a string containing the list of configuration options that it sup...
Definition: IFixedSizeLearner.cpp:86
iCub::learningmachine::LSSVMLearner::clone
LSSVMLearner * clone()
Asks the learning machine to return a clone of its type.
Definition: LSSVMLearner.cpp:169
iCub::learningmachine::RBFKernel::getGamma
virtual double getGamma()
Definition: LSSVMLearner.h:75