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(); }
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); }