iCub-main
Loading...
Searching...
No Matches
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
29using namespace yarp::math;
31
32namespace iCub {
33namespace learningmachine {
34
35double 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
49LSSVMLearner::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
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
86void 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
145Prediction 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
193void 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
218void 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
247void LSSVMLearner::setDomainSize(unsigned int size) {
249}
250
251void LSSVMLearner::setCoDomainSize(unsigned int size) {
253 //this->initAll(this->getCoDomainSize());
254}
255
256bool 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
An generalized interface for a learning machine with a fixed domain and codomain size.
virtual void writeBottle(yarp::os::Bottle &bot) const
Writes a serialization of the machine into a bottle.
virtual void feedSample(const yarp::sig::Vector &input, const yarp::sig::Vector &output)
Provide the learning machine with an example of the desired mapping.
virtual void readBottle(yarp::os::Bottle &bot)
Unserializes a machine from a bottle.
virtual bool checkDomainSize(const yarp::sig::Vector &input)
Checks whether the input is of the desired dimensionality.
unsigned int getCoDomainSize() const
Returns the size (dimensionality) of the output domain (codomain).
virtual std::string getInfo()
Asks the learning machine to return a string containing information on its operation so far.
virtual void setCoDomainSize(unsigned int size)
Mutator for the codomain size.
virtual bool configure(yarp::os::Searchable &config)
Change parameters.
virtual void setDomainSize(unsigned int size)
Mutator for the domain size.
virtual std::string getConfigHelp()
Asks the learning machine to return a string containing the list of configuration options that it sup...
unsigned int getDomainSize() const
Returns the size (dimensionality) of the input domain.
void setName(const std::string &name)
Set the name of this machine learning technique.
This is basic implementation of the LSSVM algorithms.
virtual void feedSample(const yarp::sig::Vector &input, const yarp::sig::Vector &output)
Provide the learning machine with an example of the desired mapping.
virtual void writeBottle(yarp::os::Bottle &bot)
virtual double getC()
Accessor for the regularization parameter C.
void setCoDomainSize(unsigned int size)
Mutator for the codomain size.
void reset()
Forget everything and start over.
void setDomainSize(unsigned int size)
Mutator for the domain size.
virtual void setC(double C)
Mutator for the regularization parameter C.
LSSVMLearner * clone()
Asks the learning machine to return a clone of its type.
Prediction predict(const yarp::sig::Vector &input)
Ask the learning machine to predict the output for a given input.
virtual void train()
Train the learning machine on the examples that have been supplied so far.
virtual void readBottle(yarp::os::Bottle &bot)
Unserializes a machine from a bottle.
LSSVMLearner(unsigned int dom=1, unsigned int cod=1, double c=1.0)
Constructor.
virtual std::string getInfo()
Asks the learning machine to return a string containing information on its operation so far.
virtual LSSVMLearner & operator=(const LSSVMLearner &other)
Assignment operator.
virtual std::string getConfigHelp()
Asks the learning machine to return a string containing the list of configuration options that it sup...
virtual bool configure(yarp::os::Searchable &config)
Change parameters.
A class that represents a prediction result.
Definition Prediction.h:44
virtual std::string getConfigHelp()
virtual std::string getInfo()
virtual void setGamma(double g)
virtual double evaluate(const yarp::sig::Vector &v1, const yarp::sig::Vector &v2)
virtual bool configure(yarp::os::Searchable &config)
zeros(2, 2) eye(2
This file contains the definition of unique IDs for the body parts and the skin parts of the robot.