Jelajahi Sumber

CRSplineRegression is now able to handle multi-dimensional data.

Frank Prüfer 11 tahun lalu
induk
melakukan
1672865a40
2 mengubah file dengan 150 tambahan dan 92 penghapusan
  1. TEMPAT SAMPAH
      regression/splineregression/.swp.CRSplineReg.cpp
  2. 150 92
      regression/splineregression/CRSplineReg.cpp

TEMPAT SAMPAH
regression/splineregression/.swp.CRSplineReg.cpp


+ 150 - 92
regression/splineregression/CRSplineReg.cpp

@@ -5,10 +5,14 @@
 * @date 09/03/2013
 
 */  
+#ifdef NICE_USELIB_OPENMP
+#include <omp.h>
+#endif
 
 #include <iostream>
 
 #include "vislearning/regression/splineregression/CRSplineReg.h"
+#include "vislearning/regression/linregression/LinRegression.h"
 
 #include "vislearning/math/mathbase/FullVector.h"
 
@@ -71,109 +75,163 @@ double CRSplineReg::predict ( const NICE::Vector & x )
     fprintf (stderr, "CRSplineReg: please use the train method first\n");
     exit(-1);
   }
+  int dimension = dataSet[0].size();
+  int sortDim = 0;
+
+  FullVector data ( dataSet.size()+1 );
   
-  if ( dataSet[0].size() == 1 ){	//one-dimensional case
-    FullVector data ( dataSet.size()+1 );
-    for ( uint i = 0; i < dataSet.size(); i++ ){
-      data[i] = dataSet[i][0];
-    }
-    cerr<<"data x: "<<x[0]<<endl;
-    data[dataSet.size()] = x[0];
-    
-    std::vector<int> ind;
-    data.getSortedIndices(ind);
-    
-    int index;
-    for ( uint i = 0; i < ind.size(); i++ ){
-      if ( ind[i] == dataSet.size() ){
-	index = i;
-	break;
-      }
-    }
+#pragma omp parallel for  
+  for ( uint i = 0; i < dataSet.size(); i++ ){
+    data[i] = dataSet[i][sortDim];
+  }
+  data[dataSet.size()] = x[sortDim];
     
+  std::vector<int> sortedInd;
+  data.getSortedIndices(sortedInd);
     
-    NICE::Matrix points (4,2,0.0);
-    if ( index >= 2 && index < (ind.size() - 2) ){	//everything is okay
-      points(0,0) = data[ind[index-2]];
-      points(0,1) = labelSet[ind[index-2]];
-      points(1,0) = data[ind[index-1]];
-      points(1,1) = labelSet[ind[index-1]];
-      points(2,0) = data[ind[index+1]];
-      points(2,1) = labelSet[ind[index+1]];
-      points(3,0) = data[ind[index+2]];
-      points(3,1) = labelSet[ind[index+2]];      
-    }
-    else if ( index == 1 ){	//just one point left from x
-      points(0,0) = data[ind[index-1]];
-      points(0,1) = labelSet[ind[index-1]];
-      points(1,0) = data[ind[index-1]];
-      points(1,1) = labelSet[ind[index-1]];
-      points(2,0) = data[ind[index+1]];
-      points(2,1) = labelSet[ind[index+1]];
-      points(3,0) = data[ind[index+2]];
-      points(3,1) = labelSet[ind[index+2]];       
-    }
-    else if ( index == 0 ){	//x is the farthest left point
-      //do linear approximation
+  int index;
+   
+  for ( uint i = 0; i < sortedInd.size(); i++ ){
+    if ( sortedInd[i] == dataSet.size() ){
+      index = i;
+      break;
     }
-    else if ( index == (ind.size() - 2) ){	//just one point right from x
-      points(0,0) = data[ind[index-2]];
-      points(0,1) = labelSet[ind[index-2]];
-      points(1,0) = data[ind[index-1]];
-      points(1,1) = labelSet[ind[index-1]];
-      points(2,0) = data[ind[index+1]];
-      points(2,1) = labelSet[ind[index+1]];
-      points(3,0) = data[ind[index+1]];
-      points(3,1) = labelSet[ind[index+1]];  
-    }
-    else if ( index == (ind.size() - 1) ){	//x is the farthest right point
-      //do linear approximation
-    }
-    
-    double t = (x[0] - points(1,0)) / (points(2,0) - points(1,0));
-    cerr<<"t: "<<t<<endl;
-    
-//     NICE::Vector vecT(4,1.0);
-//     
-//     vecT[1] = t;
-//     vecT[2] = t*t;
-//     vecT[3] = t*t*t;
-//     
-//     Matrix coeffMatrix (4,4,0.0);	// M = (0 2 0 0
-//     coeffMatrix(0,1) = 2.0;		//	-1 0 1 0
-//     coeffMatrix(1,0) = -1.0;		//	2 -5 4 -1
-//     coeffMatrix(1,2) = 1.0;		//	-1 3 -3 1)
-//     coeffMatrix(2,0) = 2.0;
-//     coeffMatrix(2,1) = -5.0;
-//     coeffMatrix(2,2) = 4.0;
-//     coeffMatrix(2,3) = -1.0;
-//     coeffMatrix(3,0) = -1.0;
-//     coeffMatrix(3,1) = 3.0;
-//     coeffMatrix(3,2) = -3.0;
-//     coeffMatrix(3,3) = 1.0;
+  }
+
+  NICE::Matrix points (4,dimension+1,0.0);
+  if ( index >= 2 && index < (sortedInd.size() - 2) ){	//everything is okay
+    points.setRow(0,dataSet[sortedInd[index-2]]);
+    points(0,dimension) = labelSet[sortedInd[index-2]];
+    points.setRow(1,dataSet[sortedInd[index-1]]);
+    points(1,dimension) = labelSet[sortedInd[index-1]];      
+    points.setRow(2,dataSet[sortedInd[index+1]]);
+    points(2,dimension) = labelSet[sortedInd[index+1]];      
+    points.setRow(3,dataSet[sortedInd[index+2]]);
+    points(3,dimension) = labelSet[sortedInd[index+2]];           
+  }
+  else if ( index == 1 ){	//just one point left from x
+    points.setRow(0,dataSet[sortedInd[index-1]]);
+    points(0,dimension) = labelSet[sortedInd[index-1]];
+    points.setRow(1,dataSet[sortedInd[index-1]]);
+    points(1,dimension) = labelSet[sortedInd[index-1]];      
+    points.setRow(2,dataSet[sortedInd[index+1]]);
+    points(2,dimension) = labelSet[sortedInd[index+1]];      
+    points.setRow(3,dataSet[sortedInd[index+2]]);
+    points(3,dimension) = labelSet[sortedInd[index+2]];      
+  }
+  else if ( index == 0 ){	//x is the farthest left point
+    points.setRow(0,dataSet[sortedInd[index+1]]);
+    points(0,dimension) = labelSet[sortedInd[index+1]];
+    points.setRow(1,dataSet[sortedInd[index+1]]);
+    points(1,dimension) = labelSet[sortedInd[index+1]];      
+    points.setRow(2,dataSet[sortedInd[index+1]]);
+    points(2,dimension) = labelSet[sortedInd[index+1]];      
+    points.setRow(3,dataSet[sortedInd[index+2]]);
+    points(3,dimension) = labelSet[sortedInd[index+2]]; 
+  }
+  else if ( index == (sortedInd.size() - 2) ){	//just one point right from x
+    points.setRow(0,dataSet[sortedInd[index-2]]);
+    points(0,dimension) = labelSet[sortedInd[index-2]];
+    points.setRow(1,dataSet[sortedInd[index-1]]);
+    points(1,dimension) = labelSet[sortedInd[index-1]];      
+    points.setRow(2,dataSet[sortedInd[index+1]]);
+    points(2,dimension) = labelSet[sortedInd[index+1]];      
+    points.setRow(3,dataSet[sortedInd[index+1]]);
+    points(3,dimension) = labelSet[sortedInd[index+1]];   
+  }
+  else if ( index == (sortedInd.size() - 1) ){	//x is the farthest right point
+    points.setRow(0,dataSet[sortedInd[index-2]]);
+    points(0,dimension) = labelSet[sortedInd[index-2]];
+    points.setRow(1,dataSet[sortedInd[index-1]]);
+    points(1,dimension) = labelSet[sortedInd[index-1]];      
+    points.setRow(2,dataSet[sortedInd[index-1]]);
+    points(2,dimension) = labelSet[sortedInd[index-1]];      
+    points.setRow(3,dataSet[sortedInd[index-1]]);
+    points(3,dimension) = labelSet[sortedInd[index-1]];     
+  }
+
+//   NICE::Vector P(dimension);
+//   double y;
+//   double diff,bestT;
+//   double bestDiff = std::numeric_limits<double>::max();
+//   double b0,b1,b2,b3;
+// 
+//   for ( double t = 0.0; t <= 1.0; t += 0.02 ){
+//     b0 = tau * (-(t*t*t) + 2*t*t - t);
+//     b1 = tau * (3*t*t*t - 5*t*t + 2);
+//     b2 = tau * (-3*t*t*t + 4*t*t + t);
+//     b3 = tau * (t*t*t - t*t);    
+// 
+// #pragma omp parallel for  
+//     for ( uint i = 0; i < dimension; i++ ){
+//       P[i] = b0*points(0,i) + b1*points(1,i) + b2*points(2,i) + b3*points(3,i);
+//     }
 //     
-//     // P(t) = tau * vecT * coeffMatrix * points;
-//     NICE::Vector P;
-//     NICE::Matrix tmp;
-//     tmp.multiply(coeffMatrix,points);
-//     P.multiply(vecT,tmp);
-//     P *= tau;
+//     diff = (P-x).normL2();
+//     if ( diff < bestDiff ){
+//       bestDiff = diff;
+//       bestT = t;
+//     }
+//   }
+//   b0 = tau * (-(bestT*bestT*bestT) + 2*bestT*bestT - bestT);
+//   b1 = tau * (3*bestT*bestT*bestT - 5*bestT*bestT + 2);
+//   b2 = tau * (-3*bestT*bestT*bestT + 4*bestT*bestT + bestT);
+//   b3 = tau * (bestT*bestT*bestT - bestT*bestT); 
+
+  double t = (x[sortDim]-points(1,sortDim)) / (points(2,sortDim)-points(1,sortDim));
+//   cerr<<"t: "<<t<<endl;
+
+  //P(t) = b0*P0 + b1*P1 + b2*P2 + b3*P3    
+  NICE::Vector P(dimension);
+  double y;
+  double b0,b1,b2,b3;
     
-    //P(t) = b0*P0 + b1*P1 + b2*P2 + b3*P3
-    NICE::Vector P(2);
-    double b0,b1,b2,b3;
+  b0 = tau * (-(t*t*t) + 2*t*t - t);
+  b1 = tau * (3*t*t*t - 5*t*t + 2);
+  b2 = tau * (-3*t*t*t + 4*t*t + t);
+  b3 = tau * (t*t*t - t*t);
+
+#pragma omp parallel for  
+  for ( uint i = 0; i < dimension; i++ ){
+    P[i] = b0*points(0,i) + b1*points(1,i) + b2*points(2,i) + b3*points(3,i);
+  }
+  
+  double diff1 = (P-x).normL2();
+  uint counter = 1;
+  while ( diff1 > 1e-5 && counter <= 21){
+    double tmp = t;;
+    if (tmp > 0.5)
+      tmp = 1 - tmp;
+    t += tmp/counter;
+     
     b0 = tau * (-(t*t*t) + 2*t*t - t);
     b1 = tau * (3*t*t*t - 5*t*t + 2);
     b2 = tau * (-3*t*t*t + 4*t*t + t);
     b3 = tau * (t*t*t - t*t);
+      
+    for ( uint i = 0; i < dimension; i++ ){
+      P[i] = b0*points(0,i) + b1*points(1,i) + b2*points(2,i) + b3*points(3,i);
+    }
     
-    P[0] = b0*points(0,0) + b1*points(1,0) + b2*points(2,0) + b3*points(3,0);
-    P[1] = b0*points(0,1) + b1*points(1,1) + b2*points(2,1) + b3*points(3,1);
-    
-    cerr<<"Response x: "<<P[0]<<endl;
-    cerr<<"Response y: "<<P[1]<<endl;
-    
-    return P[1];  
+    double diff2 = (P-x).normL2();
+    if ( diff2 > diff1 && t > 0) {
+      t -= 2*tmp/counter;    
+	
+      b0 = tau * (-(t*t*t) + 2*t*t - t);
+      b1 = tau * (3*t*t*t - 5*t*t + 2);
+      b2 = tau * (-3*t*t*t + 4*t*t + t);
+      b3 = tau * (t*t*t - t*t);
+
+#pragma omp parallel for      
+      for ( uint i = 0; i < dimension; i++ ){
+	P[i] = b0*points(0,i) + b1*points(1,i) + b2*points(2,i) + b3*points(3,i);
+      }
+      diff1 = (P-x).normL2();
+    }
+    counter++;
   }
   
+  y = b0*points(0,dimension) + b1*points(1,dimension) + b2*points(2,dimension) + b3*points(3,dimension);
+  return y;
+  
 }