fewer hints, alternatives search

This commit is contained in:
Sander Land committed 2020-09-08 22:26:14 +02:00
1 parent 2758e936c8
commit 4e2ee03db7
26 files changed
+132 -42

No files matched your search

+7 -13
View File
@@ -154,23 +154,21 @@ Keyboard shortcuts are shown with **[key]**.
wanting to guess the next move.
* **[w]**: Show all dots: Show all evaluation dots instead of the last few.
* You can configure how many are shown with this setting off, and whether they are shown for AIs under 'Configure Teacher'.
* **[e]**: Top moves: Show the next moves KataGo considered, colored by their expected point loss. Small dots indicate high uncertainty. Hover over any of them to see the principal variation.
* **[r]**: Policy moves: Show KataGo's policy network evaluation, i.e. where it thinks the best next move is purely from the position, and in the absence of any 'reading'.
* **[e]**: Top moves: Show the next moves KataGo considered, colored by their expected point loss.
Small/faint dots indicate high uncertainty and never show text (lower than your 'fast visits' setting).
Hover over any of them to see the principal variation.
* **[r]**: Policy moves: Show KataGo's policy network evaluation, i.e. where it thinks the best next move is purely from the position,
and in the absence of any 'reading'. This turns off the 'top moves' setting as the overlap is often not useful.
* **[t]**: Expected territory: Show expected ownership of each intersection.
* The analysis options available under the 'Analysis' button are used for deeper evaluation of the position:
* **[a]**: Deeper analysis: Re-evaluate the position using more visits, usually resulting in a more accurate evaluation.
* **[s]**: Equalize visits: Re-evaluate all currently shown next moves with the same visits as the current top move. Useful to increase confidence in the suggestions with high uncertainty.
* **[d]**: Analyze all moves: Evaluate all possible next moves. This can take a bit of time even though 'fast_visits' is used, but can be useful to see how many reasonable next moves are available.
* **[f]**: Find alternatives: Increases analysis of current candidate moves to at least the 'fast visits' level, and request a new query that excludes all current candidate moves.
* **[spacebar]**: Turn continuous analysis on/off. This will continuously improve analysis of the current position, similar to Lizzie's 'pondering', but only when there are no other queries going on.
* **[enter]** AI move. Makes the AI move for the current player regardless of current player selection.
### Rank Estimation
A new feature in v1.3 is the rank estimation panel. This adds an extra graph which uses a statistical model to estimate the playing strength
of both players for every 80 move segment. It can be used for determining which part of your game needs extra attention,
but keep in mind the estimation is based purely on how well moves correspond to the 'shape sense' of KataGo and can be very inaccurate at times.
## <a name="keyboard"></a> Keyboard and mouse shortcuts
In addition to shortcuts mentioned above and those shown in the main menu:
@@ -197,15 +195,11 @@ In addition to shortcuts mentioned above and those shown in the main menu:
* Try using a lower number for `nnMaxBatchSize` in `KataGo/analysis_config.cfg`, and avoid using versions compiled with large board sizes.
* If still encountering problems, please start KataGo by itself to check for any errors it gives.
* Note that if you don't have a GPU, or your GPU does not support OpenCL, you should use the 'eigen' binaries which run on CPU only.
* How can I play on larger boards?
* For windows, change the `katago` setting to `katrain\KataGo\katago-bs52.exe`. For other operating systems, you need to compile your own KataGo version with higher limits.
## <a name="support"></a> Support / Contribute
[![GitHub issues](https://img.shields.io/github/issues/sanderland/katrain)](https://github.com/sanderland/katrain/issues)
[![Contributors](https://img.shields.io/static/v1?label=contributors&message=19&color=dcb424)](CONTRIBUTIONS.md)
[![Liberapay patrons](https://img.shields.io/liberapay/patrons/sanderbaduk)](https://liberapay.com/sanderbaduk/)
[![Github sponsors](https://img.shields.io/static/v1?label=sponsor&message=7&logo=GitHub&color=dcb424&link=https://github.com/sponsors/sanderland/)](https://github.com/sponsors/sanderland)
* Ideas, feedback, and contributions to code or translations are all very welcome.
@@ -213,7 +207,7 @@ In addition to shortcuts mentioned above and those shown in the main menu:
* I am looking for contributors of more translations of both this manual and the program itself. The best way to help with this is to contact me on discord.
* You can contact me on [discord](https://discord.gg/AjTPFpN) (Sander#3278), [KakaoTalk](https://open.kakao.com/o/gTsMJCac)
or [Reddit](http://reddit.com/u/sanderbaduk) to get help, discuss improvements, or simply show your appreciation.
* You can also donate to the project through [Liberapay](https://liberapay.com/KaTrain/) or [Github Sponsors](https://github.com/sponsors/sanderland).
* You can also donate to the project through [Github Sponsors](https://github.com/sponsors/sanderland).
+1
View File
@@ -440,6 +440,7 @@ class KaTrainGui(Screen, KaTrainBase):
"a": ("analyze-extra", "extra"),
"s": ("analyze-extra", "equalize"),
"d": ("analyze-extra", "sweep"),
"f": ("analyze-extra", "alternative"),
"p": ("play", None),
"down": ("switch-branch", 1),
"up": ("switch-branch", -1),
+16 -1
View File
@@ -77,7 +77,9 @@ class KataGoEngine:
elif not os.path.isfile(cfg):
self.katrain.log(i18n._("Kata config not found").format(config=cfg), OUTPUT_ERROR)
return # don't start
self.command = shlex.split(f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]}')
self.command = shlex.split(
f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]}'
)
self.start()
def start(self):
@@ -224,6 +226,7 @@ class KataGoEngine:
visits: int = None,
analyze_fast: bool = False,
time_limit=True,
find_alternatives: bool = False,
priority: int = 0,
ownership: Optional[bool] = None,
next_move: Optional[GameNode] = None,
@@ -241,6 +244,17 @@ class KataGoEngine:
if analyze_fast and self.config.get("fast_visits"):
visits = self.config["fast_visits"]
if find_alternatives:
avoid = [
{
"moves": list(analysis_node.analysis["moves"].keys()),
"player": analysis_node.next_player,
"untilDepth": 1,
}
]
else:
avoid = []
size_x, size_y = analysis_node.board_size
settings = copy.copy(self.override_settings)
if time_limit:
@@ -254,6 +268,7 @@ class KataGoEngine:
"analyzeTurns": [len(moves)],
"maxVisits": visits,
"komi": analysis_node.komi,
"avoidMoves": avoid,
"boardXSize": size_x,
"boardYSize": size_y,
"includeOwnership": ownership and not next_move,
+8 -2
View File
@@ -369,18 +369,24 @@ class Game:
visits = engine.config["fast_visits"]
self.katrain.controls.set_status(i18n._("sweep analysis").format(visits=visits), STATUS_ANALYSIS)
priority = -1_000_000_000
elif mode == "equalize":
elif mode in ["equalize", "alternative"]:
if not cn.analysis_ready:
self.katrain.controls.set_status(i18n._("wait-before-equalize"), STATUS_INFO, self.current_node)
return
analyze_moves = [Move.from_gtp(gtp, player=cn.next_player) for gtp, _ in cn.analysis["moves"].items()]
priority = -1_000
if mode == "alternative": # also do a quick update on current candidates so it doesn't look too weird
self.katrain.controls.set_status("Searching for alternatives", STATUS_ANALYSIS)
cn.analyze(engine, priority=-500, time_limit=False, find_alternatives=True)
visits = engine.config["fast_visits"]
else:
visits = max(d["visits"] for d in cn.analysis["moves"].values())
self.katrain.controls.set_status(i18n._("equalizing analysis").format(visits=visits), STATUS_ANALYSIS)
priority = -1_000
else:
raise ValueError("Invalid analysis mode")
for move in analyze_moves:
if cn.analysis["moves"].get(move.gtp(), {"visits": 0})["visits"] < visits:
cn.analyze(
engine, priority, visits=visits, refine_move=move, time_limit=False
) # explicitly requested so take as long as you need
+17 -3
View File
@@ -68,15 +68,25 @@ class GameNode(SGFNode):
) # analyzed/not undone main, non-teach second, undone last
# various analysis functions
def analyze(self, engine, priority=0, visits=None, time_limit=True, refine_move=None, analyze_fast=False):
def analyze(
self,
engine,
priority=0,
visits=None,
time_limit=True,
refine_move=None,
analyze_fast=False,
find_alternatives=False,
):
engine.request_analysis(
self,
lambda result: self.set_analysis(result, refine_move),
lambda result: self.set_analysis(result, refine_move, find_alternatives),
priority=priority,
visits=visits,
analyze_fast=analyze_fast,
time_limit=time_limit,
next_move=refine_move,
find_alternatives=find_alternatives,
)
def update_move_analysis(self, move_analysis, move_gtp):
@@ -90,17 +100,21 @@ class GameNode(SGFNode):
elif cur["visits"] < move_analysis["visits"]:
cur.update(move_analysis)
def set_analysis(self, analysis_json, refine_move):
def set_analysis(self, analysis_json, refine_move, alternatives_mode):
if refine_move:
pvtail = analysis_json["moveInfos"][0]["pv"] if analysis_json["moveInfos"] else []
self.update_move_analysis(
{"pv": [refine_move.gtp()] + pvtail, **analysis_json["rootInfo"]}, refine_move.gtp()
)
else:
if alternatives_mode:
for m in analysis_json["moveInfos"]:
m["order"] += 10 # offset for not making this top
for move_analysis in analysis_json["moveInfos"]:
self.update_move_analysis(move_analysis, move_analysis["move"])
self.ownership = analysis_json.get("ownership")
self.policy = analysis_json.get("policy")
if not alternatives_mode:
self.analysis["root"] = analysis_json["rootInfo"]
if self.parent and self.move:
analysis_json["rootInfo"]["pv"] = [self.move.gtp()] + (
+5
View File
@@ -744,6 +744,11 @@
icon: 'img/Sweep.png'
shortcut: 'd'
on_action: root.katrain("analyze-extra", "sweep")
AnalysisMenuItem:
text: i18n._("analysis:alternatives")
icon: 'img/Alternative.png'
shortcut: 'f'
on_action: root.katrain("analyze-extra", "alternative")
AnalysisMenuItem:
text: i18n._("analysis:game")
icon: 'img/analysis.png'
+17 -7
View File
@@ -361,7 +361,7 @@ class BadukPanWidget(Widget):
polsize = 1.1 * math.sqrt(policy_grid[y][x])
policy_circle_color = (
*POLICY_COLOR,
POLICY_ALPHA + TOP_MOVE_ALPHA * (policy_grid[y][x] == best_move_policy),
POLICY_ALPHA + TOP_POLICY_ALPHA * (policy_grid[y][x] == best_move_policy),
)
draw_circle(
(self.gridpos_x[x], self.gridpos_y[y]), polsize * self.stone_size, policy_circle_color
@@ -409,27 +409,37 @@ class BadukPanWidget(Widget):
self.active_pv_moves = []
# hints or PV
if katrain.analysis_controls.hints.active and not katrain.analysis_controls.policy.active and not game_ended:
if (
katrain.analysis_controls.hints.active
and not katrain.analysis_controls.policy.active
and not game_ended
):
hint_moves = current_node.candidate_moves
for i, move_dict in enumerate(hint_moves):
move = Move.from_gtp(move_dict["move"])
if move.coords is not None:
scale = 0.95
if move_dict["visits"] < VISITS_FRAC_SMALL * hint_moves[0]["visits"]:
scale = 0.75
scale = HINT_SCALE
text_on = True
alpha = HINTS_ALPHA
if move_dict["visits"] < katrain.config("engine/fast_visits"):
scale = UNCERTAIN_HINT_SCALE
text_on = False
alpha = HINTS_MIN_ALPHA + (HINTS_ALPHA - HINTS_MIN_ALPHA) * (
move_dict["visits"] / katrain.config("engine/fast_visits")
)
if "pv" in move_dict:
self.active_pv_moves.append((move.coords, move_dict["pv"], current_node))
else:
katrain.log(f"PV missing for move_dict {move_dict}", OUTPUT_DEBUG)
evalsize = self.stone_size * scale
evalcol = self.eval_color(move_dict["pointsLost"])
Color(*evalcol[:3], HINTS_ALPHA)
Color(*evalcol[:3], alpha)
Rectangle(
pos=(self.gridpos_x[move.coords[0]] - evalsize, self.gridpos_y[move.coords[1]] - evalsize),
size=(2 * evalsize, 2 * evalsize),
source="katrain/img/topmove.png",
)
if self.trainer_config["text_point_loss"]:
if self.trainer_config["text_point_loss"] and text_on:
if move_dict["pointsLost"] < 0.05:
ptloss_text = "0.0"
else:
+1
View File
@@ -373,6 +373,7 @@ class AnalysisToggle(MDBoxLayout):
default_active = BooleanProperty(False)
font_name = StringProperty(DEFAULT_FONT)
disabled = BooleanProperty(False)
def trigger_action(self, *args, **kwargs):
return self.checkbox.trigger_action(*args, **kwargs)
+7 -4
View File
@@ -59,13 +59,16 @@ POLICY_COLOR = [0.9, 0.2, 0.8]
STARPOINT_SIZE = 0.1
BOARD_COLOR = [0.85, 0.68, 0.40, 1]
STONE_SIZE = 0.505 # texture edge is transparent
VISITS_FRAC_SMALL = 0.1
POLICY_ALPHA = 0.5
HINTS_ALPHA = 0.75
TOP_MOVE_ALPHA = 0.4
HINTS_ALPHA = 0.8
HINTS_MIN_ALPHA = 0.1 # single visit
POLICY_ALPHA = 0.6
TOP_POLICY_ALPHA = 0.3
TOP_MOVE_BORDER_COLOR = [10 / 255, 200 / 255, 250 / 255, 1.0]
CHILD_SCALE = 0.95
HINT_SCALE = 0.975
UNCERTAIN_HINT_SCALE = 0.7
# ponder light
ENGINE_DOWN_COL = EVAL_COLORS["theme:normal"][1]
Binary file not shown.
@@ -521,6 +521,7 @@ msgstr "读秒声音开启"
msgid "tab:info-details"
msgstr "详细"
#. TODO: updated
msgid "teaching undo message"
msgstr "撤销第 {move} 手棋因为损失超过 {points_lost:.1f} 目. 悬停在该手棋 上方查看信息. 请再次尝试."
@@ -631,3 +632,7 @@ msgstr "启动katago失败因缺失dll文件. 请检查运行要求, 或尝试
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.
+11 -6
View File
@@ -105,12 +105,6 @@ msgstr "AI Zug erzwingen"
msgid "pass-button-text"
msgstr "Passen"
msgid "teaching undo message"
msgstr ""
"Zug {move} zurückgenommen, da er {points_lost:.1f} Punkte verliert. Bewege "
"Mauszeiger über den Zug,um die erwartete Widerlegung zu sehen. Bitte "
"versuche es erneut."
msgid "ai-ponder"
msgstr ""
"Zeigt den Enginestatus an von grün (Leerlauf) bis orange(Zugberechnung). Ist"
@@ -680,3 +674,14 @@ msgstr "Zeig den Punkteverlust auf Beste Züge"
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
#. TODO - updated
msgid "teaching undo message"
msgstr ""
"Zug {move} zurückgenommen, da er {points_lost:.1f} Punkte verliert. Bewege "
"Mauszeiger über den Zug,um die erwartete Widerlegung zu sehen. Bitte "
"versuche es erneut."
Binary file not shown.
@@ -102,6 +102,10 @@ msgstr "Fast analysis of all moves"
msgid "analysis:game"
msgstr "Deeper full game analysis"
#. Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
#. Keep improving current position analysis when there is nothing else to do
msgid "analysis:continuous"
msgstr "Toggle continuous analysis"
@@ -133,10 +137,12 @@ msgstr "Pass"
msgid "resign"
msgstr "Resign"
#. Shown when a move is undone in teaching mode.
msgid "teaching undo message"
msgstr ""
"Undid move {move} as it lost {points_lost:.1f} points. Hover over the move "
"to see expected refutation. Please try again."
"Undid move {move} as it lost {points_lost:.1f} points. Please try again. For"
" a hint, hover over the move to see expected refutation, or check expected "
"territory (t) to see the areas of the board where point loss is expected."
msgid "ai-ponder"
msgstr ""
Binary file not shown.
@@ -105,6 +105,7 @@ msgstr "Forzar jugada IA"
msgid "pass-button-text"
msgstr "Pasar"
#. TODO: updated
msgid "teaching undo message"
msgstr ""
"Deshice jugada {move} ya que perdía {points_lost:.1f} puntos. Coloca el "
@@ -688,3 +689,7 @@ msgstr "Show point loss on top moves"
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.
@@ -522,6 +522,7 @@ msgstr ""
"possiblement pour cause de \n"
"mémoire insuffisante : {error}"
#. TODO: updated
msgid "teaching undo message"
msgstr ""
"Le coup {move} a été annulé car il perdait {points_lost:.1f} points. Vous "
@@ -715,3 +716,7 @@ msgstr "Indiquer les points perdus"
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.
@@ -129,10 +129,6 @@ msgstr "一局全体を再分析中(各{visits}手)"
msgid "pass-button-text"
msgstr "パス"
msgid "teaching undo message"
msgstr ""
"待った。{move}は{points_lost:.1f}目損です(マウスカーソルをこの手にかざせばとがめる手順が表示されます)。打ち直してください。"
msgid "ai-ponder"
msgstr "この印はエンジンの状態をシンプルに表します(緑=空き、オレンジ=処理中)。エンジンが止まったり起動できなかったりすると赤くなります。"
@@ -670,3 +666,12 @@ msgstr "損失目数を候補手上に表示"
#. - resign the game
msgid "resign"
msgstr "投了"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
#. TODO - updated
msgid "teaching undo message"
msgstr ""
"待った。{move}は{points_lost:.1f}目損です(マウスカーソルをこの手にかざせばとがめる手順が表示されます)。打ち直してください。"
Binary file not shown.
@@ -546,6 +546,7 @@ msgstr ""
"`threshold`선 밑의 수를 더 많이 뽑은 후 그 중 최선의 수를 둡니다. `line_weight`을 증가시키면 바둑판 중앙에 있는"
" 수를 더욱 꺼리게 됩니다. 판이 `endgame` 비율만큼 차면 평범하게 둡니다."
#. TODO: updated
msgid "teaching undo message"
msgstr ""
"{points_lost:.1f}집 손해이므로 {move}을/를 물렀습니다. 커서를 올려 상대의 대응책을 보십시오. 다시 두어 주세요."
@@ -648,3 +649,7 @@ msgstr "돌 위에 집 손해 표시하기"
#. TODO - resign the game
msgid "resign"
msgstr "기권함"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.
@@ -117,6 +117,7 @@ msgstr "Дополнительный анализ всех ходов-канди
msgid "pass-button-text"
msgstr "Пас"
#. TODO - updated
msgid "teaching undo message"
msgstr ""
"Ход {move} отменён, т.к. это потеря {points_lost:.1f} очков. Наведите на "
@@ -676,3 +677,7 @@ msgstr "Показывать потерянные очки текстом"
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB