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;
		
	}
Beispiel #2
0
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;							
	}
Beispiel #7
0
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( &currentTime );
						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( &currentTime );
				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;
	}
Beispiel #10
0
	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();
		}				
	}
Beispiel #11
0
		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;

	}
Beispiel #12
0
	//-------------------------------------------------------------------------------
	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;
	}
Beispiel #13
0
	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;
	}