libcmaes 0.10.2
A C++11 library for stochastic optimization with CMA-ES
Loading...
Searching...
No Matches
rankingsvm.hpp
1
29#ifndef RANKINGSVM_H
30#define RANKINGSVM_H
31
32#include <libcmaes/eo_matrix.h>
33#include <vector>
34#include <limits>
35#include <cstdlib>
36#include <random>
37#include <iostream>
38
43{
44 public:
45 SVMKernel() {};
46 ~SVMKernel() {};
47
48 double K(const dVec &x1, const dVec &x2);
49 void init(const dMat &x) {};
50};
51
55class LinearKernel : public SVMKernel
56{
57public:
59 :SVMKernel()
60 {}
61
62 ~LinearKernel() {}
63
64 double K(const dVec &x1, const dVec &x2) { return x1.transpose()*x2; }
65};
66
70template <int d,int c=1>
71class PolyKernel : public SVMKernel
72{
73public:
75 :SVMKernel()
76 {}
77
78 ~PolyKernel() {}
79
80 double K(const dVec &x1, const dVec &x2) { return pow((x1.transpose()*x2 + c),d); }
81};
82
86class RBFKernel : public SVMKernel
87{
88 public:
89 RBFKernel()
90 :SVMKernel()
91 {}
92
93 ~RBFKernel() {}
94
95 double K(const dVec &x1, const dVec &x2) { return exp(-_gamma*((x1-x2).squaredNorm())); }
96
97 void init(const dMat &x)
98 {
99 double avgdist = 0.0;
100 for (int i=0;i<x.cols();i++)
101 for (int j=i+1;j<x.cols();j++)
102 avgdist += (x.col(i)-x.col(j)).norm();
103 avgdist /= 0.5*(x.cols()*(x.cols()-1.0));
104 double sigma = _sigma_a * std::pow(avgdist,_sigma_pow);
105 _gamma = 1.0/(2.0*sigma*sigma);
106
107 //debug
108 //std::cout << "avgdist=" << avgdist << " / sigma=" << sigma << " / gamma=" << _gamma << std::endl;
109 //debug
110 }
111
112 double _gamma = 1.0;
113 double _sigma_a = 1.0;
114 double _sigma_pow = 1.0;
115};
116
120template<class TKernel=RBFKernel>
122{
123 public:
124 RankingSVM()
125 {
126 _udist = std::uniform_real_distribution<>(0,1);
127 }
128
130 {
131 }
132
142 void train(dMat &x,
143 const int &niter,
144 const dMat &covinv,
145 const dVec &xmean)
146 {
147 //debug
148 //std::cout << "Learning RSVM with niter=" << niter << std::endl;
149 //debug
150
151 // init structures.
152 int nalphas = x.cols()-1;
153 _C = dMat::Constant(nalphas,1,_Cval);
154 for (int i=0;i<nalphas;i++)
155 _C(nalphas-1-i) = _Cval*pow(nalphas-i,2);
156 _dKij = dMat::Zero(nalphas,nalphas);
157 _alpha = dVec::Zero(nalphas);
158
159 if (_encode)
160 encode(x,covinv,xmean);
162 optimize(x,niter);
163
164 //debug
165 //std::cout << "alpha=" << _alpha.transpose() << std::endl;
166 //debug
167 }
168
180 void predict(dVec &fit,
181 dMat &x_test,
182 dMat &x_train,
183 const dMat &covinv,
184 const dVec &xmean)
185 {
186 if (_alpha.size() == 0)
187 return; // model is not yet trained.
188 fit = dVec::Zero(x_test.cols());
189 if (_encode)
190 {
191 encode(x_train,covinv,xmean);
192 encode(x_test,covinv,xmean);
193 }
194#pragma omp parallel for
195 for (int i=0;i<x_test.cols();i++)
196 {
197 dVec Kvals(x_train.cols());
198 for (int j=0;j<x_train.cols();j++)
199 Kvals(j) = _kernel.K(x_test.col(i),x_train.col(j));
200 double curfit = 0.0;
201 for (int j=0;j<x_train.cols()-1;j++)
202 curfit += _alpha(j) * (Kvals(j)-Kvals(j+1));
203 fit(i) = curfit;
204 }
205
206 //debug
207 //std::cout << "fit=" << fit.transpose() << std::endl;
208 //debug
209 }
210
217 void encode(dMat &x,
218 const dMat &covinv,
219 const dVec &xmean)
220 {
221 for (int i=0;i<x.cols();i++)
222 x.col(i) -= xmean;
223 if (covinv.cols() > 1)
224 x = covinv * x;
225 else
226 {
227 for (int i=0;i<x.cols();i++)
228 x.col(i) = covinv.cwiseProduct(x.col(i));
229 }
230 }
231
237 {
238 _kernel.init(x);
239 _K = dMat::Zero(x.cols(),x.cols());
240#pragma omp parallel for
241 for (int i=0;i<_K.rows();i++)
242 for (int j=i;j<_K.cols();j++)
243 _K(i,j)=_K(j,i)=_kernel.K(x.col(i),x.col(j));
244
245 //debug
246 //std::cout << "K=" << _K << std::endl;
247 //debug
248 }
249
255 void optimize(const dMat &x,
256 const int &niter)
257 {
258 // initialization of temporary variables
259 dVec sum_alphas = dVec::Zero(_dKij.cols());
260 dMat div_dKij = dMat::Zero(_dKij.rows(),_dKij.cols());
261#pragma omp parallel
262 {
263#pragma omp for
264 for (int i=0;i<_dKij.rows();i++)
265 {
266 for (int j=0;j<_dKij.cols();j++)
267 {
268 _dKij(i,j) = _K(i,j) - _K(i,j+1) - _K(i+1,j) + _K(i+1,j+1);
269 }
270 double fact = _udist(_rng);
271 _alpha(i) = _C(i) * (0.95 + 0.05*fact);
272 }
273#pragma omp for
274 for (int i=0;i<_dKij.rows();i++)
275 {
276 double sum_alpha = 0.0;
277 for (int j=0;j<_dKij.cols();j++)
278 {
279 sum_alpha += _alpha(j) * _dKij(i,j);
280 div_dKij(i,j) = _dKij(i,j) / _dKij(j,j);
281 }
282 sum_alphas(i) = (_epsilon - sum_alpha) / _dKij(i,i);
283 }
284 }
285
286 // optimize for niter
287 double L=0.0;
288 int i1 = 0;
289 double old_alpha = 0.0, new_alpha = 0.0, delta_alpha = 0.0;
290 for (int i=0;i<niter;i++)
291 {
292 i1 = i % _dKij.cols();
293 old_alpha = _alpha(i1);
294 new_alpha = old_alpha + sum_alphas(i1);
295 new_alpha = std::max(std::min(new_alpha,_C(i1)),0.0);
296 delta_alpha = new_alpha - old_alpha;
297 double dL = delta_alpha * _dKij(i1,i1) * (sum_alphas(i1) - 0.5*delta_alpha + _epsilon);
298 if (dL > 0)
299 {
300 sum_alphas -= delta_alpha * div_dKij.row(i1);
301 _alpha(i1) = new_alpha;
302 }
303 L += dL;
304 }
305 }
306
318 double error(dMat &x_test,
319 dMat &x_train,
320 const dVec &ref_fit,
321 const dMat &covinv,
322 const dVec &xmean)
323 {
324 dVec fit;
325 predict(fit,x_test,x_train,covinv,xmean);
326 if (fit.size() == 0)
327 return 1.0;
328 double err = 0.0;
329 double sum = 0.0;
330 for (int i=0;i<ref_fit.size();i++)
331 {
332 for (int j=0;j<ref_fit.size();j++)
333 {
334 if (i != j)
335 {
336 err += ((ref_fit(i) > ref_fit(j) && fit(i) < fit(j)) || (ref_fit(i) < ref_fit(j) && fit(i) > fit(j))) ? 1 : 0;
337 sum++;
338 }
339 }
340 }
341 err /= static_cast<double>((ref_fit.size()*ref_fit.size())-ref_fit.size());
342 return err;
343 }
344
345 public:
346 bool _encode = false;
348 dMat _K;
349 dVec _alpha;
350 dMat _dKij;
351 dMat _C;
352 double _Cval = 1e6;
353 double _epsilon = 1.0;
354
355 TKernel _kernel;
357 std::mt19937 _rng;
358 std::uniform_real_distribution<> _udist;
359};
360
361#endif
linear kernel
Definition rankingsvm.hpp:56
Polynomial kernel.
Definition rankingsvm.hpp:72
Radial Basis Function kernel.
Definition rankingsvm.hpp:87
Ranking SVM algorithm with support for custom kernels.
Definition rankingsvm.hpp:122
double _Cval
Definition rankingsvm.hpp:352
TKernel _kernel
Definition rankingsvm.hpp:355
double error(dMat &x_test, dMat &x_train, const dVec &ref_fit, const dMat &covinv, const dVec &xmean)
computes the ranker's error over a dataset
Definition rankingsvm.hpp:318
void train(dMat &x, const int &niter, const dMat &covinv, const dVec &xmean)
trains a ranker from a set of points
Definition rankingsvm.hpp:142
void predict(dVec &fit, dMat &x_test, dMat &x_train, const dMat &covinv, const dVec &xmean)
predicts a ranking from a learnt ranker
Definition rankingsvm.hpp:180
void compute_training_kernel(dMat &x)
pre-computation of the kernel values for every examples and coordinates
Definition rankingsvm.hpp:236
dMat _C
Definition rankingsvm.hpp:351
dMat _K
Definition rankingsvm.hpp:348
void optimize(const dMat &x, const int &niter)
optimizes a ranker's model given a training set x
Definition rankingsvm.hpp:255
dVec _alpha
Definition rankingsvm.hpp:349
void encode(dMat &x, const dMat &covinv, const dVec &xmean)
encoding a set of point in a transformed space
Definition rankingsvm.hpp:217
bool _encode
Definition rankingsvm.hpp:346
Kernel base class.
Definition rankingsvm.hpp:43