By Stefan Pohl
Date 2018-07-06 14:09
Edited 2018-07-06 14:24
Idee für eine Leela-Hybrid-Engine
Leela ist ein bionisches Schachprogramm, nimmt sich also die menschliche Art Schach zu spielen zum Vorbild: Ein (emuliertes) neurales Netz lernt Schach zu spielen über das Erlernen und Erkennen von Stellungsmustern. Dies führt nun dazu, daß Leela dieselben prinzipiellen Stärken und Schwächen im Schachspiel zeigt, wie Menschen: Nämlich sehr gutes Positionsspiel auf der einen Seite, generell schwaches taktisches Spiel – gepaart mit teils schrecklichen taktischen Aussetzern auf der anderen Seite. Letzteres ist dem hohen Rechenaufwand bei der Abarbeitung des NeuralNetz-Codes zur Beurteilung der jeweiligen Stellung zuzuschreiben, welcher die Zahl der untersuchbaren Stellungen durch Leela in einer bestimmten Zeitspanne stark limitiert.
Beide Eigenschaften sind nun aber völlig konträr zu den Stärken und Schwächen von klassischen Schachengines, welche eher Schwächen im Positionsspiel zeigen, dafür aber taktisch extrem stark sind. Daher liegt es nahe, Leela und eine klassische Engine zu einem Hybriden zu verbinden und so zu versuchen, die Stärken beider zu verbinden und ihre jeweiligen Schwächen auszumerzen. Dies ist umso verlockender, als Leela den Großteil ihrer Berechnungen auf der Grafikkarte des Rechners ausführt, während die klassische Engine die Prozessorkerne zum Rechnen nutzt. Dies macht ein paralleles Arbeiten von Leela und einer klassischen Engine möglich.
Der naheliegenste Ansatz, nämlich zunächst Leela einen besten Zug errechnen zu lassen und diesen dann anschließend von der klassischen Engine auf taktische Tauglichkeit zu prüfen, ist insofern nicht besonders sinnvoll. Viel sinnvoller scheint, die Berechnungen von Leela und der klassischen Engine parallel ablaufen zu lassen, da jeweils unterschiedliche Hardwarekomponenten genutzt werden. Das Problem, das sich nun ergibt, ist natürlich, daß die klassische Engine nicht weiß, welchen Zug Leela überhaupt spielen wird, wenn beide zur selben Zeit mit den Berechnungen beginnen – nämlich sobald der Gegner seinen Zug auf dem Brett ausgeführt hat. Für dieses Problem schlage ich nun die Nutzung des Multivariantenmodus vor (im folgenden kurz MV-Modus), welcher von vielen aktuellen, klassischen Engines unterstützt wird. Unter anderem auch von Stockfish. Diese Engine würde sich meiner Meinung nach zur Nutzung in einem Leela-Hybriden anbieten, da sie sehr stark spielt (z.Zt. zweifelsfrei die weltbeste Engine) und ihr Programmcode OpenSource ist, sodaß ihr Programmcode für jedermann einsehbar und nutzbar ist. Daher gehe ich im folgenden von Stockfish als Hybridpartner von Leela aus. Generell ist aber jede andere klassische Engine, die den MV-Modus anbietet, ebenfalls nutzbar. Wie soll das Ganze nun ablaufen?
Wenn der Gegner seinen Zug ausgeführt hat, beginnen Leela und Stockfish beide zeitgleich und parallel zu rechnen, wobei Leela die GPU nutzt, sowie einen oder zwei Prozesserkerne. Die restlichen CPU-Kerne bekommt Stockfish zum Rechnen zugewiesen. Während Leela „ganz normal“ rechnet, läuft Stockfish im MV-Modus und errechnet so nicht nur einen besten Zug, sondern n beste Züge. Wobei n als UCI-Parameter für den Benutzer einstellbar gemacht werden könnte. Ich würde einen Wert von 5-10 als sinnvoll erachten, aber dies müßte man experimentell justieren und optimieren. Je mehr Varianten Stockfish berechnet, desto höher der Rechenaufwand, um eine bestimmte Suchtiefe zu erreichen, also umso geringer die taktische Qualität jeder einzelnen der n Varianten. Aber desto mehr spielerische „Freiheit“ hätte Leela für ihr planvolles, positionelles Spiel. Dazu gleich mehr.
Nun kommt noch ein weiterer Parameter ins Spiel, den man ebenfalls als UCI-Parameter für den User extern einstellbar machen könnte, nämlich ein Bewertungs-Schwellwert, den ich hier kurz ev („eval“) nenne. Je höher man ev einstellt, desto mehr spielerische „Freiheit“ hat Leela und desto seltener wird Stockfish eingreifen.
Wenn Leela mit ihren Berechnungen fertig ist (das Zeitmanagement der Hybrid-Engine liegt natürlich bei Leela) und ziehen will, wird auch die MV-Berechnung von Stockfish abgebrochen. Nun gibt es mehrere mögliche Szenarien, die eintreten können:
a) Stockfish und Leela sind sich einig, was der beste Zug ist, also ist der Zug, den Leela spielen will, auch der erste Zug in der MV-Zugliste von Stockfish. In diesem Fall wird dieser Zug natürlich auch ausgespielt.
b) Leelas favorisierter Zug ist nicht in der MV-Zugliste von Stockfish enthalten. Dann wird der von Stockfish favorisierte Zug gespielt, also der erste Zug in der MV-Zugliste von Stockfish. Leela wird also „überstimmt“.
c) Leelas favorisierter Zug ist zwar nicht der erste Zug in der MV-Zugliste von Stockfish, aber er taucht in dieser Liste weiter unten auf. In diesem Fall wird die Differenz der Bewertungen von Stockfish (Leelas Bewertungen spielen in meinem Konzept überhaupt keine Rolle!) dieser beiden Züge (in Stockfishs MV-Zugliste) gebildet und geprüft, ob diese Differenz kleiner oder gleich ev ist, oder aber höher. Ist die Differenz kleiner oder gleich ev, so wird Leelas Zug gespielt. Ist sie aber höher, so „überstimmt“ Stockfish nun Leela und es wird der von Stockfish favorisierte Zug gespielt, also der erste Zug in der MV-Zugliste von Stockfish. Da dies der komplizierteste Fall ist, hier ein Beispiel, wobei Züge und Zugnummern beliebig gewählt sind:
Leela möchte in einer Brettstellung 24.Da4 spielen. Stockfish hat mit 5 Varianten im MV-Modus gerechnet und folgendes Resultat errechnet:
1.) Eval +0.20 Line: 24.Ta5 Kf8 25.Df3 usw...
2.) Eval +0.12 Line: 24.Sc5 Ta8 25.Lf3 usw...
3.) Eval -0.40 Line: 24.Da4 Tf8 25.Sf3 usw...
4.) Eval -0.71 Line: 24.Sd4 Ta8 25.Ta3 usw...
5.) Eval -1.33 Line: 24.Lc7 Ta8 25.Ta3 usw...
Ist ev nun größer oder gleich 60 (centipawns) gesetzt, so würde Stockfish Leela „ihren Willen“ lassen und es würde 24.Da4 gespielt, da die Differenz der Evals von Zug 1 (+0.20 (= +20 centipawns)) und Leelas favorisiertem Zug 24.Da4, also Zug 3 in der MV-Variantenliste von Stockfish, (-0.40 (= -40 centipawns)) = 0.60 = 60 centipawns ist. Wäre ev nur auf z.B. 50 gesetzt, so würde Stockfish hier eingreifen und seinen favorisierten Zug, also 24.Ta5, spielen.
Es ist klar, daß Leela umso mehr „spielerische Freiheiten“ hat, je höher die Parameter n (Zahl der MV-Varianten) und ev (Bewertungsschwellwert) gesetzt werden. Gleichzeitig würde sich aber im Gegenzug auch die taktische Anfälligkeit erhöhen. Welche Werte für n und ev optimal sind, müßten natürlich umfangreiche Experimente (Clop-Tuning?) zeigen. Aus meinen Erfahrungen mit Stockfish heraus, würde ich n=7 und ev=40 ausprobieren, aber das sind nur Schätzungen. Auch die verwendete Hardware, auf der der Leela-Stockfish Hybrid läuft, würde hier sicher eine Rolle spielen.
Ich hoffe, ein erfahrener Programmierer wird meine Idee realisieren. Denn ich glaube, so könnte eine alles überragende Spielstärke auf dem Schachbrett erreicht werden!
Der Programmieraufwand sollte relativ überschaubar sein, zumindest für jemanden der mit der Nutzung der UCI-Schnittstelle Erfahrung hat und den Stockfish Programmcode gut kennt. Denn es ist ja nicht nötig, ein eigenes Schachprogramm zu schreiben. Nur eine gemeinsame Schnittstelle für Leela und Stockfish und die Steuerung derselben über die zwei UCI-Parameter n und ev wird benötigt.
Ich hatte diese Idee mal in Kurzform mit Thomas Zipproth (BrainFish) erörtert. Leider ist dieser z.Zt. sehr stark zeitlich ausgelastet und wird wohl nicht dazu kommen, mein Konzept umzusetzen.
Stefan (SPCC)