123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /**
- * @file CRSplineReg.cpp
- * @brief Implementation of Catmull-Rom-Splines for regression purposes
- * @author Frank Prüfer
- * @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"
- using namespace OBJREC;
- using namespace std;
- using namespace NICE;
- CRSplineReg::CRSplineReg ( const NICE::Config *_conf )
- {
- tau = _conf->gD("CRSplineReg","tau",0.5);
- sortDim = _conf->gI("CRSplineReg","sortDim",0);
- }
- CRSplineReg::CRSplineReg ( uint sDim )
- {
- sortDim = sDim;
- }
- CRSplineReg::CRSplineReg ( const CRSplineReg & src ) : RegressionAlgorithm ( src )
- {
- tau = src.tau;
- dataSet = src.dataSet;
- labelSet = src.labelSet;
- sortDim = src.sortDim;
- }
- CRSplineReg::~CRSplineReg()
- {
- }
- CRSplineReg* CRSplineReg::clone ( void ) const
- {
- return new CRSplineReg(*this);
- }
- void CRSplineReg::teach ( const NICE::VVector & _dataSet, const NICE::Vector & _labelSet)
- {
- fprintf (stderr, "teach using all !\n");
- //NOTE this is crucial if we clear _teachSet afterwards!
- //therefore, take care NOT to call _techSet.clear() somewhere out of this method
- this->dataSet = _dataSet;
- this->labelSet = _labelSet.std_vector();
-
- std::cerr << "number of known training samples: " << this->dataSet.size() << std::endl;
-
- }
- void CRSplineReg::teach ( const NICE::Vector & x, const double & y )
- {
- std::cerr << "CRSplineReg::teach one new example" << std::endl;
-
- for ( size_t i = 0 ; i < x.size() ; i++ )
- if ( isnan(x[i]) )
- {
- fprintf (stderr, "There is a NAN value in within this vector: x[%d] = %f\n", (int)i, x[i]);
- cerr << x << endl;
- exit(-1);
- }
- dataSet.push_back ( x );
-
- labelSet.push_back ( y );
-
- std::cerr << "number of known training samples: " << dataSet.size()<< std::endl;
- }
- double CRSplineReg::predict ( const NICE::Vector & x )
- {
-
- if ( dataSet.size() <= 0 ) {
- fprintf (stderr, "CRSplineReg: please use the train method first\n");
- exit(-1);
- }
- int dimension = dataSet[0].size();
- FullVector data ( dataSet.size()+1 );
-
- #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);
-
- int index;
-
- for ( uint i = 0; i < sortedInd.size(); i++ ){
- if ( sortedInd[i] == (int)dataSet.size() ){
- index = i;
- break;
- }
- }
- NICE::Matrix points (4,dimension+1,0.0);
- if ( index >= 2 && index < (int)(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 == (int)(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 == (int)(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]];
- }
- double t = (x[sortDim]-points(1,sortDim)) / (points(2,sortDim)-points(1,sortDim)); //this is just some kind of heuristic
- if ( t != t || t < 0 || t > 1){ //check if t is NAN, -inf or inf (happens in the farthest right or left case from above)
- t = 0.5;
- }
- //P(t) = b0*P0 + b1*P1 + b2*P2 + b3*P3
- NICE::Vector P(dimension);
- double y;
- 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 < (uint)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){ //adjust t to fit data better
- 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 < (uint)dimension; i++ ){
- P[i] = b0*points(0,i) + b1*points(1,i) + b2*points(2,i) + b3*points(3,i);
- }
-
- 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 < (uint)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;
-
- }
|