AlphaReal SingleStumpLearner::run( int colIdx ) { const int numClasses = _pTrainingData->getNumClasses(); const int numColumns = _pTrainingData->getNumAttributes(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( 1.0 / (AlphaReal)_pTrainingData->getNumExamples() * 0.01 ); vector<sRates> mu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<AlphaReal> tmpV(numClasses); // The class-wise votes/abstentions AlphaReal tmpAlpha; AlphaReal bestEnergy = numeric_limits<AlphaReal>::max(); StumpAlgorithm<FeatureReal> sAlgo(numClasses); sAlgo.initSearchLoop(_pTrainingData); AlphaReal halfTheta; if ( _abstention == ABST_REAL || _abstention == ABST_CLASSWISE ) halfTheta = _theta/2.0; else halfTheta = 0; int numOfDimensions = _maxNumOfDimensions; const pair<vpIterator,vpIterator> dataBeginEnd = static_cast<SortedData*>(_pTrainingData)->getFileteredBeginEnd( colIdx ); const vpIterator dataBegin = dataBeginEnd.first; const vpIterator dataEnd = dataBeginEnd.second; // also sets mu, tmpV, and bestHalfEdge _threshold = sAlgo.findSingleThresholdWithInit(dataBegin, dataEnd, _pTrainingData, halfTheta, &mu, &tmpV); bestEnergy = getEnergy(mu, tmpAlpha, tmpV); _alpha = tmpAlpha; _v = tmpV; _selectedColumn = colIdx; if ( _selectedColumn != -1 ) { stringstream thresholdString; thresholdString << _threshold; _id = _pTrainingData->getAttributeNameMap().getNameFromIdx(_selectedColumn) + thresholdString.str(); } else { bestEnergy = numeric_limits<float>::signaling_NaN(); } return bestEnergy; }
AlphaReal ConstantLearner::run() { const int numClasses = _pTrainingData->getNumClasses(); //const int numColumns = _pTrainingData->getNumColumns(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( 1.0 / (AlphaReal)_pTrainingData->getNumExamples() * 0.01 ); vector<sRates> mu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<AlphaReal> tmpV(numClasses); // The class-wise votes/abstentions ConstantAlgorithm cAlgo; cAlgo.findConstant(_pTrainingData,&mu,&tmpV); _v = tmpV; return getEnergy(mu, _alpha, _v); }
AlphaReal MultiThresholdStumpLearner::run() { const int numClasses = _pTrainingData->getNumClasses(); const int numColumns = _pTrainingData->getNumAttributes(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal(1.0 / (AlphaReal) _pTrainingData->getNumExamples() * 0.01); vector<sRates> mu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<AlphaReal> tmpV(numClasses); // The class-wise votes/abstentions vector<FeatureReal> tmpThresholds(numClasses); AlphaReal tmpAlpha; AlphaReal bestEnergy = numeric_limits<AlphaReal>::max(); AlphaReal tmpEnergy; StumpAlgorithm<FeatureReal> sAlgo(numClasses); sAlgo.initSearchLoop(_pTrainingData); int numOfDimensions = _maxNumOfDimensions; for (int j = 0; j < numColumns; ++j) { // Tricky way to select numOfDimensions columns randomly out of numColumns int rest = numColumns - j; float r = rand() / static_cast<float> (RAND_MAX); if (static_cast<float> (numOfDimensions) / rest > r) { --numOfDimensions; const pair<vpIterator, vpIterator> dataBeginEnd = static_cast<SortedData*> (_pTrainingData)->getFileteredBeginEnd( j); const vpIterator dataBegin = dataBeginEnd.first; const vpIterator dataEnd = dataBeginEnd.second; sAlgo.findMultiThresholdsWithInit(dataBegin, dataEnd, _pTrainingData, tmpThresholds, &mu, &tmpV); tmpEnergy = getEnergy(mu, tmpAlpha, tmpV); if (tmpEnergy < bestEnergy && tmpAlpha > 0) { // Store it in the current algorithm // note: I don't really like having so many temp variables // but the alternative would be a structure, which would need // to be inheritable to make things more consistent. But this would // make it less flexible. Therefore, I am still undecided. This // might change! _alpha = tmpAlpha; _v = tmpV; _selectedColumn = j; _thresholds = tmpThresholds; bestEnergy = tmpEnergy; } } } return bestEnergy; }
float UCBVHaarSingleStumpLearner::run() { if ( UCBVHaarSingleStumpLearner::_numOfCalling == 0 ) { init(); } UCBVHaarSingleStumpLearner::_numOfCalling++; //cout << "Num of iter:\t" << UCBVHaarSingleStumpLearner::_numOfCalling << " " << this->getTthSeriesElement( UCBVHaarSingleStumpLearner::_numOfCalling ) << flush << endl; const int numClasses = _pTrainingData->getNumClasses(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( 1.0 / (float)_pTrainingData->getNumExamples() * 0.01 ); vector<sRates> mu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<float> tmpV(numClasses); // The class-wise votes/abstentions float tmpThreshold; float tmpAlpha; float bestEnergy = numeric_limits<float>::max(); float tmpEnergy; HaarData* pHaarData = static_cast<HaarData*>(_pTrainingData); // get the whole data matrix //const vector<int*>& intImages = pHaarData->getIntImageVector(); // The data matrix transformed into the feature's space vector< pair<int, float> > processedHaarData(_pTrainingData->getNumExamples()); // I need to prepare both type of sampling StumpAlgorithm<float> sAlgo(numClasses); sAlgo.initSearchLoop(_pTrainingData); float halfTheta; if ( _abstention == ABST_REAL || _abstention == ABST_CLASSWISE ) halfTheta = _theta/2.0; else halfTheta = 0; // The declared features types vector<HaarFeature*>& loadedFeatures = pHaarData->getLoadedFeatures(); // for every feature type vector<HaarFeature*>::iterator ftIt; //vector<HaarFeature*>::iterator maxftIt; vector<float> maxV( loadedFeatures.size() ); vector<int> maxKey( loadedFeatures.size() ); vector<int> maxNum( loadedFeatures.size() ); //claculate the Bk,s,t of the randomly chosen features int key = getKeyOfMaximalElement(); int featureIdx = (int) (key / 10); int featureType = (key % 10); //for (i = 0, ftIt = loadedFeatures.begin(); ftIt != loadedFeatures.end(); i++ ++ftIt) //*ftIt = loadedFeatures[ featureType ]; // just for readability //HaarFeature* pCurrFeature = *ftIt; HaarFeature* pCurrFeature = loadedFeatures[ featureType ]; if (_samplingType != ST_NO_SAMPLING) pCurrFeature->setAccessType(AT_RANDOM_SAMPLING); // Reset the iterator on the configurations. For random sampling // this clear the visited list pCurrFeature->loadConfigByNum( featureIdx ); if (_verbose > 1) cout << "Learning type " << pCurrFeature->getName() << ".." << flush; // transform the data from intImages to the feature's space pCurrFeature->fillHaarData( _pTrainingData->getExamples(), processedHaarData ); //pCurrFeature->fillHaarData(intImages, processedHaarData); // sort the examples in the new space by their coordinate sort( processedHaarData.begin(), processedHaarData.end(), nor_utils::comparePair<2, int, float, less<float> >() ); // find the optimal threshold tmpThreshold = sAlgo.findSingleThresholdWithInit(processedHaarData.begin(), processedHaarData.end(), _pTrainingData, halfTheta, &mu, &tmpV); tmpEnergy = getEnergy(mu, tmpAlpha, tmpV); // Store it in the current weak hypothesis. // note: I don't really like having so many temp variables // but the alternative would be a structure, which would need // to be inheritable to make things more consistent. But this would // make it less flexible. Therefore, I am still undecided. This // might change! _alpha = tmpAlpha; _v = tmpV; // I need to save the configuration because it changes within the object _selectedConfig = pCurrFeature->getCurrentConfig(); // I save the object because it contains the informations about the type, // the name, etc.. _pSelectedFeature = pCurrFeature; _threshold = tmpThreshold; bestEnergy = tmpEnergy; float edge = 0.0; for( vector<sRates>::iterator itR = mu.begin(); itR != mu.end(); itR++ ) edge += ( itR->rPls - itR->rMin ); //need to set the X value updateKeys( key, edge * edge ); if (!_pSelectedFeature) { cerr << "ERROR: No Haar Feature found. Something must be wrong!" << endl; exit(1); } else { if (_verbose > 1) cout << "Selected type: " << _pSelectedFeature->getName() << endl; } return bestEnergy; }
AlphaReal SingleStumpLearner::run() { const int numClasses = _pTrainingData->getNumClasses(); const int numColumns = _pTrainingData->getNumAttributes(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( 1.0 / (AlphaReal)_pTrainingData->getNumExamples() * 0.01 ); vector<sRates> mu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<AlphaReal> tmpV(numClasses); // The class-wise votes/abstentions FeatureReal tmpThreshold; AlphaReal tmpAlpha; AlphaReal bestEnergy = numeric_limits<AlphaReal>::max(); AlphaReal tmpEnergy; StumpAlgorithm<FeatureReal> sAlgo(numClasses); sAlgo.initSearchLoop(_pTrainingData); AlphaReal halfTheta; if ( _abstention == ABST_REAL || _abstention == ABST_CLASSWISE ) halfTheta = _theta/2.0; else halfTheta = 0; int numOfDimensions = _maxNumOfDimensions; for (int j = 0; j < numColumns; ++j) { // Tricky way to select numOfDimensions columns randomly out of numColumns int rest = numColumns - j; float r = rand()/static_cast<float>(RAND_MAX); if ( static_cast<float>(numOfDimensions) / rest > r ) { --numOfDimensions; //if ( static_cast<SortedData*>(_pTrainingData)->isAttributeEmpty( j ) ) continue; const pair<vpIterator,vpIterator> dataBeginEnd = static_cast<SortedData*>(_pTrainingData)->getFileteredBeginEnd(j); const vpIterator dataBegin = dataBeginEnd.first; const vpIterator dataEnd = dataBeginEnd.second; // also sets mu, tmpV, and bestHalfEdge tmpThreshold = sAlgo.findSingleThresholdWithInit(dataBegin, dataEnd, _pTrainingData, halfTheta, &mu, &tmpV); if (tmpThreshold == tmpThreshold) // tricky way to test Nan { // small inconsistency compared to the standard algo (but a good // trade-off): in findThreshold we maximize the edge (suboptimal but // fast) but here (among dimensions) we minimize the energy. tmpEnergy = getEnergy(mu, tmpAlpha, tmpV); if (tmpEnergy < bestEnergy && tmpAlpha > 0) { // Store it in the current weak hypothesis. // note: I don't really like having so many temp variables // but the alternative would be a structure, which would need // to be inheritable to make things more consistent. But this would // make it less flexible. Therefore, I am still undecided. This // might change! _alpha = tmpAlpha; _v = tmpV; _selectedColumn = j; _threshold = tmpThreshold; bestEnergy = tmpEnergy; } } // tmpThreshold == tmpThreshold } } if ( _selectedColumn != -1 ) { stringstream thresholdString; thresholdString << _threshold; _id = _pTrainingData->getAttributeNameMap().getNameFromIdx(_selectedColumn) + thresholdString.str(); } else { bestEnergy = numeric_limits<AlphaReal>::signaling_NaN(); } return bestEnergy; }
AlphaReal SigmoidSingleStumpLearner::run() { const int numClasses = _pTrainingData->getNumClasses(); const int numColumns = _pTrainingData->getNumAttributes(); const int numExamples = _pTrainingData->getNumExamples(); FeatureReal bestEdge = -numeric_limits<FeatureReal>::max(); vector<AlphaReal> bestv(numClasses); _v.resize(numClasses); AlphaReal gammat = _initialGammat; if (_verbose>4) cout << "-->Init gamma: " << gammat << endl; // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( 1.0 / (AlphaReal)_pTrainingData->getNumExamples() * 0.01 ); vector<FeatureReal> sigmoidSlopes( numColumns ); vector<FeatureReal> sigmoidOffSets( numColumns ); vector<vector<AlphaReal> > vsArray(numColumns); fill( sigmoidSlopes.begin(), sigmoidSlopes.end(), 0.1 ); fill( sigmoidOffSets.begin(), sigmoidOffSets.end(), 0.0 ); for(int i=0; i<numColumns; ++i ) { vsArray[i].resize(numClasses); for (int k=0; k<numClasses; ++k ) { vsArray[i][k] = (rand() % 2) * 2 - 1; } normalizeLength( vsArray[i] ); //fill(vsArray[i].begin(),vsArray[i].end(),0.0); } if ( _gMethod == OPT_SGD ) { vector<int> randomPermutation(numExamples); for (int i = 0; i < numExamples; ++i ) randomPermutation[i]=i; random_shuffle( randomPermutation.begin(), randomPermutation.end() ); AlphaReal gammaDivider = 1.0; for (int i = 0; i < numExamples; ++i ) { if ((i>0)&&((i%_gammdivperiod)==0)) gammaDivider += 1.0; AlphaReal stepOffSet, stepSlope, stepV; //int randomTrainingInstanceIdx = (rand() % _pTrainingData->getNumExamples()); int randomTrainingInstanceIdx = randomPermutation[i]; vector<Label> labels = _pTrainingData->getLabels(randomTrainingInstanceIdx); for (int j = 0; j < numColumns; ++j) { FeatureReal val = _pTrainingData->getValue(randomTrainingInstanceIdx, j); FeatureReal tmpSigVal = sigmoid(val,sigmoidSlopes[j],sigmoidOffSets[j]); AlphaReal deltaQ = 0.0; switch (_tFunction) { case TF_EXPLOSS: for( vector< Label >::iterator it = labels.begin(); it != labels.end(); it++ ) { deltaQ += exp( -vsArray[j][it->idx] * it->y * ( 2*tmpSigVal-1 ) ) *2.0 * it->weight*vsArray[j][it->idx]*it->y*tmpSigVal*(1.0-tmpSigVal); } stepOffSet = -deltaQ; stepSlope = -deltaQ * val; break; case TF_EDGE: for( vector< Label >::iterator it = labels.begin(); it != labels.end(); it++ ) { deltaQ += 2.0 * it->weight*vsArray[j][it->idx]*it->y*tmpSigVal*(1.0-tmpSigVal); } // because edge should be maximized stepOffSet = -deltaQ; stepSlope = -deltaQ * val; break; default: break; } // gradient step FeatureReal tmpSigmoidOffSet = sigmoidOffSets[j] - numExamples * static_cast<FeatureReal>(gammat * stepOffSet); FeatureReal tmpSigmoidSlopes = sigmoidSlopes[j] - numExamples * static_cast<FeatureReal>(gammat * stepSlope); // update the parameters for( vector< Label >::iterator it = labels.begin(); it != labels.end(); it++ ) { switch (_tFunction) { case TF_EXPLOSS: stepV = -exp( - vsArray[j][it->idx] * it->y * ( 2*tmpSigVal-1 ) ) * ( it->weight * (2.0 * tmpSigVal - 1.0) * it->y); break; case TF_EDGE: // + gradient since it a maximization task stepV = - ( it->weight * (2.0 * tmpSigVal - 1.0) * it->y); break; } vsArray[j][it->idx] = vsArray[j][it->idx] - gammat * stepV; } normalizeLength( vsArray[j] ); sigmoidOffSets[j] = tmpSigmoidOffSet; sigmoidSlopes[j] = tmpSigmoidSlopes; } // decrease gammat gammat = gammat / gammaDivider; } } else if (_gMethod == OPT_BGD ) { AlphaReal gammaDivider = 1.0; for (int gradi=0; gradi<_maxIter; ++gradi) { if ((gradi>0)&&((gradi%_gammdivperiod)==0)) gammaDivider += 1.0; for (int j = 0; j < numColumns; ++j) { AlphaReal slopeImporvemement = 0.0; AlphaReal offsetImporvemement = 0.0; vector<AlphaReal> vImprovement(numClasses); fill(vImprovement.begin(),vImprovement.end(),0.0); switch (_tFunction) { case TF_EXPLOSS: for (int i = 0; i < numExamples; ++i ) { vector<Label> labels = _pTrainingData->getLabels(i); FeatureReal val = _pTrainingData->getValue(i,j); // update the parameters FeatureReal tmpSigVal = sigmoid(val,sigmoidSlopes[j],sigmoidOffSets[j]); AlphaReal deltaQ = 0.0; for( vector< Label >::iterator it = labels.begin(); it != labels.end(); it++ ) { deltaQ += exp( -vsArray[j][it->idx] * it->y * ( 2*tmpSigVal-1 ) ) * 2.0 * it->weight*vsArray[j][it->idx]*it->y*tmpSigVal*(1.0-tmpSigVal); } offsetImporvemement -= deltaQ; slopeImporvemement -= (deltaQ*val); for( vector< Label >::iterator it = labels.begin(); it != labels.end(); it++ ) { // + gradient since it a maximization task vImprovement[it->idx] -= exp( -vsArray[j][it->idx] * it->y * ( 2*tmpSigVal-1 ) ) * ( it->weight * (2.0 * tmpSigVal - 1.0) * it->y); } } break; case TF_EDGE: for (int i = 0; i < numExamples; ++i ) { vector<Label> labels = _pTrainingData->getLabels(i); FeatureReal val = _pTrainingData->getValue(i,j); // update the parameters FeatureReal tmpSigVal = sigmoid(val,sigmoidSlopes[j],sigmoidOffSets[j]); AlphaReal deltaQ = 0.0; for( vector< Label >::iterator it = labels.begin(); it != labels.end(); it++ ) { deltaQ += 2.0 * it->weight*vsArray[j][it->idx]*it->y*tmpSigVal*(1.0-tmpSigVal); } offsetImporvemement -= deltaQ; slopeImporvemement -= (deltaQ*val); for( vector< Label >::iterator it = labels.begin(); it != labels.end(); it++ ) { // + gradient since it a maximization task vImprovement[it->idx] -= ( it->weight * (2.0 * tmpSigVal - 1.0) * it->y); } } break; } //update the current parameter vector for( int iimp=0; iimp < vImprovement.size(); ++iimp ) { // + gradient since it a maximization task vsArray[j][iimp] -= gammat * vImprovement[iimp]; //vsArray[j][iimp] += 100.0 * gammat * vImprovement[iimp]; } normalizeLength( vsArray[j] ); sigmoidOffSets[j] -= gammat * offsetImporvemement; //sigmoidOffSets[j] += 100.0 * gammat * offsetImporvemement; sigmoidSlopes[j] -= gammat * slopeImporvemement; //sigmoidSlopes[j] += 100.0 * gammat * slopeImporvemement; // decrease gammat gammat = gammat / gammaDivider; } // j } } else { cout << "Unknown optimization method!" << endl; exit(-1); } int bestColumn = -1; // find the best feature for (int j = 0; j < numColumns; ++j) { _selectedColumn = j; _sigmoidSlope = sigmoidSlopes[j]; _sigmoidOffset = sigmoidOffSets[j]; _v = vsArray[j]; for(int k=0; k<numClasses; ++k ) _v[k]= _v[k] < 0 ? -1.0 : 1.0; AlphaReal tmpEdge = this->getEdge(); if ((tmpEdge>0.0) && (tmpEdge>bestEdge)) { bestEdge = tmpEdge; bestv = _v; bestColumn = j; } } _selectedColumn = bestColumn; if (_verbose>3) cout << "Selected column: " << _selectedColumn << endl; if ( _selectedColumn != -1 ) { stringstream parameterString; parameterString << _sigmoidSlope << "_" << _sigmoidOffset; _id = _pTrainingData->getAttributeNameMap().getNameFromIdx(_selectedColumn) + _id + parameterString.str(); } else { return numeric_limits<AlphaReal>::signaling_NaN(); } _sigmoidSlope = sigmoidSlopes[_selectedColumn]; _sigmoidOffset = sigmoidOffSets[_selectedColumn]; _v = bestv; //normalizeLength( _v ); if (_verbose>3) { cout << "Sigmoid slope:\t" << _sigmoidSlope << endl; cout << "Sigmoid offset:\t" << _sigmoidOffset << endl; } //calculate alpha this->_alpha = 0.0; AlphaReal eps_min = 0.0, eps_pls = 0.0; //_pTrainingData->clearIndexSet(); for( int i = 0; i < _pTrainingData->getNumExamples(); i++ ) { vector< Label> l = _pTrainingData->getLabels( i ); for( vector< Label >::iterator it = l.begin(); it != l.end(); it++ ) { AlphaReal result = this->classify( _pTrainingData, i, it->idx ); result *= (it->y * it->weight); if ( result < 0 ) eps_min -= result; if ( result > 0 ) eps_pls += result; } } this->_alpha = getAlpha( eps_min, eps_pls ); // calculate the energy (sum of the energy of the leaves //AlphaReal energy = this->getEnergy( eps_min, eps_pls ); return bestEdge; }
AlphaReal TreeLearnerUCT::run() { if ( _numOfCalling == 0 ) { if (_verbose > 0) { cout << "Initializing tree..." << endl; } InnerNodeUCTSparse::setDepth( _numBaseLearners ); InnerNodeUCTSparse::setBranchOrder( _pTrainingData->getNumAttributes() ); _root.setChildrenNum(); //createUCTTree(); } _numOfCalling++; set< int > tmpIdx, idxPos, idxNeg; _pTrainingData->clearIndexSet(); for( int i = 0; i < _pTrainingData->getNumExamples(); i++ ) tmpIdx.insert( i ); vector< int > trajectory(0); _root.getBestTrajectory( trajectory ); // for UCT for(int ib = 0; ib < _numBaseLearners; ++ib) _baseLearners[ib]->setTrainingData(_pTrainingData); AlphaReal edge = numeric_limits<AlphaReal>::max(); BaseLearner* pPreviousBaseLearner = 0; //floatBaseLearner tmpPair, tmpPairPos, tmpPairNeg; // for storing the inner point (learneres) which will be extended //vector< floatBaseLearner > bLearnerVector; InnerNodeType innerNode; priority_queue<InnerNodeType, deque<InnerNodeType>, greater_first<InnerNodeType> > pq; //train the first learner //_baseLearners[0]->run(); pPreviousBaseLearner = _baseLearners[0]->copyState(); dynamic_cast<FeaturewiseLearner*>(pPreviousBaseLearner)->run( trajectory[0] ); //this contains the number of baselearners int ib = 0; NodePointUCT tmpNodePoint, nodeLeft, nodeRight; //////////////////////////////////////////////////////// //set the edge //tmpPair.first = getEdge( pPreviousBaseLearner, _pTrainingData ); //tmpPair.second.first.first = pPreviousBaseLearner; // set the pointer of the parent //tmpPair.second.first.second.first = 0; // set that this is a neg child //tmpPair.second.first.second.second = 0; //tmpPair.second.second = tmpIdx; //bLearnerVector = calculateChildrenAndEnergies( tmpPair ); /// pPreviousBaseLearner->setTrainingData( _pTrainingData ); tmpNodePoint._edge = pPreviousBaseLearner->getEdge(); tmpNodePoint._learner = pPreviousBaseLearner; tmpNodePoint._idx = 0; tmpNodePoint._depth = 0; tmpNodePoint._learnerIdxSet = tmpIdx; calculateChildrenAndEnergies( tmpNodePoint, trajectory[1] ); //////////////////////////////////////////////////////// //insert the root into the priority queue if ( tmpNodePoint._extended ) { if (_verbose > 2) { //cout << "Edges: (parent, pos, neg): " << bLearnerVector[0].first << " " << bLearnerVector[1].first << " " << bLearnerVector[2].first << endl << flush; //cout << "alpha[" << (ib) << "] = " << _alpha << endl << flush; cout << "Edges: (parent, pos, neg): " << tmpNodePoint._edge << " " << tmpNodePoint._leftEdge << " " << tmpNodePoint._rightEdge << endl << flush; } // if the energy is getting higher then we push it into the priority queue if ( tmpNodePoint._edge < ( tmpNodePoint._leftEdge + tmpNodePoint._rightEdge ) ) { float deltaEdge = abs( tmpNodePoint._edge - ( tmpNodePoint._leftEdge + tmpNodePoint._rightEdge ) ); innerNode.first = deltaEdge; innerNode.second = tmpNodePoint; pq.push( innerNode ); } else { //delete bLearnerVector[0].second.first.first; delete tmpNodePoint._leftChild; delete tmpNodePoint._rightChild; } } if ( pq.empty() ) { // we don't extend the root BaseLearner* tmpBL = _baseLearners[0]; _baseLearners[0] = tmpNodePoint._learner; delete tmpBL; ib = 1; } while ( ! pq.empty() && ( ib < _numBaseLearners ) ) { //get the best learner from the priority queue innerNode = pq.top(); if (_verbose > 2) { cout << "Delta energy: " << innerNode.first << endl << flush; cout << "Size of priority queue: " << pq.size() << endl << flush; } pq.pop(); tmpNodePoint = innerNode.second; //tmpPair = bLearnerVector[0]; //tmpPairPos = bLearnerVector[1]; //tmpPairNeg = bLearnerVector[2]; nodeLeft._edge = tmpNodePoint._leftEdge; nodeLeft._learner = tmpNodePoint._leftChild; nodeLeft._learnerIdxSet = tmpNodePoint._leftChildIdxSet; nodeRight._edge = tmpNodePoint._rightEdge; nodeRight._learner = tmpNodePoint._rightChild; nodeRight._learnerIdxSet = tmpNodePoint._rightChildIdxSet; //store the baselearner if the deltaenrgy will be higher if ( _verbose > 3 ) { cout << "Insert learner: " << ib << endl << flush; } int parentIdx = tmpNodePoint._parentIdx; BaseLearner* tmpBL = _baseLearners[ib]; _baseLearners[ib] = tmpNodePoint._learner; delete tmpBL; nodeLeft._parentIdx = ib; nodeRight._parentIdx = ib; nodeLeft._leftOrRightChild = 0; nodeRight._leftOrRightChild = 1; nodeLeft._depth = tmpNodePoint._depth + 1; nodeRight._depth = tmpNodePoint._depth + 1; if ( ib > 0 ) { //set the descendant idx _idxPairs[ parentIdx ][ tmpNodePoint._leftOrRightChild ] = ib; } ib++; if ( ib >= _numBaseLearners ) break; //extend positive node if ( nodeLeft._learner ) { calculateChildrenAndEnergies( nodeLeft, trajectory[ nodeLeft._depth + 1 ] ); } else { nodeLeft._extended = false; } //calculateChildrenAndEnergies( nodeLeft ); // if the energie is getting higher then we push it into the priority queue if ( nodeLeft._extended ) { if (_verbose > 2) { //cout << "Edges: (parent, pos, neg): " << bLearnerVector[0].first << " " << bLearnerVector[1].first << " " << bLearnerVector[2].first << endl << flush; //cout << "alpha[" << (ib) << "] = " << _alpha << endl << flush; cout << "Edges: (parent, pos, neg): " << nodeLeft._edge << " " << nodeLeft._leftEdge << " " << nodeLeft._rightEdge << endl << flush; } // if the energy is getting higher then we push it into the priority queue if ( nodeLeft._edge < ( nodeLeft._leftEdge + nodeLeft._rightEdge ) ) { float deltaEdge = abs( nodeLeft._edge - ( nodeLeft._leftEdge + nodeLeft._rightEdge ) ); innerNode.first = deltaEdge; innerNode.second = nodeLeft; pq.push( innerNode ); } else { //delete bLearnerVector[0].second.first.first; delete nodeLeft._leftChild; delete nodeLeft._rightChild; if ( ib >= _numBaseLearners ) { delete nodeLeft._learner; break; } else { //this will be a leaf, we do not extend further int parentIdx = nodeLeft._parentIdx; BaseLearner* tmpBL = _baseLearners[ib]; _baseLearners[ib] = nodeLeft._learner; delete tmpBL; _idxPairs[ parentIdx ][ 0 ] = ib; ib += 1; } } } //extend negative node if ( nodeRight._learner ) { calculateChildrenAndEnergies( nodeRight, trajectory[ nodeRight._depth + 1 ] ); } else { nodeRight._extended = false; } // if the energie is getting higher then we push it into the priority queue if ( nodeRight._extended ) { if (_verbose > 2) { cout << "Edges: (parent, pos, neg): " << nodeRight._edge << " " << nodeRight._leftEdge << " " << nodeRight._rightEdge << endl << flush; //cout << "alpha[" << (ib) << "] = " << _alpha << endl << flush; } // if the energie is getting higher then we push it into the priority queue if ( nodeRight._edge < ( nodeRight._leftEdge + nodeRight._rightEdge ) ) { float deltaEdge = abs( nodeRight._edge - ( nodeRight._leftEdge + nodeRight._rightEdge ) ); innerNode.first = deltaEdge; innerNode.second = nodeRight; pq.push( innerNode ); } else { //delete bLearnerVector[0].second.first.first; delete nodeRight._leftChild; delete nodeRight._rightChild; if ( ib >= _numBaseLearners ) { delete nodeRight._learner; break; } else { //this will be a leaf, we do not extend further int parentIdx = nodeRight._parentIdx; BaseLearner* tmpBL = _baseLearners[ib]; _baseLearners[ib] = nodeRight._learner; delete tmpBL; _idxPairs[ parentIdx ][ 1 ] = ib; ib += 1; } } } } for(int ib2 = ib; ib2 < _numBaseLearners; ++ib2) delete _baseLearners[ib2]; _numBaseLearners = ib; if (_verbose > 2) { cout << "Num of learners: " << _numBaseLearners << endl << flush; } //clear the priority queur while ( ! pq.empty() && ( ib < _numBaseLearners ) ) { //get the best learner from the priority queue innerNode = pq.top(); pq.pop(); tmpNodePoint = innerNode.second; delete tmpNodePoint._learner; delete tmpNodePoint._leftChild; delete tmpNodePoint._rightChild; } _id = _baseLearners[0]->getId(); for(int ib = 0; ib < _numBaseLearners; ++ib) _id += "_x_" + _baseLearners[ib]->getId(); //calculate alpha this->_alpha = 0.0; float eps_min = 0.0, eps_pls = 0.0; _pTrainingData->clearIndexSet(); for( int i = 0; i < _pTrainingData->getNumExamples(); i++ ) { vector< Label> l = _pTrainingData->getLabels( i ); for( vector< Label >::iterator it = l.begin(); it != l.end(); it++ ) { float result = this->classify( _pTrainingData, i, it->idx ); if ( ( result * it->y ) < 0 ) eps_min += it->weight; if ( ( result * it->y ) > 0 ) eps_pls += it->weight; } } //update the weights in the UCT tree double updateWeight = 0.0; if ( _updateRule == EDGE_SQUARE ) { double edge = getEdge(); updateWeight = 1 - sqrt( 1 - ( edge * edge ) ); } else if ( _updateRule == ALPHAS ) { double alpha = this->getAlpha(); updateWeight = alpha; } else if ( _updateRule == ESQUARE ) { double edge = getEdge(); updateWeight = edge * edge; } _root.updateInnerNodes( updateWeight, trajectory ); if (_verbose > 2) { cout << "Update weight (" << updateWeight << ")" << "\tUpdate rule index: "<< _updateRule << endl << flush; } // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( (float)1.0 / (float)_pTrainingData->getNumExamples() * (float)0.01 ); this->_alpha = getAlpha( eps_min, eps_pls ); // calculate the energy (sum of the energy of the leaves float energy = this->getEnergy( eps_min, eps_pls ); return energy; }
AlphaReal HaarMultiStumpLearner::run() { const int numClasses = _pTrainingData->getNumClasses(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( 1.0 / (AlphaReal)_pTrainingData->getNumExamples() * 0.01 ); vector<sRates> mu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<AlphaReal> tmpV(numClasses); // The class-wise votes/abstentions vector<FeatureReal> tmpThresholds(numClasses); AlphaReal tmpAlpha; AlphaReal bestEnergy = numeric_limits<AlphaReal>::max(); AlphaReal tmpEnergy; HaarData* pHaarData = static_cast<HaarData*>(_pTrainingData); // get the whole data matrix // const vector<int*>& intImages = pHaarData->getIntImageVector(); // The data matrix transformed into the feature's space vector< pair<int, FeatureReal> > processedHaarData(_pTrainingData->getNumExamples()); // I need to prepare both type of sampling int numConf; // for ST_NUM time_t startTime, currentTime; // for ST_TIME long numProcessed; bool quitConfiguration; StumpAlgorithm<FeatureReal> sAlgo(numClasses); sAlgo.initSearchLoop(_pTrainingData); // The declared features types vector<HaarFeature*>& loadedFeatures = pHaarData->getLoadedFeatures(); // for every feature type vector<HaarFeature*>::iterator ftIt; for (ftIt = loadedFeatures.begin(); ftIt != loadedFeatures.end(); ++ftIt) { // just for readability HaarFeature* pCurrFeature = *ftIt; if (_samplingType != ST_NO_SAMPLING) pCurrFeature->setAccessType(AT_RANDOM_SAMPLING); // Reset the iterator on the configurations. For random sampling // this shuffles the configurations. pCurrFeature->resetConfigIterator(); quitConfiguration = false; numProcessed = 0; numConf = 0; time( &startTime ); if (_verbose > 1) cout << "Learning type " << pCurrFeature->getName() << ".." << flush; // While there is a configuration available while ( pCurrFeature->hasConfigs() ) { // transform the data from intImages to the feature's space pCurrFeature->fillHaarData(_pTrainingData->getExamples(), processedHaarData); // sort the examples in the new space by their coordinate sort( processedHaarData.begin(), processedHaarData.end(), nor_utils::comparePair<2, int, float, less<float> >() ); // find the optimal threshold sAlgo.findMultiThresholdsWithInit(processedHaarData.begin(), processedHaarData.end(), _pTrainingData, tmpThresholds, &mu, &tmpV); tmpEnergy = getEnergy(mu, tmpAlpha, tmpV); ++numProcessed; if (tmpEnergy < bestEnergy) { // Store it in the current weak hypothesis. // note: I don't really like having so many temp variables // but the alternative would be a structure, which would need // to be inheritable to make things more consistent. But this would // make it less flexible. Therefore, I am still undecided. This // might change! _alpha = tmpAlpha; _v = tmpV; // I need to save the configuration because it changes within the object _selectedConfig = pCurrFeature->getCurrentConfig(); // I save the object because it contains the informations about the type, // the name, etc.. _pSelectedFeature = pCurrFeature; _thresholds = tmpThresholds; bestEnergy = tmpEnergy; } // Move to the next configuration pCurrFeature->moveToNextConfig(); // check stopping criterion for random configurations switch (_samplingType) { case ST_NUM: ++numConf; if (numConf >= _samplingVal) quitConfiguration = true; break; case ST_TIME: { time( ¤tTime ); float diff = difftime(currentTime, startTime); // difftime is in seconds if (diff >= _samplingVal) quitConfiguration = true; } break; case ST_NO_SAMPLING: perror("ERROR: st no sampling... not sure what this means"); break; } // end switch if (quitConfiguration) break; } // end while if (_verbose > 1) { time( ¤tTime ); float diff = difftime(currentTime, startTime); // difftime is in seconds cout << "done! " << "(processed: " << numProcessed << " - elapsed: " << diff << " sec)" << endl; } } if (!_pSelectedFeature) { cerr << "ERROR: No Haar Feature found. Something must be wrong!" << endl; exit(1); } else { if (_verbose > 1) cout << "Selected type: " << _pSelectedFeature->getName() << endl; } return bestEnergy; }
AlphaReal BanditSingleSparseStump::run() { if ( ! this->_banditAlgo->isInitialized() ) { init(); } const int numClasses = _pTrainingData->getNumClasses(); const int numColumns = _pTrainingData->getNumAttributes(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( (AlphaReal) 1.0 / (AlphaReal)_pTrainingData->getNumExamples() * (AlphaReal)0.01 ); vector<sRates> mu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<AlphaReal> tmpV(numClasses); // The class-wise votes/abstentions FeatureReal tmpThreshold; AlphaReal tmpAlpha; AlphaReal bestEnergy = numeric_limits<AlphaReal>::max(); AlphaReal tmpEnergy; StumpAlgorithmLSHTC<FeatureReal> sAlgo(numClasses); sAlgo.initSearchLoop(_pTrainingData); AlphaReal halfTheta; if ( _abstention == ABST_REAL || _abstention == ABST_CLASSWISE ) halfTheta = _theta/(AlphaReal)2.0; else halfTheta = 0; AlphaReal bestReward = 0.0; _banditAlgo->getKBestAction( _K, _armsForPulling ); _rewards.resize( _armsForPulling.size() ); if ( this->_armsForPulling.size() == 0 ) { cout << "error" << endl; } for( int i = 0; i < (int)_armsForPulling.size(); i++ ) { //columnIndices[i] = p.second; const pair<vpReverseIterator,vpReverseIterator> dataBeginEnd = static_cast<SortedData*>(_pTrainingData)->getFileteredReverseBeginEnd( _armsForPulling[i] ); /* const pair<vpIterator,vpIterator> dataBeginEnd = static_cast<SortedData*>(_pTrainingData)->getFileteredBeginEnd( _armsForPulling[i] ); */ const vpReverseIterator dataBegin = dataBeginEnd.first; const vpReverseIterator dataEnd = dataBeginEnd.second; /* const vpIterator dataBegin = dataBeginEnd.first; const vpIterator dataEnd = dataBeginEnd.second; */ // also sets mu, tmpV, and bestHalfEdge tmpThreshold = sAlgo.findSingleThresholdWithInit(dataBegin, dataEnd, _pTrainingData, halfTheta, &mu, &tmpV); tmpEnergy = getEnergy(mu, tmpAlpha, tmpV); //update the weights in the UCT tree AlphaReal edge = 0.0; for ( vector<sRates>::iterator itR = mu.begin(); itR != mu.end(); itR++ ) edge += ( itR->rPls - itR->rMin ); AlphaReal reward = this->getRewardFromEdge( edge ); _rewards[i] = reward; if ( _verbose > 3 ) { //cout << "\tK = " <<i << endl; cout << "\tTempAlpha: " << tmpAlpha << endl; cout << "\tTempEnergy: " << tmpEnergy << endl; cout << "\tUpdate weight: " << reward << endl; } if ( (i==0) || (tmpEnergy < bestEnergy && tmpAlpha > 0) ) { // Store it in the current weak hypothesis. // note: I don't really like having so many temp variables // but the alternative would be a structure, which would need // to be inheritable to make things more consistent. But this would // make it less flexible. Therefore, I am still undecided. This // might change! _alpha = tmpAlpha; _v = tmpV; _selectedColumn = _armsForPulling[i]; _threshold = tmpThreshold; bestEnergy = tmpEnergy; bestReward = reward; } } if ( _banditAlgoName == BA_EXP3G2 ) { vector<AlphaReal> ePayoffs( numColumns ); fill( ePayoffs.begin(), ePayoffs.end(), 0.0 ); for( int i=0; i<_armsForPulling.size(); i++ ) { ePayoffs[_armsForPulling[i]] = _rewards[i]; } estimatePayoffs( ePayoffs ); (dynamic_cast<Exp3G2*>(_banditAlgo))->receiveReward( ePayoffs ); } else { for( int i=0; i<_armsForPulling.size(); i++ ) { _banditAlgo->receiveReward( _armsForPulling[i], _rewards[i] ); } } if ( _verbose > 2 ) cout << "Column has been selected: " << _selectedColumn << endl; stringstream thresholdString; thresholdString << _threshold; _id = _pTrainingData->getAttributeNameMap().getNameFromIdx(_selectedColumn) + thresholdString.str(); _reward = bestReward; return bestEnergy; }
float SelectorLearner::run() { const int numClasses = _pTrainingData->getNumClasses(); const int numColumns = _pTrainingData->getNumAttributes(); const int numExamples = _pTrainingData->getNumExamples(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( 1.0 / (float)_pTrainingData->getNumExamples() * 0.01 ); vector<sRates> vMu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<float> tmpV(numClasses); // The class-wise votes/abstentions float tmpAlpha, tmpEnergy; float bestEnergy = numeric_limits<float>::max(); int numOfDimensions = _maxNumOfDimensions; for (int j = 0; j < numColumns; ++j) { // Tricky way to select numOfDimensions columns randomly out of numColumns int rest = numColumns - j; float r = rand()/static_cast<float>(RAND_MAX); if ( static_cast<float>(numOfDimensions) / rest > r ) { --numOfDimensions; /* if (_verbose > 2) cout << " --> trying attribute = " <<_pTrainingData->getAttributeNameMap().getNameFromIdx(j) << endl << flush; */ const int numIdxs = _pTrainingData->getEnumMap(j).getNumNames(); // Create and initialize the numIdxs x numClasses gamma matrix vector<vector<float> > tmpGammasPls(numIdxs); vector<vector<float> > tmpGammasMin(numIdxs); for (int io = 0; io < numIdxs; ++io) { vector<float> tmpGammaPls(numClasses); vector<float> tmpGammaMin(numClasses); fill(tmpGammaPls.begin(), tmpGammaPls.end(), 0.0); fill(tmpGammaMin.begin(), tmpGammaMin.end(), 0.0); tmpGammasPls[io] = tmpGammaPls; tmpGammasMin[io] = tmpGammaMin; } // Compute the elements of the gamma plus and minus matrices float entry; for (int i = 0; i < numExamples; ++i) { const vector<Label>& labels = _pTrainingData->getLabels(i); int io = static_cast<int>(_pTrainingData->getValue(i,j)); for (int l = 0; l < numClasses; ++l) { entry = labels[l].weight * labels[l].y; if (entry > 0) tmpGammasPls[io][l] += entry; else if (entry < 0) tmpGammasMin[io][l] += -entry; } } // Initialize the u vector to random +-1 vector<sRates> uMu(numIdxs); // The idx-wise rates vector<float> tmpU(numIdxs);// The idx-wise votes/abstentions vector<float> previousTmpU(numIdxs);// The idx-wise votes/abstentions for (int io = 0; io < numIdxs; ++io) { uMu[io].classIdx = io; } for (int io = 0; io < numIdxs; ++io) { // initializing u as it has only one positive element fill( tmpU.begin(), tmpU.end(), -1 ); tmpU[io] = +1; vector<sRates> vMu(numClasses); // The label-wise rates for (int l = 0; l < numClasses; ++l) vMu[l].classIdx = l; vector<float> tmpV(numClasses); // The label-wise votes/abstentions float tmpVal; tmpAlpha = 0.0; //filling out tmpV and vMu for (int l = 0; l < numClasses; ++l) { vMu[l].rPls = vMu[l].rMin = vMu[l].rZero = 0; for (int io = 0; io < numIdxs; ++io) { if (tmpU[io] > 0) { vMu[l].rPls += tmpGammasPls[io][l]; vMu[l].rMin += tmpGammasMin[io][l]; } else if (tmpU[io] < 0) { vMu[l].rPls += tmpGammasMin[io][l]; vMu[l].rMin += tmpGammasPls[io][l]; } } if (vMu[l].rPls >= vMu[l].rMin) { tmpV[l] = +1; } else { tmpV[l] = -1; tmpVal = vMu[l].rPls; vMu[l].rPls = vMu[l].rMin; vMu[l].rMin = tmpVal; } } tmpEnergy = AbstainableLearner::getEnergy(vMu, tmpAlpha, tmpV); if ( tmpEnergy < bestEnergy && tmpAlpha > 0 ) { _alpha = tmpAlpha; _v = tmpV; //_u = tmpU; _positiveIdxOfArrayU = io; _selectedColumn = j; bestEnergy = tmpEnergy; } } } } if (_selectedColumn>-1) { _id = _pTrainingData->getAttributeNameMap().getNameFromIdx(_selectedColumn); return bestEnergy; } else { return bestEnergy = numeric_limits<float>::signaling_NaN(); } }
float EnumLearner::run( int colIdx ) { const int numClasses = _pTrainingData->getNumClasses(); const int numColumns = _pTrainingData->getNumAttributes(); const int numExamples = _pTrainingData->getNumExamples(); // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( 1.0 / (float)_pTrainingData->getNumExamples() * 0.01 ); vector<sRates> vMu(numClasses); // The class-wise rates. See BaseLearner::sRates for more info. vector<float> tmpV(numClasses); // The class-wise votes/abstentions vector<float> previousTmpV(numClasses); // The class-wise votes/abstentions float tmpAlpha,previousTmpAlpha, previousEnergy; float bestEnergy = numeric_limits<float>::max(); int numOfDimensions = _maxNumOfDimensions; // Tricky way to select numOfDimensions columns randomly out of numColumns int j = colIdx; if (_verbose > 2) cout << " --> trying attribute = " <<_pTrainingData->getAttributeNameMap().getNameFromIdx(j) << endl << flush; const int numIdxs = _pTrainingData->getEnumMap(j).getNumNames(); // Create and initialize the numIdxs x numClasses gamma matrix vector<vector<float> > tmpGammasPls(numIdxs); vector<vector<float> > tmpGammasMin(numIdxs); for (int io = 0; io < numIdxs; ++io) { vector<float> tmpGammaPls(numClasses); vector<float> tmpGammaMin(numClasses); fill(tmpGammaPls.begin(), tmpGammaPls.end(), 0.0); fill(tmpGammaMin.begin(), tmpGammaMin.end(), 0.0); tmpGammasPls[io] = tmpGammaPls; tmpGammasMin[io] = tmpGammaMin; } // Compute the elements of the gamma plus and minus matrices float entry; for (int i = 0; i < numExamples; ++i) { const vector<Label>& labels = _pTrainingData->getLabels(i); int io = static_cast<int>(_pTrainingData->getValue(i,j)); for (int l = 0; l < numClasses; ++l) { entry = labels[l].weight * labels[l].y; if (entry > 0) tmpGammasPls[io][l] += entry; else if (entry < 0) tmpGammasMin[io][l] += -entry; } } // Initialize the u vector to random +-1 vector<sRates> uMu(numIdxs); // The idx-wise rates vector<float> tmpU(numIdxs);// The idx-wise votes/abstentions vector<float> previousTmpU(numIdxs);// The idx-wise votes/abstentions for (int io = 0; io < numIdxs; ++io) { uMu[io].classIdx = io; if ( rand()/static_cast<float>(RAND_MAX) > 0.5 ) tmpU[io] = +1; else tmpU[io] = -1; } //vector<sRates> vMu(numClasses); // The label-wise rates for (int l = 0; l < numClasses; ++l) vMu[l].classIdx = l; //vector<float> tmpV(numClasses); // The label-wise votes/abstentions float tmpEnergy = numeric_limits<float>::max(); float tmpVal; tmpAlpha = 0.0; while (1) { previousEnergy = tmpEnergy; previousTmpV = tmpV; previousTmpAlpha = tmpAlpha; //filling out tmpV and vMu for (int l = 0; l < numClasses; ++l) { vMu[l].rPls = vMu[l].rMin = vMu[l].rZero = 0; for (int io = 0; io < numIdxs; ++io) { if (tmpU[io] > 0) { vMu[l].rPls += tmpGammasPls[io][l]; vMu[l].rMin += tmpGammasMin[io][l]; } else if (tmpU[io] < 0) { vMu[l].rPls += tmpGammasMin[io][l]; vMu[l].rMin += tmpGammasPls[io][l]; } } if (vMu[l].rPls >= vMu[l].rMin) { tmpV[l] = +1; } else { tmpV[l] = -1; tmpVal = vMu[l].rPls; vMu[l].rPls = vMu[l].rMin; vMu[l].rMin = tmpVal; } } tmpEnergy = AbstainableLearner::getEnergy(vMu, tmpAlpha, tmpV); if (_verbose > 2) cout << " --> energy V = " << tmpEnergy << "\talpha = " << tmpAlpha << endl << flush; if (tmpEnergy >= previousEnergy) { tmpV = previousTmpV; break; } previousEnergy = tmpEnergy; previousTmpU = tmpU; previousTmpAlpha = tmpAlpha; //filling out tmpU and uMu for (int io = 0; io < numIdxs; ++io) { uMu[io].rPls = uMu[io].rMin = uMu[io].rZero = 0; for (int l = 0; l < numClasses; ++l) { if (tmpV[l] > 0) { uMu[io].rPls += tmpGammasPls[io][l]; uMu[io].rMin += tmpGammasMin[io][l]; } else if (tmpV[l] < 0) { uMu[io].rPls += tmpGammasMin[io][l]; uMu[io].rMin += tmpGammasPls[io][l]; } } if (uMu[io].rPls >= uMu[io].rMin) { tmpU[io] = +1; } else { tmpU[io] = -1; tmpVal = uMu[io].rPls; uMu[io].rPls = uMu[io].rMin; uMu[io].rMin = tmpVal; } } tmpEnergy = AbstainableLearner::getEnergy(uMu, tmpAlpha, tmpU); if (_verbose > 2) cout << " --> energy U = " << tmpEnergy << "\talpha = " << tmpAlpha << endl << flush; if (tmpEnergy >= previousEnergy) { tmpU = previousTmpU; break; } if ( previousEnergy < bestEnergy && previousTmpAlpha > 0 ) { _alpha = previousTmpAlpha; _v = tmpV; _u = tmpU; _selectedColumn = j; bestEnergy = previousEnergy; } } _id = _pTrainingData->getAttributeNameMap().getNameFromIdx(_selectedColumn); return bestEnergy; }
//------------------------------------------------------------------------------- float BanditTreeLearner::run() { if ( ! this->_banditAlgo->isInitialized() ) { init(); } // the bandit algorithm selects the subset the tree learner is aloowed to use // the armindexes will be stored in _armsForPulling getArms(); //declarations NodePoint tmpNodePoint, nodeLeft, nodeRight; ScalarLearner* pPreviousBaseLearner = 0; set< int > tmpIdx; //this contains the current number of baselearners int ib = 0; floatInnerNode innerNode; // for storing the inner point (learneres) which will be extended priority_queue<floatInnerNode, deque<floatInnerNode>, greater_first<floatInnerNode> > pq; for(int ib = 0; ib < _numBaseLearners; ++ib) _baseLearners[ib]->setTrainingData(_pTrainingData); //train the first learner on the whole dataset _pTrainingData->clearIndexSet(); pPreviousBaseLearner = dynamic_cast<ScalarLearner* >(_baseLearners[0]->copyState()); float energy = dynamic_cast< FeaturewiseLearner* >(pPreviousBaseLearner)->run( _armsForPulling ); if ( energy != energy ) { if (_verbose > 2) { cout << "Cannot find weak hypothesis, constant learner is used!!" << endl; } delete pPreviousBaseLearner; //cannot find better than constant learner ScalarLearner* pConstantWeakHypothesisSource = dynamic_cast<ScalarLearner*>(BaseLearner::RegisteredLearners().getLearner("ConstantLearner")); ScalarLearner* cLearner = dynamic_cast<ScalarLearner*>(pConstantWeakHypothesisSource->create()); cLearner->setTrainingData(_pTrainingData); float constantEnergy = cLearner->run(); tmpNodePoint._edge = 0.0; tmpNodePoint._learner = cLearner; tmpNodePoint._idx = 0; tmpNodePoint._learnerIdxSet = tmpIdx; tmpNodePoint._extended = false; } else { //try to extend the root for( int i = 0; i < _pTrainingData->getNumExamples(); i++ ) tmpIdx.insert( i ); tmpNodePoint._edge = pPreviousBaseLearner->getEdge(); tmpNodePoint._learner = pPreviousBaseLearner; tmpNodePoint._idx = 0; tmpNodePoint._learnerIdxSet = tmpIdx; calculateChildrenAndEnergies( tmpNodePoint ); } //////////////////////////////////////////////////////// //insert the root into the priority queue if ( tmpNodePoint._extended ) { if (_verbose > 2) { //cout << "Edges: (parent, pos, neg): " << bLearnerVector[0].first << " " << bLearnerVector[1].first << " " << bLearnerVector[2].first << endl << flush; //cout << "alpha[" << (ib) << "] = " << _alpha << endl << flush; cout << "Edges: (parent, pos, neg): " << tmpNodePoint._edge << " " << tmpNodePoint._leftEdge << " " << tmpNodePoint._rightEdge << endl << flush; } // if the energy is getting higher then we push it into the priority queue if ( tmpNodePoint._edge < ( tmpNodePoint._leftEdge + tmpNodePoint._rightEdge ) ) { float deltaEdge = abs( tmpNodePoint._edge - ( tmpNodePoint._leftEdge + tmpNodePoint._rightEdge ) ); innerNode.first = deltaEdge; innerNode.second = tmpNodePoint; pq.push( innerNode ); } else { //delete bLearnerVector[0].second.first.first; delete tmpNodePoint._leftChild; delete tmpNodePoint._rightChild; } } // we cannot extend the root node if ( pq.empty() ) { // we don't extend the root BaseLearner* tmpBL = _baseLearners[0]; _baseLearners[0] = tmpNodePoint._learner; delete tmpBL; ib = 1; } while ( ! pq.empty() && ( ib < _numBaseLearners ) ) { //get the best learner from the priority queue innerNode = pq.top(); if (_verbose > 2) { cout << "Delta edge: " << innerNode.first << endl << flush; cout << "Size of priority queue: " << pq.size() << endl << flush; } pq.pop(); tmpNodePoint = innerNode.second; nodeLeft._edge = tmpNodePoint._leftEdge; nodeLeft._learner = tmpNodePoint._leftChild; nodeLeft._learnerIdxSet = tmpNodePoint._leftChildIdxSet; nodeRight._edge = tmpNodePoint._rightEdge; nodeRight._learner = tmpNodePoint._rightChild; nodeRight._learnerIdxSet = tmpNodePoint._rightChildIdxSet; //store the baselearner if the delta enrgy will be higher if ( _verbose > 3 ) { cout << "Insert learner: " << ib << endl << flush; } int parentIdx = tmpNodePoint._parentIdx; BaseLearner* tmpBL = _baseLearners[ib]; _baseLearners[ib] = tmpNodePoint._learner; delete tmpBL; nodeLeft._parentIdx = ib; nodeRight._parentIdx = ib; nodeLeft._leftOrRightChild = 0; nodeRight._leftOrRightChild = 1; if ( ib > 0 ) { //set the descendant idx _idxPairs[ parentIdx ][ tmpNodePoint._leftOrRightChild ] = ib; } ib++; if ( ib >= _numBaseLearners ) break; //extend positive node if ( nodeLeft._learner ) { calculateChildrenAndEnergies( nodeLeft ); } else { nodeLeft._extended = false; } //calculateChildrenAndEnergies( nodeLeft ); // if the energy is getting higher then we push it into the priority queue if ( nodeLeft._extended ) { if (_verbose > 2) { //cout << "Edges: (parent, pos, neg): " << bLearnerVector[0].first << " " << bLearnerVector[1].first << " " << bLearnerVector[2].first << endl << flush; //cout << "alpha[" << (ib) << "] = " << _alpha << endl << flush; cout << "Edges: (parent, pos, neg): " << nodeLeft._edge << " " << nodeLeft._leftEdge << " " << nodeLeft._rightEdge << endl << flush; } // if the energy is getting higher then we push it into the priority queue if ( nodeLeft._edge < ( nodeLeft._leftEdge + nodeLeft._rightEdge ) ) { float deltaEdge = abs( nodeLeft._edge - ( nodeLeft._leftEdge + nodeLeft._rightEdge ) ); innerNode.first = deltaEdge; innerNode.second = nodeLeft; pq.push( innerNode ); } else { //delete bLearnerVector[0].second.first.first; delete nodeLeft._leftChild; delete nodeLeft._rightChild; if ( ib >= _numBaseLearners ) { delete nodeLeft._learner; break; } else { //this will be a leaf, we do not extend further int parentIdx = nodeLeft._parentIdx; BaseLearner* tmpBL = _baseLearners[ib]; _baseLearners[ib] = nodeLeft._learner; delete tmpBL; _idxPairs[ parentIdx ][ 0 ] = ib; ib += 1; } } } //extend negative node if ( nodeRight._learner ) { calculateChildrenAndEnergies( nodeRight ); } else { nodeRight._extended = false; } // if the energie is getting higher then we push it into the priority queue if ( nodeRight._extended ) { if (_verbose > 2) { cout << "Edges: (parent, pos, neg): " << nodeRight._edge << " " << nodeRight._leftEdge << " " << nodeRight._rightEdge << endl << flush; //cout << "alpha[" << (ib) << "] = " << _alpha << endl << flush; } // if the energie is getting higher then we push it into the priority queue if ( nodeRight._edge < ( nodeRight._leftEdge + nodeRight._rightEdge ) ) { float deltaEdge = abs( nodeRight._edge - ( nodeRight._leftEdge + nodeRight._rightEdge ) ); innerNode.first = deltaEdge; innerNode.second = nodeRight; pq.push( innerNode ); } else { //delete bLearnerVector[0].second.first.first; delete nodeRight._leftChild; delete nodeRight._rightChild; if ( ib >= _numBaseLearners ) { delete nodeRight._learner; break; } else { //this will be a leaf, we do not extend further int parentIdx = nodeRight._parentIdx; BaseLearner* tmpBL = _baseLearners[ib]; _baseLearners[ib] = nodeRight._learner; delete tmpBL; _idxPairs[ parentIdx ][ 1 ] = ib; ib += 1; } } } } for(int ib2 = ib; ib2 < _numBaseLearners; ++ib2) delete _baseLearners[ib2]; _numBaseLearners = ib; if (_verbose > 2) { cout << "Num of learners: " << _numBaseLearners << endl << flush; } //clear the priority queur while ( ! pq.empty() && ( ib < _numBaseLearners ) ) { //get the best learner from the priority queue innerNode = pq.top(); pq.pop(); tmpNodePoint = innerNode.second; delete tmpNodePoint._learner; delete tmpNodePoint._leftChild; delete tmpNodePoint._rightChild; } _id = _baseLearners[0]->getId(); for(int ib = 0; ib < _numBaseLearners; ++ib) _id += "_x_" + _baseLearners[ib]->getId(); //calculate alpha this->_alpha = 0.0; float eps_min = 0.0, eps_pls = 0.0; _pTrainingData->clearIndexSet(); for( int i = 0; i < _pTrainingData->getNumExamples(); i++ ) { vector< Label> l = _pTrainingData->getLabels( i ); for( vector< Label >::iterator it = l.begin(); it != l.end(); it++ ) { float result = this->classify( _pTrainingData, i, it->idx ); if ( ( result * it->y ) < 0 ) eps_min += it->weight; if ( ( result * it->y ) > 0 ) eps_pls += it->weight; } } // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( (float)(1.0 / _pTrainingData->getNumExamples() * 0.01 ) ); this->_alpha = getAlpha( eps_min, eps_pls ); // calculate the energy (sum of the energy of the leaves energy = this->getEnergy( eps_min, eps_pls ); //bandit part we calculate the reward _reward = getRewardFromEdge( getEdge() ); provideRewardForBanditAlgo(); return energy; }
AlphaReal TreeLearner::run() { set< int > tmpIdx, idxPos, idxNeg, origIdx; //ScalarLearner* pCurrentBaseLearner = 0; ScalarLearner* pTmpBaseLearner = 0; int ib = 0; vector< int > tmpVector( 2, -1 ); _pTrainingData->getIndexSet( origIdx ); _pScalaWeakHypothesisSource->setTrainingData(_pTrainingData); //train the first learner NodePoint parentNode, nodeLeft, nodeRight; parentNode._idx = 0; parentNode._parentIdx = -1; parentNode._learnerIdxSet = origIdx; calculateEdgeImprovement( parentNode ); // insert the root if ( parentNode._edgeImprovement <= 0.0 ) // the constant is the best, in this case the treelearner is equivalent to the constant learner { _baseLearners.push_back( parentNode._constantLearner ); _idxPairs.push_back( tmpVector ); this->_alpha = parentNode._constantLearner->getAlpha(); ib++; delete parentNode._learner; return parentNode._constantEnergy; } _baseLearners.push_back( parentNode._learner ); _idxPairs.push_back( tmpVector ); ib++; // put the first two children into the priority queue extendNode( parentNode, nodeLeft, nodeRight ); calculateEdgeImprovement( nodeLeft ); calculateEdgeImprovement( nodeRight ); priority_queue< NodePoint, vector<NodePoint>, greater_first_tree<NodePoint> > pq; pq.push(nodeLeft); pq.push(nodeRight); while ( ! pq.empty() ) { NodePoint currentNode = pq.top(); pq.pop(); if ( _verbose > 3 ) { cout << "Current edge imporvement: " << currentNode._edgeImprovement << endl; } if (currentNode._edgeImprovement>0) { _baseLearners.push_back( currentNode._learner ); _idxPairs.push_back( tmpVector ); //_baseLearners[ib] = currentNode._learner; delete currentNode._constantLearner; } else { _baseLearners.push_back(currentNode._constantLearner); _idxPairs.push_back( tmpVector ); //_baseLearners[ib] = currentNode._constantLearner; delete currentNode._learner; continue; } _idxPairs[ currentNode._parentIdx ][ currentNode._leftOrRightChild ] = ib; currentNode._idx = ib; ib++; if (ib >= _numBaseLearners) break; extendNode( currentNode, nodeLeft, nodeRight ); calculateEdgeImprovement( nodeLeft ); calculateEdgeImprovement( nodeRight ); pq.push(nodeLeft); pq.push(nodeRight); } while ( ! pq.empty() ) { NodePoint currentNode = pq.top(); pq.pop(); if (_verbose>3) cout << "Discarded node's edge improvement: " << currentNode._edgeImprovement << endl; if (currentNode._learner) delete currentNode._learner; delete currentNode._constantLearner; } _id = _baseLearners[0]->getId(); for(int ib = 1; ib < _baseLearners.size(); ++ib) _id += "_x_" + _baseLearners[ib]->getId(); //calculate alpha this->_alpha = 0.0; AlphaReal eps_min = 0.0, eps_pls = 0.0; //_pTrainingData->clearIndexSet(); _pTrainingData->loadIndexSet( origIdx ); for( int i = 0; i < _pTrainingData->getNumExamples(); i++ ) { vector< Label> l = _pTrainingData->getLabels( i ); for( vector< Label >::iterator it = l.begin(); it != l.end(); it++ ) { AlphaReal result = this->classify( _pTrainingData, i, it->idx ); if ( ( result * it->y ) < 0 ) eps_min += it->weight; if ( ( result * it->y ) > 0 ) eps_pls += it->weight; } } // set the smoothing value to avoid numerical problem // when theta=0. setSmoothingVal( (AlphaReal)(1.0 / _pTrainingData->getNumExamples() * 0.01 ) ); this->_alpha = getAlpha( eps_min, eps_pls ); // calculate the energy (sum of the energy of the leaves AlphaReal energy = this->getEnergy( eps_min, eps_pls ); return energy; }