working version with json analysis engine

This commit is contained in:
Sander Land committed 2020-01-25 16:51:27 +01:00
1 parent ff1db55a97
commit da5d99194b
9 files changed
+68 -703

No files matched your search

-305
View File
@@ -1,305 +0,0 @@
# Example config for C++ (non-python) gtp bot
# RUNNING ON AN ONLINE SERVER OR IN A REAL TOURNAMENT OR MATCH:
# If you plan to do so, you may want to read through the "Rules" section
# below carefully for proper handling of komi and handicap games and end-of-game cleanup
# and various other details.
# NOTES ABOUT PERFORMANCE AND MEMORY USAGE:
# You will likely want to tune one or more the following:
#
# numSearchThreads:
# The number of CPU threads to use. If your GPU is powerful, it can actually be much higher than
# the number of cores on your processor because you will need many threads to feed large enough
# batches to make good use of the GPU.
#
# The "./katago benchmark" command can help you tune this parameter, as well as to test out the effect
# of changes to any of the other parameters below!
#
# nnMaxBatchSize:
# The maximum GPU batch size. Should often be at least as large as numSearchThreads.
# Larger won't do anything, but also won't hurt except use a little bit more GPU memory.
# Smaller can be fine if you have more than one GPU, since the GPUs will be sharing the work
# of servicing the CPU threads.
#
# cudaUseFP16 and cudaUseNHWC:
# These have a good chance of improving peformance at larger threads/batch sizes if
# you are using the CUDA implementation with an NVIDIA GPU with FP16 tensor cores.
#
# nnCacheSizePowerOfTwo:
# This controls the NN Cache size, which is the primary RAM/memory use.
# Increase this if you don't mind the memory use and want better performance for searches with
# tens of thousands of visits or more. Decrease this if you want to limit memory usage.
#
# If you're someone who is happy to do a bit of math - each neural net entry takes very
# approximately 1.5KB, except when using whole-board ownership/territory visualizations, each
# entry will take very approximately 3KB. The number of entries is (2 ** nnCacheSizePowerOfTwo),
# for example 2 ** 18 = 262144.
#
# OTHER NOTES:
# If you have more than one GPU, take a look at "OpenCL GPU settings" or "CUDA GPU settings" below.
#
# If using OpenCL, you will want to verify that KataGo is picking up the correct device!
# (e.g. some systems may have both an Intel CPU OpenCL and GPU OpenCL, if KataGo appears to pick
# the wrong one, you correct this by specifying "openclGpuToUse" below).
#
# You may also want to adjust "maxVisits", "ponderingEnabled", "resignThreshold", and possibly
# other parameters depending on your intended usage.
# Logs------------------------------------------------------------------------------------
# Where to output log?
logFile = gtp.log
# Logging options
logAllGTPCommunication = true
logSearchInfo = true
logToStderr = false
# KataGo will display some info to stderr on GTP startup
# Uncomment this to suppress that and remain silent
# startupPrintMessageToStderr = false
# Chat some stuff to stderr, for use in things like malkovich chat to OGS.
# ogsChatToStderr = true
# Configure the maximum length of analysis printed out by lz-analyze and other places.
# Controls the number of moves after the first move in a variation.
# analysisPVLen = 9
# Report winrates for chat and analysis as (BLACK|WHITE|SIDETOMOVE).
# Default is SIDETOMOVE, which is what tools that use LZ probably also expect
# reportAnalysisWinratesAs = SIDETOMOVE
# Default rules------------------------------------------------------------------------------------
# See https://lightvector.github.io/KataGo/rules.html for a description of the rules.
# These rules are defaults and can be changed mid-run by several custom GTP commands.
# See https://github.com/lightvector/KataGo/blob/master/docs/GTP_Extensions.md for those commands.
# koRule = SIMPLE # Simple ko rules (triple ko = no result)
koRule = POSITIONAL # Positional superko
# koRule = SITUATIONAL # Situational superko
scoringRule = AREA # Area scoring
# scoringRule = TERRITORY # Territory scoring (uses a sort of special computer-friendly territory ruleset)
taxRule = NONE # All surrounded empty points are scored
# taxRule = SEKI # Eyes in seki do NOT count as points
# taxRule = ALL # All groups are taxed up to 2 points for the two eyes needed to live
multiStoneSuicideLegal = true #Is multiple-stone suicide legal? (Single-stone suicide is always illegal).
hasButton = false # Set to true when area scoring to award 0.5 points to the first pass.
whiteHandicapBonus = 0 # In handicap games, give white no compensation for black's handicap stones (Tromp-taylor, NZ, JP)
# whiteHandicapBonus = N-1 # In handicap games, give white N-1 points for black's handicap stones (AGA)
# whiteHandicapBonus = N # In handicap games, give white N points for black's handicap stones (Chinese)
# Bot behavior---------------------------------------------------------------------------------------
# Resignation -------------
# Resignation occurs if for at least resignConsecTurns in a row,
# the winLossUtility (which is on a [-1,1] scale) is below resignThreshold.
allowResignation = true
resignThreshold = -0.98
resignConsecTurns = 3
# Handicap -------------
# Assume that if black makes many moves in a row right at the start of the game, then the game is a handicap game.
# This is necessary on some servers and for some GUIs and also when initializing from many SGF files, which may
# set up a handicap games using repeated GTP "play" commands for black rather than GTP "place_free_handicap" commands.
# However, it may also lead to incorrect understanding of komi if whiteHandicapBonus is used and a server does NOT
# have such a practice.
# Defaults to true! Uncomment and set to false to disable this behavior.
# assumeMultipleStartingBlackMovesAreHandicap = true
# Makes katago dynamically adjust to play more aggressively in handicap games based on the handicap and the current state of the game.
# Comment to disable this and make KataGo play the same always.
dynamicPlayoutDoublingAdvantageCapPerOppLead = 0.04
# Instead of setting dynamicPlayoutDoublingAdvantageCapPerOppLead, you can uncomment these and set this to a value from -2.0 to 2.0
# to set KataGo's aggression to a FIXED level.
# Negative makes KataGo behave as if it is much weaker than the opponent, preferring to play defensively
# Positive makes KataGo behave as if it is much stronger than the opponent, prefering to play aggressively or even overplay slightly.
# playoutDoublingAdvantage = 0.0
# Controls which side dynamicPlayoutDoublingAdvantageCapPerOppLead or playoutDoublingAdvantage applies to.
playoutDoublingAdvantagePla = WHITE
# Passing and cleanup -------------
# Make the bot never assume that its pass will end the game, even if passing would end and "win" under Tromp-Taylor rules.
# Usually this is a good idea when using it for analysis or playing on servers where scoring may be implemented non-tromp-taylorly.
# Defaults to true! Uncomment and set to false to disable this.
# conservativePass = true
# When playing under territory scoring, encourage the bot to fill dame before passing.
# This is NOT absolutely guaranteed to work, and possibly in some rare pathological situations will make the bot
# play a bad move, losing points. However, it also acts as a safeguard against things like a situation when the opponent must
# eventually make a protective move and lose 1 point, where the bot might otherwise assume that the score would be counted as such,
# yet without filling the dame to force the opponent to actually make the move.
# Defaults to true! Uncomment and set to false to disable this.
# fillDameBeforePass = true
# When using territory scoring, self-play games continue beyond two passes with special cleanup
# rules that may be confusing for human players. This option prevents the special cleanup phases from being
# reachable when using the bot for GTP play.
# Defaults to true! Uncomment and set to false if you want KataGo to be able to enter special cleanup.
# For example, if you are testing it against itself, or against another bot that has precisely implemented the rules
# documented at https://lightvector.github.io/KataGo/rules.html
# preventCleanupPhase = true
# Search limits-----------------------------------------------------------------------------------
# If provided, limit maximum number of root visits per search to this much. (With tree reuse, visits do count earlier search)
maxVisits = 500
# If provided, limit maximum number of new playouts per search to this much. (With tree reuse, playouts do not count earlier search)
# maxPlayouts = 300
# If provided, cap search time at this many seconds (search will still try to follow GTP time controls)
# maxTime = 60
# Ponder on the opponent's turn?
ponderingEnabled = false
# Same limits but for ponder searches if pondering is enabled
# maxVisitsPondering = 1000
# maxPlayoutsPondering = 1000
# maxTimePondering = 60
# Number of seconds to buffer for lag for GTP time controls
lagBuffer = 1.0
# Number of threads to use in search
numSearchThreads = 1
# Play a little faster if the opponent is passing, for friendliness
searchFactorAfterOnePass = 0.50
searchFactorAfterTwoPass = 0.25
# Play a little faster if super-winning, for friendliess
searchFactorWhenWinning = 0.40
searchFactorWhenWinningThreshold = 0.95
# GPU Settings-------------------------------------------------------------------------------
# Maximum number of positions to send to GPU at once. Note that you will also need to increase numSearchThreads
# to make use of this, as every thread in KataGo is synchronous, so with 1 thread max batch will only be 1 anyways.
nnMaxBatchSize = 16
# Cache up to 2 ** this many neural net evaluations in case of transpositions in the tree.
nnCacheSizePowerOfTwo = 19
# Size of mutex pool for nnCache is 2 ** this
nnMutexPoolSizePowerOfTwo = 15
# Randomize board orientation when running neural net evals?
nnRandomize = true
# If provided, force usage of a specific seed for nnRandomize instead of randomizing
# nnRandSeed = abcdefg
# How many threads should there be to feed positions to the neural net?
# Server threads are indexed 0,1,...(n-1) for the purposes of the below GPU settings arguments
# that specify which threads should use which GPUs.
# NOTE: This parameter is probably ONLY useful if you have multiple GPUs, since each GPU will need a thread.
# If you're tuning single-GPU performance, use numSearchThreads instead.
numNNServerThreadsPerModel = 1
# CUDA GPU settings--------------------------------------
# These only apply when using CUDA as the backend for inference.
# (For GTP, we only ever have one model, when playing matches, we might have more than one, see match_example.cfg)
# Default behavior tries to guess the 'best' GPU or device
# You will want to uncomment and adjust one or more of these lines to take advantage of a multi-gpu machine
# cudaDeviceToUse = 0 #use device 0 for all server threads (numNNServerThreadsPerModel) unless otherwise specified per-model or per-thread-per-model
# cudaDeviceToUseModel0 = 3 #use device 3 for model 0 for all threads unless otherwise specified per-thread for this model
# cudaDeviceToUseModel1 = 2 #use device 2 for model 1 for all threads unless otherwise specified per-thread for this model
# cudaDeviceToUseModel0Thread0 = 3 #use device 3 for model 0, server thread 0
# cudaDeviceToUseModel0Thread1 = 2 #use device 2 for model 0, server thread 1
# Uncomment these on NVIDIA devices with FP16 tensor cores for probably a speedup, at the cost of introducing some precision loss in the nn calculation.
# cudaUseFP16 = true
# cudaUseNHWC = true
# OpenCL GPU settings--------------------------------------
# These only apply when using OpenCL as the backend for inference.
# (For GTP, we only ever have one model, when playing matches, we might have more than one, see match_example.cfg)
# Default behavior tries to guess the 'best' GPU or device
# You will want to uncomment and adjust one or more of these lines to take advantage of a multi-gpu machine
# openclDeviceToUse = 0 #use device 0 for all server threads (numNNServerThreadsPerModel) unless otherwise specified per-model or per-thread-per-model
# openclDeviceToUseModel0 = 3 #use device 3 for model 0 for all threads unless otherwise specified per-thread for this model
# openclDeviceToUseModel1 = 2 #use device 2 for model 1 for all threads unless otherwise specified per-thread for this model
# openclDeviceToUseModel0Thread0 = 3 #use device 3 for model 0, server thread 0
# openclDeviceToUseModel0Thread1 = 2 #use device 2 for model 0, server thread 1
# Uncomment to tune OpenCL for every board size separately, rather than only the largest possible size
# openclReTunePerBoardSize = true
# Root move selection and biases------------------------------------------------------------------------------
# If provided, force usage of a specific seed for various things in the search instead of randomizing
# searchRandSeed = hijklmn
# Temperature for the early game, randomize between chosen moves with this temperature
chosenMoveTemperatureEarly = 0.5
# Decay temperature for the early game by 0.5 every this many moves, scaled with board size.
chosenMoveTemperatureHalflife = 19
# At the end of search after the early game, randomize between chosen moves with this temperature
chosenMoveTemperature = 0.10
# Subtract this many visits from each move prior to applying chosenMoveTemperature
# (unless all moves have too few visits) to downweight unlikely moves
chosenMoveSubtract = 0
# The same as chosenMoveSubtract but only prunes moves that fall below the threshold, does not affect moves above
chosenMovePrune = 1
# Use dirichlet noise for the root node policy?
rootNoiseEnabled = false
# Dirichlet noise alpha is set to this divided by number of legal moves. 10.83 produces an alpha of 0.03 on an empty 19x19 board.
rootDirichletNoiseTotalConcentration = 10.83
# Proportion of root policy that is noise
rootDirichletNoiseWeight = 0.25
# Number of symmetries to sample (WITH replacement) and average at the root
rootNumSymmetriesToSample = 1
# Using LCB for move selection?
useLcbForSelection = true
# How many stdevs a move needs to be better than another for LCB selection
lcbStdevs = 5.0
# Only use LCB override when a move has this proportion of visits as the top move
minVisitPropForLCB = 0.15
# Internal params------------------------------------------------------------------------------
# Scales the utility of winning/losing
winLossUtilityFactor = 1.0
# Scales the utility for trying to maximize score
staticScoreUtilityFactor = 0.10
dynamicScoreUtilityFactor = 0.30
# Adjust dynamic score center this proportion of the way towards zero, capped at a reasonable amount.
dynamicScoreCenterZeroWeight = 0.20
dynamicScoreCenterScale = 0.75
# The utility of getting a "no result" due to triple ko or other long cycle in non-superko rulesets (-1 to 1)
noResultUtilityForWhite = 0.0
# The number of wins that a draw counts as, for white. (0 to 1)
drawEquivalentWinsForWhite = 0.5
# Exploration constant for mcts
cpuctExploration = 0.9
cpuctExplorationLog = 0.6
# FPU reduction constant for mcts
fpuReductionMax = 0.2
rootFpuReductionMax = 0.1
# Use parent average value for fpu base point instead of point value net estimate
fpuUseParentAverage = true
# Amount to apply a downweighting of children with very bad values relative to good ones
valueWeightExponent = 0.5
# Slight incentive for the bot to behave human-like with regard to passing at the end, filling the dame,
# not wasting time playing in its own territory, etc, and not play moves that are equivalent in terms of
# points but a bit more unfriendly to humans.
rootEndingBonusPoints = 0.5
# Make the bot prune useless moves that are just prolonging the game to avoid losing yet
rootPruneUselessMoves = true
# How big to make the mutex pool for search synchronization
mutexPoolSize = 8192
# How many virtual losses to add when a thread descends through a node
numVirtualLossesPerThread = 1
-305
View File
@@ -1,305 +0,0 @@
# Example config for C++ (non-python) gtp bot
# RUNNING ON AN ONLINE SERVER OR IN A REAL TOURNAMENT OR MATCH:
# If you plan to do so, you may want to read through the "Rules" section
# below carefully for proper handling of komi and handicap games and end-of-game cleanup
# and various other details.
# NOTES ABOUT PERFORMANCE AND MEMORY USAGE:
# You will likely want to tune one or more the following:
#
# numSearchThreads:
# The number of CPU threads to use. If your GPU is powerful, it can actually be much higher than
# the number of cores on your processor because you will need many threads to feed large enough
# batches to make good use of the GPU.
#
# The "./katago benchmark" command can help you tune this parameter, as well as to test out the effect
# of changes to any of the other parameters below!
#
# nnMaxBatchSize:
# The maximum GPU batch size. Should often be at least as large as numSearchThreads.
# Larger won't do anything, but also won't hurt except use a little bit more GPU memory.
# Smaller can be fine if you have more than one GPU, since the GPUs will be sharing the work
# of servicing the CPU threads.
#
# cudaUseFP16 and cudaUseNHWC:
# These have a good chance of improving peformance at larger threads/batch sizes if
# you are using the CUDA implementation with an NVIDIA GPU with FP16 tensor cores.
#
# nnCacheSizePowerOfTwo:
# This controls the NN Cache size, which is the primary RAM/memory use.
# Increase this if you don't mind the memory use and want better performance for searches with
# tens of thousands of visits or more. Decrease this if you want to limit memory usage.
#
# If you're someone who is happy to do a bit of math - each neural net entry takes very
# approximately 1.5KB, except when using whole-board ownership/territory visualizations, each
# entry will take very approximately 3KB. The number of entries is (2 ** nnCacheSizePowerOfTwo),
# for example 2 ** 18 = 262144.
#
# OTHER NOTES:
# If you have more than one GPU, take a look at "OpenCL GPU settings" or "CUDA GPU settings" below.
#
# If using OpenCL, you will want to verify that KataGo is picking up the correct device!
# (e.g. some systems may have both an Intel CPU OpenCL and GPU OpenCL, if KataGo appears to pick
# the wrong one, you correct this by specifying "openclGpuToUse" below).
#
# You may also want to adjust "maxVisits", "ponderingEnabled", "resignThreshold", and possibly
# other parameters depending on your intended usage.
# Logs------------------------------------------------------------------------------------
# Where to output log?
logFile = gtp.log
# Logging options
logAllGTPCommunication = true
logSearchInfo = true
logToStderr = false
# KataGo will display some info to stderr on GTP startup
# Uncomment this to suppress that and remain silent
# startupPrintMessageToStderr = false
# Chat some stuff to stderr, for use in things like malkovich chat to OGS.
# ogsChatToStderr = true
# Configure the maximum length of analysis printed out by lz-analyze and other places.
# Controls the number of moves after the first move in a variation.
# analysisPVLen = 9
# Report winrates for chat and analysis as (BLACK|WHITE|SIDETOMOVE).
# Default is SIDETOMOVE, which is what tools that use LZ probably also expect
# reportAnalysisWinratesAs = SIDETOMOVE
# Default rules------------------------------------------------------------------------------------
# See https://lightvector.github.io/KataGo/rules.html for a description of the rules.
# These rules are defaults and can be changed mid-run by several custom GTP commands.
# See https://github.com/lightvector/KataGo/blob/master/docs/GTP_Extensions.md for those commands.
koRule = SIMPLE # Simple ko rules (triple ko = no result)
# koRule = POSITIONAL # Positional superko
# koRule = SITUATIONAL # Situational superko
# scoringRule = AREA # Area scoring
scoringRule = TERRITORY # Territory scoring (uses a sort of special computer-friendly territory ruleset)
# taxRule = NONE # All surrounded empty points are scored
taxRule = SEKI # Eyes in seki do NOT count as points
# taxRule = ALL # All groups are taxed up to 2 points for the two eyes needed to live
multiStoneSuicideLegal = false #Is multiple-stone suicide legal? (Single-stone suicide is always illegal).
hasButton = false # Set to true when area scoring to award 0.5 points to the first pass.
whiteHandicapBonus = 0 # In handicap games, give white no compensation for black's handicap stones (Tromp-taylor, NZ, JP)
# whiteHandicapBonus = N-1 # In handicap games, give white N-1 points for black's handicap stones (AGA)
# whiteHandicapBonus = N # In handicap games, give white N points for black's handicap stones (Chinese)
# Bot behavior---------------------------------------------------------------------------------------
# Resignation -------------
# Resignation occurs if for at least resignConsecTurns in a row,
# the winLossUtility (which is on a [-1,1] scale) is below resignThreshold.
allowResignation = true
resignThreshold = -0.999
resignConsecTurns = 3
# Handicap -------------
# Assume that if black makes many moves in a row right at the start of the game, then the game is a handicap game.
# This is necessary on some servers and for some GUIs and also when initializing from many SGF files, which may
# set up a handicap games using repeated GTP "play" commands for black rather than GTP "place_free_handicap" commands.
# However, it may also lead to incorrect understanding of komi if whiteHandicapBonus is used and a server does NOT
# have such a practice.
# Defaults to true! Uncomment and set to false to disable this behavior.
# assumeMultipleStartingBlackMovesAreHandicap = true
# Makes katago dynamically adjust to play more aggressively in handicap games based on the handicap and the current state of the game.
# Comment to disable this and make KataGo play the same always.
dynamicPlayoutDoublingAdvantageCapPerOppLead = 0.04
# Instead of setting dynamicPlayoutDoublingAdvantageCapPerOppLead, you can uncomment these and set this to a value from -2.0 to 2.0
# to set KataGo's aggression to a FIXED level.
# Negative makes KataGo behave as if it is much weaker than the opponent, preferring to play defensively
# Positive makes KataGo behave as if it is much stronger than the opponent, prefering to play aggressively or even overplay slightly.
# playoutDoublingAdvantage = 0.0
# Controls which side dynamicPlayoutDoublingAdvantageCapPerOppLead or playoutDoublingAdvantage applies to.
playoutDoublingAdvantagePla = WHITE
# Passing and cleanup -------------
# Make the bot never assume that its pass will end the game, even if passing would end and "win" under Tromp-Taylor rules.
# Usually this is a good idea when using it for analysis or playing on servers where scoring may be implemented non-tromp-taylorly.
# Defaults to true! Uncomment and set to false to disable this.
conservativePass = true
# When playing under territory scoring, encourage the bot to fill dame before passing.
# This is NOT absolutely guaranteed to work, and possibly in some rare pathological situations will make the bot
# play a bad move, losing points. However, it also acts as a safeguard against things like a situation when the opponent must
# eventually make a protective move and lose 1 point, where the bot might otherwise assume that the score would be counted as such,
# yet without filling the dame to force the opponent to actually make the move.
# Defaults to true! Uncomment and set to false to disable this.
# fillDameBeforePass = true
# When using territory scoring, self-play games continue beyond two passes with special cleanup
# rules that may be confusing for human players. This option prevents the special cleanup phases from being
# reachable when using the bot for GTP play.
# Defaults to true! Uncomment and set to false if you want KataGo to be able to enter special cleanup.
# For example, if you are testing it against itself, or against another bot that has precisely implemented the rules
# documented at https://lightvector.github.io/KataGo/rules.html
# preventCleanupPhase = true
# Search limits-----------------------------------------------------------------------------------
# If provided, limit maximum number of root visits per search to this much. (With tree reuse, visits do count earlier search)
maxVisits = 2500
# If provided, limit maximum number of new playouts per search to this much. (With tree reuse, playouts do not count earlier search)
# maxPlayouts = 300
# If provided, cap search time at this many seconds (search will still try to follow GTP time controls)
# maxTime = 60
# Ponder on the opponent's turn?
ponderingEnabled = false
# Same limits but for ponder searches if pondering is enabled
# maxVisitsPondering = 1000
# maxPlayoutsPondering = 1000
# maxTimePondering = 60
# Number of seconds to buffer for lag for GTP time controls
lagBuffer = 1.0
# Number of threads to use in search
numSearchThreads = 4
# Play a little faster if the opponent is passing, for friendliness
searchFactorAfterOnePass = 0.50
searchFactorAfterTwoPass = 0.25
# Play a little faster if super-winning, for friendliess
searchFactorWhenWinning = 0.40
searchFactorWhenWinningThreshold = 0.95
# GPU Settings-------------------------------------------------------------------------------
# Maximum number of positions to send to GPU at once. Note that you will also need to increase numSearchThreads
# to make use of this, as every thread in KataGo is synchronous, so with 1 thread max batch will only be 1 anyways.
nnMaxBatchSize = 16
# Cache up to 2 ** this many neural net evaluations in case of transpositions in the tree.
nnCacheSizePowerOfTwo = 20
# Size of mutex pool for nnCache is 2 ** this
nnMutexPoolSizePowerOfTwo = 16
# Randomize board orientation when running neural net evals?
nnRandomize = true
# If provided, force usage of a specific seed for nnRandomize instead of randomizing
# nnRandSeed = abcdefg
# How many threads should there be to feed positions to the neural net?
# Server threads are indexed 0,1,...(n-1) for the purposes of the below GPU settings arguments
# that specify which threads should use which GPUs.
# NOTE: This parameter is probably ONLY useful if you have multiple GPUs, since each GPU will need a thread.
# If you're tuning single-GPU performance, use numSearchThreads instead.
numNNServerThreadsPerModel = 1
# CUDA GPU settings--------------------------------------
# These only apply when using CUDA as the backend for inference.
# (For GTP, we only ever have one model, when playing matches, we might have more than one, see match_example.cfg)
# Default behavior tries to guess the 'best' GPU or device
# You will want to uncomment and adjust one or more of these lines to take advantage of a multi-gpu machine
# cudaDeviceToUse = 0 #use device 0 for all server threads (numNNServerThreadsPerModel) unless otherwise specified per-model or per-thread-per-model
# cudaDeviceToUseModel0 = 3 #use device 3 for model 0 for all threads unless otherwise specified per-thread for this model
# cudaDeviceToUseModel1 = 2 #use device 2 for model 1 for all threads unless otherwise specified per-thread for this model
# cudaDeviceToUseModel0Thread0 = 3 #use device 3 for model 0, server thread 0
# cudaDeviceToUseModel0Thread1 = 2 #use device 2 for model 0, server thread 1
# Uncomment these on NVIDIA devices with FP16 tensor cores for probably a speedup, at the cost of introducing some precision loss in the nn calculation.
# cudaUseFP16 = true
# cudaUseNHWC = true
# OpenCL GPU settings--------------------------------------
# These only apply when using OpenCL as the backend for inference.
# (For GTP, we only ever have one model, when playing matches, we might have more than one, see match_example.cfg)
# Default behavior tries to guess the 'best' GPU or device
# You will want to uncomment and adjust one or more of these lines to take advantage of a multi-gpu machine
# openclDeviceToUse = 0 #use device 0 for all server threads (numNNServerThreadsPerModel) unless otherwise specified per-model or per-thread-per-model
# openclDeviceToUseModel0 = 3 #use device 3 for model 0 for all threads unless otherwise specified per-thread for this model
# openclDeviceToUseModel1 = 2 #use device 2 for model 1 for all threads unless otherwise specified per-thread for this model
# openclDeviceToUseModel0Thread0 = 3 #use device 3 for model 0, server thread 0
# openclDeviceToUseModel0Thread1 = 2 #use device 2 for model 0, server thread 1
# Uncomment to tune OpenCL for every board size separately, rather than only the largest possible size
# openclReTunePerBoardSize = true
# Root move selection and biases------------------------------------------------------------------------------
# If provided, force usage of a specific seed for various things in the search instead of randomizing
# searchRandSeed = hijklmn
# Temperature for the early game, randomize between chosen moves with this temperature
chosenMoveTemperatureEarly = 0.5
# Decay temperature for the early game by 0.5 every this many moves, scaled with board size.
chosenMoveTemperatureHalflife = 19
# At the end of search after the early game, randomize between chosen moves with this temperature
chosenMoveTemperature = 0.10
# Subtract this many visits from each move prior to applying chosenMoveTemperature
# (unless all moves have too few visits) to downweight unlikely moves
chosenMoveSubtract = 0
# The same as chosenMoveSubtract but only prunes moves that fall below the threshold, does not affect moves above
chosenMovePrune = 1
# Use dirichlet noise for the root node policy?
rootNoiseEnabled = false
# Dirichlet noise alpha is set to this divided by number of legal moves. 10.83 produces an alpha of 0.03 on an empty 19x19 board.
rootDirichletNoiseTotalConcentration = 10.83
# Proportion of root policy that is noise
rootDirichletNoiseWeight = 0.25
# Number of symmetries to sample (WITH replacement) and average at the root
rootNumSymmetriesToSample = 1
# Using LCB for move selection?
useLcbForSelection = true
# How many stdevs a move needs to be better than another for LCB selection
lcbStdevs = 5.0
# Only use LCB override when a move has this proportion of visits as the top move
minVisitPropForLCB = 0.15
# Internal params------------------------------------------------------------------------------
# Scales the utility of winning/losing
winLossUtilityFactor = 0.4
# Scales the utility for trying to maximize score
staticScoreUtilityFactor = 0.2
dynamicScoreUtilityFactor = 0.4
# Adjust dynamic score center this proportion of the way towards zero, capped at a reasonable amount.
dynamicScoreCenterZeroWeight = 0.20
dynamicScoreCenterScale = 0.75
# The utility of getting a "no result" due to triple ko or other long cycle in non-superko rulesets (-1 to 1)
noResultUtilityForWhite = 0.0
# The number of wins that a draw counts as, for white. (0 to 1)
drawEquivalentWinsForWhite = 0.5
# Exploration constant for mcts
cpuctExploration = 2.0
cpuctExplorationLog = 0.8
# FPU reduction constant for mcts
fpuReductionMax = 0.2
rootFpuReductionMax = 0.1
# Use parent average value for fpu base point instead of point value net estimate
fpuUseParentAverage = true
# Amount to apply a downweighting of children with very bad values relative to good ones
valueWeightExponent = 0.5
# Slight incentive for the bot to behave human-like with regard to passing at the end, filling the dame,
# not wasting time playing in its own territory, etc, and not play moves that are equivalent in terms of
# points but a bit more unfriendly to humans.
rootEndingBonusPoints = 0.5
# Make the bot prune useless moves that are just prolonging the game to avoid losing yet
rootPruneUselessMoves = true
# How big to make the mutex pool for search synchronization
mutexPoolSize = 8192
# How many virtual losses to add when a thread descends through a node
numVirtualLossesPerThread = 1
BIN
View File
Binary file not shown.
+11 -11
View File
@@ -4,36 +4,38 @@ Manual
Installation
------------
* pip install kivy
* change the `engine.command` field in `config.json` to your kata installation (for example, to `path/to/lizzie/katago/katago.exe`)
* start the app by running `python katrain.py` (or `python3` if needed)
* On linux, change the `engine.command` field in `config.json` to your kata v1.3+ installation.
* start the app by running `python katrain.py`
Options
-------
* Top row options
* Check box options
* Eval: show the coloured dots on the moves for this player.
* Hints: show suggested moves for this player.
* Undo: automatically undo poor moves for this player and make them try again.
* Lock AI: disallow extra undos, changing hints options, changing auto move, or AI move.
* AI: let the AI control this player. Check both for self-play.
* Show owner: show expected control of territory.
* Lock AI: disallow extra undos, changing hints options, changing auto move, or AI move.
* Fast: use a lower number of max visits for evaluation/AI move.
* Balance score: Deliberately make sub-optimal moves as the AI in an attempt to balance the score towawrds a slight win.
* Temperature/Evaluation/Score: Not that these fields can be hidden by clicking on the text.
* Temperature is the point difference between passing and the best move.
* Evaluation is where on this scale the last move was, from 0% (equivalent to a pass) to 100% (best move).
This can be < 0% in case of suicidal moves, or >100% when Kata did not consider the move before, or further analysis shows it to be better than the best one considered.
* Score: Expected score.
* Score: How far one player is ahead.
Play
----
* Play against the AI
* Turn on auto move.
* Turn on AI for the chosen player.
* Choose whether to turn on `balance score` to make the AI play slack moves.
* Choose whether to turn on `undo` for your colour to be prompted to re-try poor moves.
* Choose whether or not to turn on `fast` to make the AI play faster but read less deeply (NB: with balance score, faster AI can be a stronger opponent, as there are fewer mediocre moves considered).
* Possibly lock AI to prevent yourself from peeking at hints, etc.
* Possibly hide score or temperature.
* Possibly hide evaluation for the AI player.
* Play by playing a move or clicking AI move if you want white.
* If you chose AI to play black, click AI move for the first move.
* Engine-assisted play
* Turn off auto move.
@@ -43,7 +45,7 @@ Play
* Play with a friend with instant feedback and/or undos for both, or see how many stones stronger you are with one undo. (But please play unranked and be honest to your opponent on what you're doing)
* Analysis
* Copy the SGF into the text box
* Copy the SGF into the text box. Note that branches are not supported and will lead to strange results.
* Choose whether or not to turn on `fast` to make the AI weaker but analyze faster.
* Click `Analyze`
@@ -61,9 +63,7 @@ The `trainer` block has the following options to tweak:
* `balance_play_min_eval`: when needing to balance score, the AI will pick a move which is at least this good.
* `balance_play_min_visits`: never pick a move with fewer playouts than this.
* `undo_eval_threshold`, `undo_point_threshold`: prompt player to undo if move is worse than this in terms of points AND evaluation.
* `undo_outdated_eval_threshold`: don't prompt undo if last move's evaluation is >= `undo_eval_threshold` and the NEW evaluation is greater than this. (this decreases frustration when hints are on, or when kata over-estimates the best move).
* `num_undo_prompts`: automatically undo bad moves when `undo` is on at most this many times.
* `show_ai_options`: show which moves the AI considered.
The cfg file has additional configuration for kata. In particular, it changes the default to being more exploratory and score-based (and therefore nicer as an opponent, but weaker as analysis tool).
+13 -8
View File
@@ -17,6 +17,8 @@ class Move:
self.analysis = None
self.pass_analysis = None
self.ownership = None
self.x_comment = ""
self.auto_undid = False
self.move_number = 0
def __repr__(self):
@@ -61,11 +63,13 @@ class Move:
score = score or self.score
return f"{'B' if score >= 0 else 'W'}+{abs(score):.1f}"
@property
def comment(self,sgf=False):
def comment(self,sgf=False, eval=False, hints=False):
if not self.parent: # root
return ""
text = f"Move {self.move_number}: {self.bw_player()} @ {self.gtp()} {'(AI Move)' if self.robot else ''}\n"
text = f"Move {self.move_number}: {self.bw_player()} {self.gtp()} {'(AI Move)' if self.robot else ''}\n"
text += self.x_comment
text += "".join(f"Auto undid move {m.gtp()} ({m.evaluation*100:.1f}% efficient)\n" for m in self.children if m.auto_undid)
if self.analysis_ready:
score, _, temperature = self.temperature_stats
if sgf:
@@ -73,13 +77,14 @@ class Move:
text += f"Temperature: {temperature:.1f}\n"
if self.parent and self.parent.analysis_ready:
prev_best_score, prev_worst_score, prev_temperature = self.parent.temperature_stats
text += f"Top move was {self.format_score(prev_best_score)} @ {self.parent.analysis[0]['move']}\n"
if sgf or hints:
text += f"Top move was {self.parent.analysis[0]['move']} ({self.format_score(prev_best_score)})\n"
text += f"Pass score was {self.format_score(prev_worst_score)}\n"
if prev_temperature < 0.5:
text += f"Previous temperature ({prev_temperature}) too low for evaluation\n"
else:
if eval:
text += f"Evaluation: {100*self.evaluation:.1f}%\n"
if sgf or eval:
text += f"Evaluation: {100*self.evaluation:.1f}% efficient\n"
outdated_evaluation = self.outdated_evaluation
if outdated_evaluation and outdated_evaluation > self.evaluation and outdated_evaluation > self.evaluation + 0.01:
text += f"(Was considered last move as: {100 * outdated_evaluation :.1f}%)\n"
@@ -94,7 +99,7 @@ class Move:
@property
def evaluation_info(self):
if self.parent and self.parent.analysis_ready and self.analysis_ready:
return self.evaluation,self.parent.temperature_stats[2]
return self.evaluation, self.parent.temperature_stats[2]
else:
return None,None
@@ -264,7 +269,7 @@ class Board:
def moves(self) -> list: # flat list of moves to current
moves = []
p = self.current_move
while p != self.root:
while p is not self.root: # NB == is wrong here
moves.append(p)
p = p.parent
return moves[::-1]
+2 -4
View File
@@ -3,12 +3,11 @@
"pass_visits": 200,
"pass_visits_fast": 50,
"visits": 3500,
"visits_fast": 1500,
"nopass_visits": 10
"visits_fast": 1500
},
"board": {
"size": 19,
"komi": 7.5
"komi": 6.5
},
"ui": {
"size_min": 1,
@@ -35,7 +34,6 @@
"balance_play_min_eval": 0.875,
"balance_play_min_visits": 20,
"undo_eval_threshold": 0.875,
"undo_outdated_eval_threshold": 0.8,
"undo_point_threshold": 1,
"num_undo_prompts": 1
},
+24 -58
View File
@@ -26,7 +26,6 @@ class EngineControls(GridLayout):
[analysis_settings["pass_visits"], analysis_settings["visits"]],
[analysis_settings["pass_visits_fast"], analysis_settings["visits_fast"]],
]
self.min_nopass_visits = analysis_settings["nopass_visits"]
self.train_settings = Config.get("trainer")
self.debug = Config.get("debug")["level"]
self.board_size = Config.get("board")["size"]
@@ -78,13 +77,11 @@ class EngineControls(GridLayout):
print(str(e))
self.info.text = f"Illegal move: {str(e)}"
return
print("PLAYED", move, self.board.stones)
self._request_analysis(mr)
return mr
# engine action functions
def _do_play(self, *args):
print("CURRENT PLAYER", self.board.current_player)
move = Move(player=self.board.current_player, coords=args[0])
self.play(move)
# mr.waiting_for_analysis
@@ -93,66 +90,34 @@ class EngineControls(GridLayout):
def update_evaluation(self):
current_move = self.board.current_move
if self.eval.active(current_move.player):
self.info.text = current_move.comment
self.info.text = current_move.comment(eval=self.eval.active(current_move.player), hints=self.hints.active(current_move.player))
self.evaluation.text = ''
if current_move.analysis_ready:
if current_move.analysis_ready and self.eval.active(current_move.player):
self.score.text = current_move.format_score().replace("-", "\u2013")
self.temperature.text = f"{current_move.temperature_stats[2]:.1f}"
if current_move.parent and current_move.parent.analysis_ready:
self.evaluation.text = f"{100 * current_move.evaluation:.1f}%"
# when to trigger auto undo?
# self.undo.disabled = True # undo while waiting for this does weird things
# undid = False
# self.info.text = ""
# if self.auto_undo.active(1 - self.board.current_player):
# undid = self._auto_undo(move)
# if self.ai_auto.active and not undid:
# self._do_aimove(move, True)
# self.undo.disabled = False
def _auto_undo(self, move):
if current_move.analysis_ready and current_move.parent and current_move.parent.analysis_ready and not current_move.children:
# handle automatic undo
if self.auto_undo.active(current_move.player) and not self.ai_auto.active(current_move.player) and not current_move.auto_undid:
ts = self.train_settings
self.info.text = "Evaluating..."
if (
move.evaluation
and move.evaluation < ts["undo_eval_threshold"]
and move.points_lost >= ts["undo_point_threshold"]
and ts["num_undo_prompts"] > 0
):
if move.outdated_evaluation:
outdated_points_lost = (1 - move.outdated_evaluation) * move.points_lost / (1 - move.evaluation)
# so if the move was not that far off (>undo_outdated_eval_threshold) and according to last move's analysis it was fine, don't undo.
if (
move.outdated_evaluation
and (
move.outdated_evaluation >= ts["undo_eval_threshold"]
or outdated_points_lost < ts["undo_point_threshold"]
)
and (
move.evaluation > ts["undo_outdated_eval_threshold"]
or outdated_points_lost < ts["undo_point_threshold"]
)
):
self.info.text += f"\nBut according to my previous evaluation it was {move.outdated_evaluation*100:.1f}% effective and lost {outdated_points_lost:.1f} point(s), so let's continue anyway.\n"
else:
if len(self.board.current_move.parent.children) <= ts["num_undo_prompts"]:
self.info.text += f"\nLet's try again.\n"
# TODO: is this overly generous wrt low visit outdated evaluations?
eval = max(current_move.evaluation, current_move.outdated_evaluation or 0)
points_lost = (current_move.parent or current_move).temperature_stats[2] * (1 - eval)
if eval < ts["undo_eval_threshold"] and points_lost >= ts["undo_point_threshold"]:
current_move.auto_undid = True
self.board.undo()
return True
else:
evaled_moves = sorted(
[m for m in self.board.current_move.parent.children if m.evaluation],
key=lambda m: -m.evaluation,
)
if evaled_moves and evaled_moves[0].coords != move.coords:
self.board.undo()
self.board.play(evaled_moves[0])
summary = "\n".join(f"{m.gtp()}: {100*m.evaluation:.1f}% effective" for m in evaled_moves)
self.info.text += f"\nYour moves:\n{summary}.\nLet's continue with {evaled_moves[0].gtp()}.\n"
return False
if len(current_move.parent.children) >= ts["num_undo_prompts"] + 1:
best_move = sorted([m for m in current_move.parent.children], key=lambda m: -(m.evaluation_info[0] or 0) )[0]
best_move.x_comment = f"Automatically played as best option after max. {ts['num_undo_prompts']} undo(s).\n"
self.board.play(best_move)
self.update_evaluation()
# ai player doesn't technically need parent ready, but don't want to override waiting for undo
elif self.ai_auto.active(1 - current_move.player) and not current_move.children:
self._do_aimove()
def _do_aimove(self, auto=False):
def _do_aimove(self):
ts = self.train_settings
while not self.board.current_move.analysis_ready:
self.info.text = "Thinking..."
@@ -204,9 +169,9 @@ class EngineControls(GridLayout):
sgfmoves = re.findall(r"([BW])\[([a-z]{2})\]", sgf)
moves = [Move(player=Move.PLAYERS.index(p.upper()), sgfcoords=(mv, self.board_size)) for p, mv in sgfmoves]
for move in moves:
self.board.play(move)
self.play(move)
while not all(m.analysis for m in moves):
time.sleep(0.01)
time.sleep(0.05)
self.info.text = f"{sum([1 if m.analysis else 0 for m in moves])}/{len(moves)} analyzed"
# analysis thread
@@ -215,6 +180,7 @@ class EngineControls(GridLayout):
while self.outstanding_analysis_queries:
self._send_analysis_query(self.outstanding_analysis_queries.pop(0))
line = self.kata.stdout.readline()
if self.debug:
print("KATA ANALYSIS RECEIVED:", line[:50])
self.board.store_analysis(json.loads(line))
self.update_evaluation()
@@ -242,14 +208,14 @@ class EngineControls(GridLayout):
"includeOwnership": True,
"maxVisits": self.visits[fast][1],
}
if self.debug:
print("query", query)
self._send_analysis_query(query)
query.update(
{"id": f"PASS_{move_id}", "maxVisits": self.visits[fast][0], "includeOwnership": False}
) # TODO: merge?
)
query["moves"] += [[move.bw_player(next_move=True), "pass"]]
query["analyzeTurns"][0] += 1
print("pass-query", query)
self._send_analysis_query(query)
+12 -12
View File
@@ -168,11 +168,11 @@
id: auto_undo
text: 'undo'
on_active: root.parent.board.redraw()
CheckBoxHint:
size_hint: 0.2, 0.5
text: 'lock\nai'
id: ai_lock
on_active: self.checkbox.disabled = hints.black.disabled = hints.white.disabled = ai_move.disabled = auto_undo.black.disabled = auto_undo.white.disabled = ai_auto.checkbox.disabled = True
BWCheckBoxHint:
size_hint: 0.166, 0.5
text: 'ai'
id: ai_auto
default_active: False
CheckBoxHint:
size_hint: 0.2, 0.5
id: ownership
@@ -189,19 +189,19 @@
on_press: root.action("aimove")
CheckBoxHint:
size_hint: 0.166, 0.5
text: 'auto\nmove'
id: ai_auto
default_active: False
text: 'fast'
id: ai_fast
default_active: True
CheckBoxHint:
size_hint: 0.166, 0.5
text: 'balance\nscore'
id: ai_balance
default_active: False
CheckBoxHint:
size_hint: 0.166, 0.5
text: 'fast'
id: ai_fast
default_active: True
size_hint: 0.2, 0.5
text: 'lock\nai'
id: ai_lock
on_active: self.checkbox.disabled = hints.black.disabled = hints.white.disabled = ai_move.disabled = auto_undo.black.disabled = auto_undo.white.disabled = ai_auto.checkbox.disabled = True
GridLayout:
cols: 2
rows: 1
+6
View File
@@ -47,6 +47,12 @@ class BadukPanWidget(Widget):
def on_touch_up(self, touch):
if self.ghost_stone:
self.engine.action("play", self.ghost_stone)
else:
xd, xp = self._find_closest(touch.x)
yd, yp = self._find_closest(touch.y)
stones_here = [m for m in self.engine.board.stones if m.coords == (xp,yp)]
if stones_here and max(yd, xd) < self.grid_size / 2: # load old comment
self.engine.info.text = stones_here[-1].comment(sgf=True)
self.ghost_stone = None
self.redraw() # remove ghost