rank model

This commit is contained in:
Sander Land committed 2020-07-05 22:24:17 +02:00
1 parent 32074d6616
commit f4f8f61084
6 files changed
+106 -14

No files matched your search

+8 -3
View File
@@ -76,13 +76,18 @@ on the board, or not output details for them in SGFs,you can do so under 'Config
This section describes the available AIs, with strength based on their current OGS rankings using the default settings.
In the 'AI settings', settings with calibration are at the top and have a lighter color, changing these will show an estimate of rank.
This estimate is reasonably accurate as long as you have not changed the other settings.
* Recommended options for serious play include:
* **[9p+]** **KataGo** is full KataGo, above professional level. The analysis and feedback given is always based on this full strength KataGo AI.
* **[15k - 3d]** **Calibrated Rank Bot** was calibrated on various bots (e.g. GnuGo and Pachi at different strength settings) to play a balanced game from the opening to the endgame without making serious (DDK) blunders. Further discussion can be found on [this](https://github.com/sanderland/katrain/issues/44) thread.
* **[15k - 3d]** **Calibrated Rank Bot** was calibrated on various bots (e.g. GnuGo and Pachi at different strength settings) to play a balanced
game from the opening to the endgame without making serious (DDK) blunders. Further discussion can be found
[here](https://github.com/sanderland/katrain/issues/44) and [here](https://github.com/sanderland/katrain/issues/74).
* **[~5k]** **ScoreLoss** is KataGo analyzing as usual, but
choosing from potential moves depending on the expected score loss, leading to a varied style with mostly small mistakes.
* **[~4d]** **Policy** uses the top move from the policy network (it's 'shape sense' without reading).
* **[~4k]** **Policy Weighted** picks a random move weighted by the policy, leading to a varied style with mostly small mistakes, and occasional blunders due to a lack of reading.
* **[~5d]** **Policy** uses the top move from the policy network (it's 'shape sense' without reading).
* **[12k - 2d]** **Policy Weighted** picks a random move weighted by the policy, leading to a varied style with mostly small mistakes, and occasional blunders due to a lack of reading.
* **[~8k]** **Blinded Policy** picks a number of moves at random and play the best move among them, being effectively 'blind' to part of the board each turn.
* Options that are more on the 'fun and experimental' side include:
* Variants of **Blinded Policy**, which use the same basic strategy, but with a twist.:
+1
View File
@@ -242,6 +242,7 @@ class KaTrainGui(Screen, KaTrainBase):
self.message_queue.put([self.game.game_id, message, args, kwargs])
def _do_new_game(self, move_tree=None, analyze_fast=False):
self.idle_analysis = False
mode = self.play_analyze_mode
if (move_tree is not None and mode == MODE_PLAY) or (move_tree is None and mode == MODE_ANALYZE):
self.play_mode.switch_ui_mode() # for new game, go to play, for loaded, analyze
+39 -8
View File
@@ -25,17 +25,39 @@ from katrain.core.constants import (
OUTPUT_INFO,
AI_WEIGHTED_ELO,
CALIBRATED_RANK_ELO,
AI_LOCAL_ELO_GRID,
AI_TENUKI_ELO_GRID,
AI_TERRITORY_ELO_GRID,
AI_INFLUENCE_ELO_GRID,
)
from katrain.core.game import Game, GameNode, Move
from katrain.core.utils import var_to_grid
def interp1d(x, lookup):
def interp_ix(lst, x):
i = 0
while i + 1 < len(lookup) - 1 and lookup[i + 1][0] < x:
while i + 1 < len(lst) - 1 and lst[i + 1] < x:
i += 1
t = max(0, min(1, (x - lookup[i][0]) / (lookup[i + 1][0] - lookup[i][0])))
return (1 - t) * lookup[i][1] + t * lookup[i + 1][1]
t = max(0, min(1, (x - lst[i]) / (lst[i + 1] - lst[i])))
return i, t
def interp1d(lst, x):
xs, ys = zip(*lst)
i, t = interp_ix(xs, x)
return (1 - t) * ys[i] + t * ys[i + 1]
def interp2d(gridspec, x, y):
xs, ys, matrix = gridspec
i, t = interp_ix(xs, x)
j, s = interp_ix(ys, y)
return (
matrix[j][i] * (1 - t) * (1 - s)
+ matrix[j][i + 1] * t * (1 - s)
+ matrix[j + 1][i] * (1 - t) * s
+ matrix[j + 1][i + 1] * t * s
)
def ai_rank_estimation(strategy, settings) -> Tuple[int, bool]:
@@ -43,10 +65,19 @@ def ai_rank_estimation(strategy, settings) -> Tuple[int, bool]:
return 9, True
if strategy == AI_RANK:
return 1 - settings["kyu_rank"], True
if strategy in [AI_WEIGHTED]:
if strategy in [AI_WEIGHTED, AI_LOCAL, AI_TENUKI, AI_TERRITORY, AI_INFLUENCE]:
if strategy == AI_WEIGHTED:
elo = interp1d(settings["weaken_fac"], AI_WEIGHTED_ELO)
kyu = interp1d(elo, CALIBRATED_RANK_ELO)
elo = interp1d(AI_WEIGHTED_ELO, settings["weaken_fac"])
if strategy == AI_LOCAL:
elo = interp2d(AI_LOCAL_ELO_GRID, settings["pick_frac"], settings["pick_n"])
if strategy == AI_TENUKI:
elo = interp2d(AI_TENUKI_ELO_GRID, settings["pick_frac"], settings["pick_n"])
if strategy == AI_TERRITORY:
elo = interp2d(AI_TERRITORY_ELO_GRID, settings["pick_frac"], settings["pick_n"])
if strategy == AI_INFLUENCE:
elo = interp2d(AI_INFLUENCE_ELO_GRID, settings["pick_frac"], settings["pick_n"])
kyu = interp1d(CALIBRATED_RANK_ELO, elo)
return 1 - kyu, True
else:
return AI_STRENGTH[strategy], False
@@ -250,7 +281,7 @@ def generate_ai_move(game: Game, ai_mode: str, ai_settings: Dict) -> Tuple[Move,
x_ai_thoughts = (
f"Generated equal weights as move number >= {ai_settings['endgame'] * size[0] * size[1]}. "
)
n_moves = int(max(n_moves, 0.5 * len(legal_policy_moves)))
n_moves = int(max(n_moves, len(legal_policy_moves) // 2))
elif ai_mode in [AI_INFLUENCE, AI_TERRITORY]:
weighted_coords, x_ai_thoughts = generate_influence_territory_weights(
ai_mode, ai_settings, policy_grid, size
+56 -2
View File
@@ -88,7 +88,8 @@ AI_OPTION_VALUES = {
}
AI_KEY_PROPERTIES = {"kyu_rank", "strength", "weaken_fac", "pick_frac", "pick_n", "automatic"}
CALIBRATED_RANK_ELO =[(39.36921298625589, 18),
CALIBRATED_RANK_ELO = [
(39.36921298625589, 18),
(96.95581072853861, 17),
(154.54240847082144, 16),
(212.12900621310428, 15),
@@ -109,7 +110,8 @@ CALIBRATED_RANK_ELO =[(39.36921298625589, 18),
(1075.9279723473464, 0),
(1133.5145700896292, -1),
(1191.101167831912, -2),
(1700,-4)]
(1700, -4),
]
AI_WEIGHTED_ELO = [
(0.5, 1591.4486833932992),
(1.0, 1266.2591850212696),
@@ -120,3 +122,55 @@ AI_WEIGHTED_ELO = [
(2.5, 516.8371296455036),
(3.0, 359.9621037249864),
]
AI_LOCAL_ELO_GRID = [
[0.0, 0.05, 0.1, 0.2, 0.3, 0.5, 0.75, 1.0],
[0, 5, 10, 15, 25, 50],
[
[200.0, 806.21655824, 1293.32037587, 1392.29465619, 1423.34086023, 1475.35678018, 1631.70997963, 1700.0],
[271.88274382, 1177.38904493, 1357.48028947, 1427.89588231, 1471.76588449, 1531.66834985, 1700.0, 1700.0],
[725.2189244, 1233.32342855, 1392.46449871, 1443.99394784, 1415.66026743, 1490.09450071, 1700.0, 1700.0],
[986.18843485, 1315.19341299, 1423.36540576, 1438.78299774, 1499.2278826, 1570.46885902, 1700.0, 1700.0],
[1334.16982939, 1401.31972528, 1430.66495587, 1450.4662417, 1510.77588056, 1575.68586904, 1700.0, 1700.0],
[1388.06911342, 1451.04383633, 1391.07099726, 1500.84987644, 1520.43287013, 1700.0, 1700.0, 1700.0],
],
]
AI_TENUKI_ELO_GRID = [
[0.0, 0.05, 0.1, 0.2, 0.3, 0.5, 0.75, 1.0],
[0, 5, 10, 15, 25, 50],
[
[100, 381.67199019, 614.9022033, 807.74726571, 972.75719068, 1081.59259337, 1280.81772836, 1700.0],
[302.05524257, 447.16707419, 634.67443071, 847.73134951, 980.06971493, 1100.47221165, 1424.97514319, 1700.0],
[395.99120046, 565.59284207, 707.35509522, 883.39067276, 997.20744208, 1125.50994832, 1392.10412559, 1700.0],
[468.10121071, 660.65479606, 774.42716944, 862.84933335, 1010.69484968, 1156.68204921, 1436.80030417, 1700.0],
[652.8285294, 753.57925069, 797.59399585, 898.99936585, 1042.96870256, 1222.48814041, 1470.92773923, 1700.0],
[901.40390178, 910.28781658, 958.0281189, 1126.63475026, 1203.75546167, 1352.13779312, 1493.13435049, 1700.0],
],
]
AI_TERRITORY_ELO_GRID = [
[0.0, 0.05, 0.1, 0.2, 0.3, 0.5, 0.75, 1.0],
[0, 5, 10, 15, 25, 50],
[
[0, 491.99354617, 652.54536499, 827.56438866, 997.07978087, 1207.47161931, 1461.93571907, 1700.0],
[119.03096728, 554.30545095, 747.74695281, 852.1114908, 1049.58656646, 1250.72046036, 1475.72706895, 1700.0],
[348.45765825, 589.16893663, 775.81559273, 909.21125406, 1073.92675377, 1300.11842657, 1485.95667768, 1700.0],
[538.88999479, 676.21745434, 821.27037414, 950.58649838, 1126.1274156, 1358.9290967, 1500.00471917, 1700.0],
[597.90794583, 741.3513872, 884.73016339, 972.54025369, 1150.30545203, 1430.55449307, 1566.81074945, 1700.0],
[826.03134794, 997.58427811, 1093.54942758, 1214.9588177, 1336.40285376, 1485.32581091, 1700.0, 1700.0],
],
]
AI_INFLUENCE_ELO_GRID = [
[0.0, 0.05, 0.1, 0.2, 0.3, 0.5, 0.75, 1.0],
[0, 5, 10, 15, 25, 50],
[
[75.9591829, 483.922460, 703.633297, 898.804165, 1041.90611, 1180.64701, 1500.22844, 1510.60242,],
[285.94611, 598.87800, 673.848093, 866.826392, 1032.48205, 1334.284716, 1510.55098, 1520.774582,],
[478.37028, 643.868326, 837.7348868, 945.3233087, 1093.119452, 1350.0936572, 1515.4939758, 1530.1492031,],
[570.841325, 689.7079695, 848.3192009, 1021.7089457, 1143.3090057, 1371.453538, 1520.4852553, 1540.64105,],
[749.495401, 771.144054, 865.13815, 1019.895054, 1107.959449, 1383.373536, 1525.298316, 1549.8151732,],
[882.96911, 902.885106, 1057.305618, 1178.3968159, 1369.4749768, 1518.303563, 1530.772607, 1550.508035,],
],
]
+1 -1
View File
@@ -83,7 +83,7 @@ def rank_label(rank):
if rank is None:
return "??k"
if rank > 0:
if rank >= 0.5:
return f"{rank:.0f}{i18n._('strength:dan')}"
else:
return f"{1-rank:.0f}{i18n._('strength:kyu')}"
+1
View File
@@ -78,6 +78,7 @@ class SelectionSlider(Widget):
def on_change(self, value):
pass
KV = """
#:import i18n katrain.core.lang.i18n
<SelectionSlider>: