See More

#include "core/global.h" #include "core/config_parser.h" #include "core/timer.h" #include "core/test.h" #include "dataio/sgf.h" #include "search/asyncbot.h" #include "program/setup.h" #include "main.h" #define TCLAP_NAMESTARTSTRING "-" //Use single dashes for all flags #include int MainCmds::writeSearchValueTimeseries(int argc, const char* const* argv) { Board::initHash(); Rand seedRand; string configFile; string nnModelFile; vector sgfsDirs; string outputFile; int numThreads; double usePosProb; string mode; try { TCLAP::CmdLine cmd("Write search value timeseries", ' ', "1.0",true); TCLAP::ValueArg configFileArg("","config-file","Config file to use (see configs/gtp_example.cfg)",true,string(),"FILE"); TCLAP::ValueArg nnModelFileArg("","nn-model-file","Neural net model .pb graph file to use",true,string(),"FILE"); TCLAP::MultiArg sgfsDirsArg("","sgfs-dir","Directory of sgfs files",true,"DIR"); TCLAP::ValueArg outputFileArg("","output-csv","Output csv file",true,string(),"FILE"); TCLAP::ValueArg numThreadsArg("","num-threads","Number of threads to use",true,1,"INT"); TCLAP::ValueArg usePosProbArg("","use-pos-prob","Probability to use a position",true,0.0,"PROB"); TCLAP::ValueArg modeArg("","mode","rootValue|policyTargetSurprise",true,string(),"MODE"); cmd.add(configFileArg); cmd.add(nnModelFileArg); cmd.add(sgfsDirsArg); cmd.add(outputFileArg); cmd.add(numThreadsArg); cmd.add(usePosProbArg); cmd.add(modeArg); cmd.parse(argc,argv); configFile = configFileArg.getValue(); nnModelFile = nnModelFileArg.getValue(); sgfsDirs = sgfsDirsArg.getValue(); outputFile = outputFileArg.getValue(); numThreads = numThreadsArg.getValue(); usePosProb = usePosProbArg.getValue(); mode = modeArg.getValue(); } catch (TCLAP::ArgException &e) { cerr << "Error: " << e.error() << " for argument " << e.argId() << endl; return 1; } if(mode != "rootValue" && mode != "policyTargetSurprise") { cout << "Error: mode must be rootValue or policyTargetSurprise" << endl; return 1; } ConfigParser cfg(configFile); Logger logger; logger.setLogToStdout(true); logger.write("Engine starting..."); NNEvaluator* nnEval; { Setup::initializeSession(cfg); vector nnEvals = Setup::initializeNNEvaluators({nnModelFile},cfg,logger,seedRand); assert(nnEvals.size() == 1); nnEval = nnEvals[0]; } int posLen = nnEval->getPosLen(); logger.write("Loaded neural net"); Rules initialRules; { string koRule = cfg.getString("koRule", Rules::koRuleStrings()); string scoringRule = cfg.getString("scoringRule", Rules::scoringRuleStrings()); bool multiStoneSuicideLegal = cfg.getBool("multiStoneSuicideLegal"); float komi = 7.5f; //Default komi, sgf will generally override this initialRules.koRule = Rules::parseKoRule(koRule); initialRules.scoringRule = Rules::parseScoringRule(scoringRule); initialRules.multiStoneSuicideLegal = multiStoneSuicideLegal; initialRules.komi = komi; } SearchParams params; { vector paramss = Setup::loadParams(cfg); if(paramss.size() != 1) throw StringError("Can only specify examply one search bot in sgf mode"); params = paramss[0]; } //Check for unused config keys { vector unusedKeys = cfg.unusedKeys(); for(size_t i = 0; i sgfsFiles; for(int i = 0; i sgfs = Sgf::loadSgfsFiles(sgfsFiles); cout << "Read " << sgfs.size() << " sgfs!" << endl; { uint64_t numPoses = 0; vector movesBuf; for(size_t i = 0; igetMoves(movesBuf,sgfs[i]->getBSize()); numPoses += movesBuf.size(); movesBuf.clear(); } cout << "Num unique poses: " << numPoses << endl; cout << "(avg moves per game): " << ((double)numPoses / sgfs.size()) << endl; } ofstream out; out.open(outputFile); mutex outMutex; auto computeSurprise = [&](Search* search) { vector locs; vector playSelectionValues; bool suc = search->getPlaySelectionValues(locs,playSelectionValues); testAssert(suc); assert(search->rootNode != NULL); assert(search->rootNode->nnOutput != NULL); float* policyProbs = search->rootNode->nnOutput->policyProbs; assert(locs.size() == playSelectionValues.size()); double sum = 0.0; for(int i = 0; i= 0.0); } assert(sum > 0.0); for(int i = 0; i 1e-50) { Loc loc = locs[i]; int pos = NNPos::locToPos(loc,search->rootBoard.x_size,posLen); //surprise += playSelectionValues[i] * (log(playSelectionValues[i]) - log(policyProbs[pos])); surprise += playSelectionValues[i] * log(policyProbs[pos]); } } return surprise; }; auto runThread = [&](int threadIdx, string randSeed) { Search* search = new Search(params,nnEval,randSeed); int maxVisits; if(mode == "rootValue") maxVisits = 80000; else if(mode == "policyTargetSurprise") maxVisits = 5000; else assert(false); double* values = new double[maxVisits]; double* policySurpriseNats = new double[maxVisits]; Rand rand("root variance estimate " + Global::intToString(threadIdx)); for(size_t sgfIdx = threadIdx; sgfIdxgetBSize(); float komi = sgf->getKomi(); initialRules.komi = komi; vector placements; sgf->getPlacements(placements, bSize); vector moves; sgf->getMoves(moves, bSize); { Board board(bSize,bSize); Player pla = P_BLACK; for(int i = 0; isetPosition(pla,board,hist); } for(size_t moveNum = 0; moveNum < moves.size(); moveNum++) { if(rand.nextDouble() < usePosProb) { SearchThread* stbuf = new SearchThread(0,*search,&logger); search->beginSearch(); for(int i = 0; irunSinglePlayout(*stbuf); values[i] = search->rootNode->stats.getCombinedValueSum(search->searchParams) / search->rootNode->stats.valueSumWeight; policySurpriseNats[i] = computeSurprise(search); } delete stbuf; { float* policy = search->rootNode->nnOutput->policyProbs; double entropy = 0.0; for(int i = 0; i<:nn_policy_size i if continue entropy policy log std::lock_guard> guard(outMutex); out << moveNum << ","; out << entropy << ","; if(mode == "rootValue") { for(int i = 0; imakeMove(moves[moveNum].loc,moves[moveNum].pla); search->clearSearch(); } } delete search; delete[] values; delete[] policySurpriseNats; }; std::thread threads[numThreads]; for(int threadIdx = 0; threadIdx < numThreads; threadIdx++) { threads[threadIdx] = std::thread(runThread, threadIdx, Global::uint64ToString(seedRand.nextUInt64())); } for(int threadIdx = 0; threadIdx < numThreads; threadIdx++) { threads[threadIdx].join(); } out.close(); for(size_t i = 0; i