00001 #include "GKWGenerator.h"
00002 #include <cmath>
00003 #include "L2Distance.h"
00004
00005 namespace damina
00006 {
00007
00015 GKWGenerator::GKWGenerator(SVClustering *svc, double eps) {
00016 this->svc = svc;
00017 this->eucDist = new L2Distance();
00018 this->runs = 0;
00019 this->eps = eps;
00020 this->softening = 1;
00021
00022 this->initialKW = initialKernelWidth();
00023
00031 this->oldRadius = 0;
00032 this->oldKW = 0;
00033 }
00034
00043 GKWGenerator::GKWGenerator(SVClustering *svc, double eps, double initialKW) {
00044 this->svc = svc;
00045 this->eucDist = new L2Distance();
00046 this->runs = 0;
00047 this->eps = eps;
00048 this->softening = 1;
00049
00050 this->initialKW = initialKW;
00051
00059 this->oldRadius = 0;
00060 this->oldKW = 0;
00061 }
00062
00066 GKWGenerator::~GKWGenerator() {
00067 delete eucDist;
00068 }
00069
00070
00071
00072
00076 void GKWGenerator::reset() {
00077 this->runs = 0;
00078
00086 this->oldRadius = 0;
00087 this->oldKW = 0;
00088 }
00089
00100 double GKWGenerator::getNextKernelWidthValue() {
00101 if (runs == 0) {
00102 newKW = initialKW;
00103 runs++;
00104 return newKW;
00105 }
00106
00107 newRadius = svc->getSphereRadius();
00108
00109 double x_diff;
00110 double radiusDiff = newRadius - oldRadius;
00111 double kwDiff = newKW - oldKW;
00112
00113
00114
00115
00116 if (((double)(radiusDiff / kwDiff) < this->eps) || (svc->getProblem()->l == svc->getModel()->l)) {
00117 return -1;
00118 }
00119
00120
00121 if ((newRadius >= 1) || (newRadius < 0.5)) {
00122 if (x_max_1 == NULL) {
00123 maxDistance();
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 x_diff = kernelfunction(x_max_1, x_max_2, svc->getModel()->param);
00133 newRadius = (1 - x_diff) / 2;
00134
00135
00136 }
00137 else {
00138 while (newRadius <= oldRadius) {
00139 forceMonotonicity();
00140 }
00141 }
00142
00143 double q,y;
00144
00145 intersectLines(oldKW, oldRadius, newKW, newRadius, 0, 1 - (1/svc->getProblem()->l), 1, 1 - (1/svc->getProblem()->l), q, y);
00146
00147 oldKW = newKW;
00148 newKW = q * softening;
00149
00150 oldRadius = newRadius;
00151
00152 runs++;
00153
00154 return newKW;
00155 }
00156
00157
00163 void GKWGenerator::setGrowthSoftening(double s) {
00164 this->softening = s;
00165 }
00166
00172 double GKWGenerator::getGrowthSoftening() {
00173 return softening;
00174 }
00175
00176
00182 void GKWGenerator::setEuclideanDistance(EuclideanDistance *ed) {
00183 eucDist = ed;
00184 }
00185
00186
00187
00192 void GKWGenerator::forceMonotonicity() {
00193 newKW += eps / eps;
00194 svc->setKernelWidth(newKW);
00195 svc->learn();
00196 newRadius = svc->getSphereRadius();
00197 }
00198
00208 void GKWGenerator::intersectLines(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, double &xi,double &yi) {
00209
00210
00211
00212
00213
00214
00215
00216 double a1,b1,c1,
00217 a2,b2,c2,
00218 det_inv,
00219 m1,m2;
00220
00221
00222
00223
00224 if ((x1-x0)!=0)
00225 m1 = (y1-y0)/(x1-x0);
00226 else
00227 m1 = (double)1e+10;
00228
00229 if ((x3-x2)!=0)
00230 m2 = (y3-y2)/(x3-x2);
00231 else
00232 m2 = (double)1e+10;
00233
00234
00235
00236 a1 = m1;
00237 a2 = m2;
00238
00239 b1 = -1;
00240 b2 = -1;
00241
00242 c1 = (y0-m1*x0);
00243 c2 = (y2-m2*x2);
00244
00245
00246
00247 det_inv = 1/(a1*b2 - a2*b1);
00248
00249
00250
00251 xi = ((b1*c2 - b2*c1)*det_inv);
00252 yi = ((a2*c1 - a1*c2)*det_inv);
00253
00254 }
00255
00256
00264 double GKWGenerator::maxDistance() {
00265 struct svm_problem *p = svc->getProblem();
00266 int N = p->l;
00267
00268 double max = eucDist->calculateDistance(p->x[0], p->x[1]);
00269 double dist;
00270
00271 for (int i = 0; i < N; i++) {
00272 for (int j = 0; j < N; j++) {
00273 dist = eucDist->calculateDistance(p->x[i], p->x[j]);
00274 if (dist > max) {
00275 max = dist;
00276 x_max_1 = p->x[i];
00277 x_max_2 = p->x[j];
00278 }
00279 }
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 return max;
00297 }
00298
00311 double GKWGenerator::initialKernelWidth() {
00312 double initial = 1 / maxDistance();
00313 svc->setKernelWidth(initial);
00314 return (initial);
00315 }
00316
00317 }