void BanditSingleSparseStump::init() { const int numClasses = _pTrainingData->getNumClasses(); const int numColumns = _pTrainingData->getNumAttributes(); const int armNumber = _banditAlgo->getArmNumber(); if ( numColumns < armNumber ) { cerr << "The number of colums smaller than the number of the arms!!!!!!" << endl; exit( -1 ); } BaseLearner* pWeakHypothesisSource = BaseLearner::RegisteredLearners().getLearner("SingleSparseStumpLearner"); _banditAlgo->setArmNumber( numColumns ); vector<AlphaReal> initialValues( numColumns ); for( int i=0; i < numColumns; i++ ) { SingleSparseStumpLearner* singleStump = dynamic_cast<SingleSparseStumpLearner*>( pWeakHypothesisSource->create()); singleStump->setTrainingData(_pTrainingData); AlphaReal energy = singleStump->run( i ); AlphaReal edge = singleStump->getEdge(); AlphaReal reward = getRewardFromEdge( (AlphaReal) edge ); initialValues[i] = reward; delete singleStump; } _banditAlgo->initialize( initialValues ); }
// ------------------------------------------------------------------------------ void BanditSingleStumpLearner::estimatePayoffs( vector<AlphaReal>& payoffs ) { set<int> oldIndexSet; set<int> randomIndexSet; const int numExamples = _pTrainingData->getNumExamples(); const int numColumns = _pTrainingData->getNumAttributes(); _pTrainingData->getIndexSet( oldIndexSet ); int numSubset = static_cast<int>( static_cast<double>(numExamples) * _percentage ); if ( numSubset < 2 ) { //use the whole dataset, do nothing } else { for (int j = 0; j < numExamples; ++j) { // Tricky way to select numOfDimensions columns randomly out of numColumns int rest = numExamples - j; AlphaReal r = rand()/static_cast<AlphaReal>(RAND_MAX); if ( static_cast<AlphaReal>(numSubset) / rest > r ) { --numSubset; randomIndexSet.insert( j ); } } _pTrainingData->loadIndexSet( randomIndexSet ); } payoffs.resize( numColumns ); BaseLearner* pWeakHypothesisSource = BaseLearner::RegisteredLearners().getLearner("SingleStumpLearner"); for( int i=0; i < numColumns; i++ ) { if ( payoffs[i] > 0.0 ) continue; SingleStumpLearner* singleStump = dynamic_cast<SingleStumpLearner*>( pWeakHypothesisSource->create()); singleStump->setTrainingData(_pTrainingData); AlphaReal energy = singleStump->run( i ); AlphaReal edge = singleStump->getEdge(); AlphaReal reward = getRewardFromEdge( (float) edge ); payoffs[i] = reward; delete singleStump; } //restore the database _pTrainingData->loadIndexSet( oldIndexSet ); }
//------------------------------------------------------------------------------- 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; }
float BanditProductLearner::run() { if ( ! this->_banditAlgo->isInitialized() ) { init(); } // the bandit algorithm selects the subset the tree learner is allowed to use // the armindexes will be stored in _armsForPulling getArms(); const int numClasses = _pTrainingData->getNumClasses(); const int numExamples = _pTrainingData->getNumExamples(); // Backup original labels for (int i = 0; i < numExamples; ++i) { const vector<Label>& labels = _pTrainingData->getLabels(i); vector<char> exampleLabels; for (int l = 0; l < numClasses; ++l) exampleLabels.push_back(labels[l].y); _savedLabels.push_back(exampleLabels); } for(int ib = 0; ib < _numBaseLearners; ++ib) _baseLearners[ib]->setTrainingData(_pTrainingData); float energy = numeric_limits<float>::max(); float previousEnergy, hx, previousAlpha; BaseLearner* pPreviousBaseLearner = 0; bool firstLoop = true; int ib = -1; while (1) { ib += 1; if (ib >= _numBaseLearners) { ib = 0; firstLoop = false; } previousEnergy = energy; previousAlpha = _alpha; if (pPreviousBaseLearner) delete pPreviousBaseLearner; if ( !firstLoop ) { // take the old learner off the labels for (int i = 0; i < numExamples; ++i) { vector<Label>& labels = _pTrainingData->getLabels(i); for (int l = 0; l < numClasses; ++l) { // Here we could have the option of using confidence rated setting so the // real valued output of classify instead of its sign hx = _baseLearners[ib]->classify(_pTrainingData,i,l); if ( hx < 0 ) labels[l].y *= -1; else if ( hx == 0 ) { // have to redo the multiplications, haven't been tested for(int ib1 = 0; ib1 < _numBaseLearners && labels[l].y != 0; ++ib1) { if (ib != ib1) { hx = _baseLearners[ib1]->classify(_pTrainingData,i,l); if (hx < 0) labels[l].y *= -1; else if (hx == 0) labels[l].y = 0; } } } } } } pPreviousBaseLearner = _baseLearners[ib]->copyState(); energy = dynamic_cast< FeaturewiseLearner* >(_baseLearners[ib])->run(_armsForPulling ); // check if it is signailing_nan if ( energy != energy ) { if (_verbose > 2) { cout << "Cannot find weak hypothesis, constant learner is used!!" << endl; } BaseLearner* pConstantWeakHypothesisSource = BaseLearner::RegisteredLearners().getLearner("ConstantLearner"); BaseLearner* pConstantWeakHypothesis = pConstantWeakHypothesisSource->create() ; pConstantWeakHypothesis->setTrainingData( _pTrainingData ); energy = pConstantWeakHypothesis->run(); delete _baseLearners[ib]; _baseLearners[ib] = pConstantWeakHypothesis; } _alpha = _baseLearners[ib]->getAlpha(); if (_verbose > 2) { cout << "E[" << (ib+1) << "] = " << energy << endl << flush; cout << "alpha[" << (ib+1) << "] = " << _alpha << endl << flush; } for (int i = 0; i < numExamples; ++i) { vector<Label>& labels = _pTrainingData->getLabels(i); for (int l = 0; l < numClasses; ++l) { // Here we could have the option of using confidence rated setting so the // real valued output of classify instead of its sign if (labels[l].y != 0) { // perhaps replace it by nor_utils::is_zero(labels[l].y) hx = _baseLearners[ib]->classify(_pTrainingData,i,l); if ( hx < 0 ) labels[l].y *= -1; else if ( hx == 0 ) labels[l].y = 0; } } } // We have to do at least one full iteration. For real it's not guaranteed // Alternatively we could initialize all of them to constant // if ( !firstLoop && energy >= previousEnergy ) { // if (energy > previousEnergy) { // _baseLearners[ib] = pPreviousBaseLearner->copyState(); // delete pPreviousBaseLearner; // energy = previousEnergy; // _alpha = _baseLearners[ib]->getAlpha(); // } // break; // } if ( energy >= previousEnergy ) { _alpha = previousAlpha; energy = previousEnergy; if (firstLoop) { for(int ib2 = ib; ib2 < _numBaseLearners; ++ib2) delete _baseLearners[ib2]; _numBaseLearners = ib; } else { _baseLearners[ib] = pPreviousBaseLearner->copyState(); } delete pPreviousBaseLearner; break; } } // Restore original labels for (int i = 0; i < numExamples; ++i) { vector<Label>& labels = _pTrainingData->getLabels(i); for (int l = 0; l < numClasses; ++l) labels[l].y = _savedLabels[i][l]; } _id = _baseLearners[0]->getId(); for(int ib = 1; ib < _numBaseLearners; ++ib) _id += "_x_" + _baseLearners[ib]->getId(); //bandit part we calculate the reward _reward = getRewardFromEdge( getEdge() ); provideRewardForBanditAlgo(); return energy; }