Esempio n. 1
0
	void Bagger::buildTree(){
		int treeId;
		
		// Choose tree id
		m_chooseTree->lock();
		treeId = m_treeId++;
		m_chooseTree->unlock();

		// sorting is performed inside this constructor
		DataCachePtr myData = DataCachePtr(new DataCache(m_data,m_evaluation,m_seed));

		// create the in-bag dataset (and be sure to remember what's in bag)
		// for computing the out-of-bag error later
		DataCachePtr bagData = myData->resample(m_bagSize);
		/*bagData.reusableRandomGenerator = bagData.getRandomNumberGenerator(
				random.nextInt());*/
		m_inBag[treeId] = bagData->inBag;

		// build the classifier
		RandomTreePtr aTree = m_trees[treeId];
		aTree->data = bagData;
		TimerPtr timer = TimerPtr(new boost::timer);
		aTree->build();
		double time = timer->elapsed();

		m_chooseTree->lock();
		m_buildTime += time;
		m_totalNumNodes += aTree->getNumNodes();
		m_chooseTree->unlock();
	}
Esempio n. 2
0
	void GPUERT::deviceHandler(){
		m_devId = m_gfxMgr->createDeviceContext(m_devId);
		calculateMaxNodes(m_devId);
		initResources();

		m_constantsBagging.cb_baggingActivated = false;
		TimerPtr timerKernel = TimerPtr(new boost::timer);

		TimerPtr timer = TimerPtr(new boost::timer);
		TimerPtr timerTotal = TimerPtr(new boost::timer);

		m_internalNodes = 0, m_leafNodes = 0;
		int treesLeft = m_numTrees;
		int treesToLaunch = m_maxTreesPerIteration;
		int lastLaunch = 0;
		int checkSum = m_maxTreesPerIteration;
		int newNodes = m_maxTreesPerIteration;
		std::vector<int> checkVars(4,0);

		m_buildTime = 0;
		m_baggingTime = 0;
		m_classificationTime = 0;
		m_depth = 0;

		timerTotal->restart();
		int numIter = ceil(float(m_numTrees)/float(m_maxTreesPerIteration));
		for(unsigned int j=0; j<numIter; ++j){
			checkSum = treesToLaunch;
			newNodes = treesToLaunch;
			m_constants.cb_nodeBufferStart = 0;
			m_constants.cb_nodeIdFlip = 0;

			initResourceBatch(lastLaunch == treesToLaunch);
			lastLaunch = treesToLaunch;

			treesLeft -= treesToLaunch;
			timer->restart();
			for(unsigned int i=0; i<m_MaxDepth; ++i){
				if(i > m_depth)
					m_depth = i;

				assert(newNodes < m_maxNodesPerIteration);
				int nodeLimit = 10000;
				int innerNodes = newNodes;
				int numInnerIter = ceil(float(innerNodes)/float(nodeLimit));
				int launchCount = 0;

				m_constants.cb_availableNodes = newNodes;
				m_constants.cb_numFeatures = 0;
				timerKernel->restart();
				for(unsigned int k=0; k<m_numFeatures; ++k){
					innerNodes = newNodes;
					numInnerIter = ceil(float(innerNodes)/float(nodeLimit));
					launchCount = 0;

					// Best split kernel
					m_gfxMgr->setGPUBuffer(m_devId,m_setBufferIdsExFindSplit,m_setResourceTypesExFindSplit);
					m_gfxMgr->setGPUProgram(m_devId,m_gpuFunctionIds["RFP_ExFindSplit"]);

					innerNodes = newNodes;
					launchCount = 0;
					m_constants.cb_currentDepth = 0;
					for(unsigned int l=0; l<numInnerIter; ++l){
						launchCount = innerNodes > nodeLimit ? nodeLimit : innerNodes;
						
						m_gfxMgr->copyToGPU(m_devId,m_bufferIds["RFB_constants"],&ConstantUpdate(&m_constants,KID_ExtremeFindSplit),sizeof(m_constants));
						m_gfxMgr->launchComputation(m_devId,launchCount*thread_group_size,1,1);

						m_constants.cb_currentDepth += launchCount;
						innerNodes -= launchCount;
						if(innerNodes <= 0)
							break;
					}
					++m_constants.cb_numFeatures;
				}
				if(m_kernelSpecificTimings){
					m_gfxMgr->syncDevice(m_devId);
					m_kernelTimes[L"RFP_ExFindSplit"] += timerKernel->elapsed();
				}

				innerNodes = newNodes;
				launchCount = 0;
				m_constants.cb_currentDepth = 0;
				m_gfxMgr->setGPUBuffer(m_devId,m_setBufferIdsExMakeSplit,m_setResourceTypesExMakeSplit);
				m_gfxMgr->setGPUProgram(m_devId,m_gpuFunctionIds["RFP_ExMakeSplit"]);

				// Split data
				timerKernel->restart();
				for(unsigned int k=0; k<numInnerIter; ++k){
					launchCount = innerNodes > nodeLimit ? nodeLimit : innerNodes;
						
					m_gfxMgr->copyToGPU(m_devId,m_bufferIds["RFB_constants"],&ConstantUpdate(&m_constants,KID_ExtremeMakeSplit),sizeof(m_constants));
					m_gfxMgr->launchComputation(m_devId,launchCount*thread_group_size,1,1);

					m_constants.cb_currentDepth += launchCount;
					innerNodes -= launchCount;
					if(innerNodes <= 0)
						break;
				}
				if(m_kernelSpecificTimings){
					m_gfxMgr->syncDevice(m_devId);
					m_kernelTimes[L"RFP_ExMakeSplit"] += timerKernel->elapsed();
				}

				// Swap buffer to avoid unecessary copying
				int tmpBuffId = m_bufferIds["RFB_nodeIndices"];
				m_bufferIds["RFB_nodeIndices"] = m_bufferIds["RFB_nodeIndicesMirror"];
				m_bufferIds["RFB_nodeIndicesMirror"] = tmpBuffId;
				setBufferSettings();

				m_constants.cb_currentDepth = i;

				// Evaluate splits
				timerKernel->restart();
				m_gfxMgr->setGPUBuffer(m_devId,m_setBufferIdsExCreateNodes,m_setResourceTypesExCreateNodes);
				m_gfxMgr->copyToGPU(m_devId,m_bufferIds["RFB_constants"],&ConstantUpdate(&m_constants,KID_ExtremeCreateNodes),sizeof(m_constants));
				m_gfxMgr->setGPUProgram(m_devId,m_gpuFunctionIds["RFP_ExCreateNodes"]);
				m_gfxMgr->launchComputation(m_devId,newNodes,1,1);

				// Get continuation variables
				m_gfxMgr->copyFromGPU(m_devId,m_bufferIds["RFB_checkVariables"],&checkVars[0],checkVars.size()*sizeof(int));
				if(m_kernelSpecificTimings){
					m_gfxMgr->syncDevice(m_devId);
					m_kernelTimes[L"RFP_ExCreateNd"] += timerKernel->elapsed();
				}
			
				m_constants.cb_nodeBufferStart = checkSum;
				checkSum = checkVars[2];
				m_leafNodes += checkVars[3];
				newNodes = checkSum;
				m_internalNodes += checkSum;

				checkVars[1] = 0;
				checkVars[2] = 0;
				checkVars[3] = 0;
				m_gfxMgr->copyToGPU(m_devId,m_bufferIds["RFB_checkVariables"],&checkVars[0],checkVars.size()*sizeof(int));
				m_constants.cb_nodeIdFlip = (m_constants.cb_nodeIdFlip == 0) ? 1 : 0;

				if(newNodes <= 0)
					break;
			}
			m_buildTime += timer->elapsed();

			// Vote on test instances
			timer->restart();
			runClassificationProcess(treesToLaunch);
			m_classificationTime += timer->elapsed();

			if(m_saveModel)
				getResultsFromGPU();

			m_data->m_gui->setProgressBar(IDC_PROGRESSBAR_PROGRESS,100,(float(m_numTrees-treesLeft)/float(m_numTrees))*100);
			if(treesLeft != 0 && treesLeft < m_maxTreesPerIteration){
				treesToLaunch = treesLeft;
				m_maxTreesPerIteration = treesToLaunch;
			}
		}

		getVotesFromGPU();
		m_totalTime = timerTotal->elapsed();
		m_bar->wait();
	}
	void ExRandomTrees::run(){
		std::string setting = m_data->m_gui->getEditText(IDC_RANDFOREST_NUMFEATURES);
		
		try{
			m_numFeatures = boost::lexical_cast<int,std::string>(setting);
		}
		catch(...){
			m_numFeatures = (int)log((float)m_document->getNumAttributes())+1;
		}

		if(m_numFeatures == 0)
			m_numFeatures = (int)log((float)m_document->getNumAttributes())+1;

		setting = m_data->m_gui->getEditText(IDC_RANDFOREST_NUMTREES);
		try{
			m_numTrees = boost::lexical_cast<int,std::string>(setting);
		}
		catch(...){
			m_numTrees = 10;
		}

		setting = m_data->m_gui->getEditText(IDC_RANDFOREST_TREEDEPTH);
		try{
			m_maxDepth = boost::lexical_cast<int,std::string>(setting);
		}
		catch(...){
			m_maxDepth = 100;
		}

		setting = m_data->m_gui->getEditText(IDC_RANDFOREST_SEED);
		try{
			m_randomSeed = boost::lexical_cast<int,std::string>(setting);
		}
		catch(...){
			m_randomSeed = 100;
		}

		setting = m_data->m_gui->getEditText(IDC_RANDFOREST_MAXINST);
		try{
			m_minNumInst = boost::lexical_cast<int,std::string>(setting);
		}
		catch(...){
			m_minNumInst = 10;
		}

		m_dataSetTrain.assign(m_document->getNumAttributes(),std::vector<float>(m_evaluation->getNumTrainingInstances(),0));
		m_classSetTrain.assign(m_document->getNumInstances(),0);
		m_dataSetTest.assign(m_document->getNumAttributes(),std::vector<float>(m_evaluation->getNumTestingInstances(),0));
		m_classSetTest.assign(m_evaluation->getNumTestingInstances(),0);
		for(unsigned int a=0; a<m_document->getNumAttributes(); ++a){
			for(unsigned int i=0; i<m_evaluation->getNumTrainingInstances(); ++i){
				m_dataSetTrain[a][i] = m_evaluation->getTrainingInstance(i)->getValue(a);

				if(a == 0)
					m_classSetTrain[i] = m_evaluation->getTrainingInstance(i)->classValue();
			}

			for(unsigned int i=0; i<m_evaluation->getNumTestingInstances(); ++i){
				m_dataSetTest[a][i] = m_evaluation->getTestingInstance(i)->getValue(a);

				if(a == 0)
					m_classSetTest[i] = m_evaluation->getTestingInstance(i)->classValue();
			}
		}

		// Create trees
		ExTree tree = ExTree(m_evaluation->getNumTrainingInstances());
		m_trees.assign(m_numTrees,tree);
		
		// Seed treees
		boost::random::uniform_int_distribution<> indRand(0,INT_MAX);
		boost::random::mt19937 rng;
		rng.seed(m_randomSeed);
		for(unsigned int i=0; i<m_trees.size(); ++i){
			m_trees[i].seed(indRand(rng));
		}

		m_choiceId = 0;
		m_workLeft = m_numTrees;
		m_chooseIdLock = MutexPtr(new boost::mutex);
		m_barrier = BarrierPtr(new boost::barrier(2));

		TM_runFunctionPtr runFunc = TM_runFunctionPtr(new boost::function<void(void)>(std::bind(std::mem_fun(&ExRandomTrees::buildTree),this)));
		TM_callbackFunctionPtr callbackFunc = TM_callbackFunctionPtr(new boost::function<void(int)>(std::bind1st(std::mem_fun(&ExRandomTrees::buildTreeCallback),this)));
		for(size_t treeIdx = 0; treeIdx < m_trees.size(); ++treeIdx) {
			ThreadManager::queueWorkPackage(runFunc,callbackFunc);
		}

		// Start tree building threads
		TimerPtr timer = TimerPtr(new boost::timer);
		ThreadManager::executeWorkQueue();
		// Make sure all trees have been trained before proceeding
		m_barrier->wait();
		m_buildTimer = timer->elapsed();

		evaluateTestSet();
	}
	void ExRandomTrees::evaluateTestSet(){
		m_votes.assign(m_evaluation->getNumTestingInstances()*2,0);
		m_workLeft = m_trees.size();
		m_choiceId = 0;

		TM_runFunctionPtr runFunc = TM_runFunctionPtr(new boost::function<void(void)>(std::bind(std::mem_fun(&ExRandomTrees::collectSingleVote),this)));
		TM_callbackFunctionPtr callbackFunc = TM_callbackFunctionPtr(new boost::function<void(int)>(std::bind1st(std::mem_fun(&ExRandomTrees::buildTreeCallback),this)));
		for(size_t treeIdx = 0; treeIdx < m_trees.size(); ++treeIdx) {
			ThreadManager::queueWorkPackage(runFunc,callbackFunc);
		}

		// Start tree building threads
		TimerPtr timer = TimerPtr(new boost::timer);
		ThreadManager::executeWorkQueue();
		m_barrier->wait();
		m_testTimer = timer->elapsed();

		unsigned int correct = 0,wrong = 0;

		std::map<double,std::vector<bool>,std::greater<double>> rankingcl1,rankingcl2;
		bool truePositive;
		std::vector<int> clCorrect(m_document->getNumClassValues(),0),clWrong(m_document->getNumClassValues(),0);
		std::vector<double> probs(2,0);
		for(size_t i = 0; i < m_evaluation->getNumTestingInstances(); i++) {
			unsigned int vote = m_votes[2*i] > m_votes[2*i+1] ? 0 : 1;
			probs[0] = m_votes[2*i];
			probs[1] = m_votes[2*i+1];

			if(vote == m_classSetTest[i]){
				++clCorrect[m_classSetTest[i]];
				truePositive;
				++correct;
			}
			else{
				++clWrong[m_classSetTest[i]];
				++wrong;
			}

			rankingcl1[double(probs[0])/double(probs[0]+probs[1])].push_back((0 == m_classSetTest[i]));
			rankingcl2[double(probs[1])/double(probs[0]+probs[1])].push_back((1 == m_classSetTest[i]));
		}

		double auc = (m_evaluation->calculateAUC(rankingcl1)+m_evaluation->calculateAUC(rankingcl2))/2.0;

		m_outputStream <<
			"	Time used for building trees: " << m_buildTimer << "s\r\n" <<
			"	Time used for evaluation of trees: " << m_testTimer << "s\r\n";

		m_outputStream	<< 
			"\r\n	"; 

		std::vector<std::vector<unsigned int>> confusMatrix(m_document->getNumClassValues(),std::vector<unsigned int>(m_document->getNumClassValues(),0));
		for(unsigned int i=0; i<m_document->getNumClassValues(); ++i){
			for(unsigned int j=0; j<m_document->getNumClassValues(); ++j){
				if(i == j)
					confusMatrix[i][j] = clCorrect[i];
				else
					confusMatrix[i][j] = clWrong[i];
			}
		}

		for(unsigned int i=0; i<m_document->getNumClassValues(); ++i){
			m_outputStream << i << "	";
		}
		for(unsigned int i=0; i<m_document->getNumClassValues(); ++i){
			m_outputStream << "\r\n	";
			for(unsigned int j=0; j<m_document->getNumClassValues(); ++j){
				m_outputStream  << confusMatrix[i][j] << "	";
			}
			m_outputStream << i;
		}
		m_outputStream << "\r\n";

		double accuracy = double(double(correct)/double(wrong+correct))*100;

		m_outputStream << 
			"\r\n	" << "Accuracy: " << accuracy << "%\r\n";

		PROCESS_MEMORY_COUNTERS pmc;
		GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
		size_t memUsageCPU = pmc.WorkingSetSize;

		m_resultWriter->addKeyValue("accuracy",accuracy);
		m_resultWriter->addKeyValue("cl1Correct",clCorrect[0]);
		m_resultWriter->addKeyValue("cl1Wrong",clWrong[0]);
		m_resultWriter->addKeyValue("cl2Correct",clCorrect[1]);
		m_resultWriter->addKeyValue("cl2Wrong",clWrong[1]);
		m_resultWriter->addKeyValue("trainingTime",m_buildTimer);
		m_resultWriter->addKeyValue("testingTime",m_testTimer);
		m_resultWriter->addKeyValue("totalTime",m_testTimer+m_buildTimer);
		m_resultWriter->addKeyValue("testingInstances",m_evaluation->getNumTestingInstances());
		m_resultWriter->addKeyValue("trainingInstances",m_evaluation->getNumTrainingInstances());
		m_resultWriter->addKeyValue("auc",auc);
		m_resultWriter->addKeyValue("memUsageCPU",double(memUsageCPU)/1024.0/1024.0);
	}