GKWGenerator.cpp

Go to the documentation of this file.
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         /*      PUBLIC METHODS FOLLOW   ******************************************************************************/
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                 // if the line for the two points (newKW, newRadius) and (oldKW, oldRadius) has a slope close to zero
00114                 // or the number of SV became equal to the number of total points
00115                 // stop the 'q' generation process  
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();  //      also find the two farthest points each other
00124                         }
00125 
00126                         /* applying Corollary 4.1.10 in 
00127              *
00128                          * S. Lee and K. M. Daniels, "Gaussian Kernel Width Selection and Fast Cluster Labeling for 
00129              * Support Vector Clustering," Department of Computer Science, University of Massachussets Lowell, 2005.
00130              *
00131                          * */
00132                         x_diff = kernelfunction(x_max_1, x_max_2, svc->getModel()->param);
00133                         newRadius = (1 - x_diff) / 2;
00134                         //oldRadius = 0;
00135                         //oldKW = 0;
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         /*      PRIVATE METHODS FOLLOW  ******************************************************************************/
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                 // this function computes the intersection of the sent lines
00211                 // and returns the intersection point, note that the function assumes
00212                 // the lines intersect. the function can handle vertical as well
00213                 // as horizontal lines. note the function isn't very clever, it simply
00214                 // applies the math
00215                 
00216                 double a1,b1,c1, // constants of linear equations
00217                       a2,b2,c2,
00218                       det_inv,  // the inverse of the determinant of the coefficient matrix
00219                       m1,m2;    // the slopes of each line
00220                 
00221                 // compute slopes, note the cludge for infinity, however, this will
00222                 // be close enough
00223                 
00224                 if ((x1-x0)!=0)
00225                    m1 = (y1-y0)/(x1-x0);
00226                 else
00227                    m1 = (double)1e+10;   // close enough to infinity
00228                 
00229                 if ((x3-x2)!=0)
00230                    m2 = (y3-y2)/(x3-x2);
00231                 else
00232                    m2 = (double)1e+10;   // close enough to infinity
00233                 
00234                 // compute constants
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                 // compute the inverse of the determinate
00246                 
00247                 det_inv = 1/(a1*b2 - a2*b1);
00248                 
00249                 // use Kramers rule to compute xi and yi
00250                 
00251                 xi = ((b1*c2 - b2*c1)*det_inv);
00252                 yi = ((a2*c1 - a1*c2)*det_inv);
00253         
00254         } // end 
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                 /*double max = 2 - 2 * kernelfunction(p->x[0], p->x[1], *(svc->getParameters()));
00283                 double dist;
00284 
00285                 for (int i = 0; i < N; i++) {
00286                         for (int j = 0; j < N; j++) {
00287                                 dist = 2 - 2 * kernelfunction(p->x[i], p->x[j], *(svc->getParameters()));
00288                                 if (dist > max) {
00289                                         max = dist;
00290                                         x_max_1 = p->x[i];
00291                                         x_max_2 = p->x[j];
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 }

Generated on Mon Sep 24 22:26:48 2007 for SVClustering by  doxygen 1.5.2