Lassen Sie uns einen supereinfachen rundenbasierten Kampf im Drakue-Stil machen und Q lernen. Der Zweck ist es, den tapferen Mann, der die Welt nur mit wenigen Prozent Chance retten kann, schlauer zu machen, indem er Q lernt.
Außerdem werde ich die Implementierung des Spielteils und des Q-Lernens erklären, aber ich werde das Q-Lernen selbst nicht erklären. Wenn Sie die detaillierte Theorie des Q-Lernens kennenlernen möchten, werden Sie sich freuen, wenn Sie diese guten Artikel einzeln lesen.
Stärkung des Lernens (1): Zustandswertfunktion und Bellman-Gleichung
Die Regeln sind einfach wie folgt aufgebaut:
Lassen Sie uns nun das Spiel selbst implementieren. Erstens ist die Zeichenklasse.
dq_battle.py
class Character(object):
"""Zeichenklasse"""
ACTIONS = {0: "Attacke", 1: "Wiederherstellung"}
def __init__(self, hp, max_hp, attack, defence, agillity, intelligence, name):
self.hp = hp #Aktuelle HP
self.max_hp = max_hp #Maximale HP
self.attack = attack #Offensivkraft
self.defence = defence #Verteidigungskraft
self.agillity = agillity #Beweglichkeit
self.intelligence = intelligence #Weise
self.name = name #Charaktername
#Gibt eine Statuszeichenfolge zurück
def get_status_s(self):
return "[{}] HP:{}/{} ATK:{} DEF:{} AGI:{} INT:{}".format(
self.name, self.hp, self.max_hp, self.attack, self.defence, self.agillity, self.intelligence)
def action(self, target, action):
#Attacke
if action == 0:
#Offensivkraft-Defensive Schadensberechnung
damage = self.attack - target.defence
draw_damage = damage #Für Protokolle
#Wenn die verbleibenden HP des Gegners geringer sind als der Schaden, ist der Schaden nur die verbleibenden HP
if target.hp < damage:
damage = target.hp
#Schaden verursachen
target.hp -= damage
#Gib das Kampfprotokoll zurück
return "{}Ist{}Zu{}Beschädigt".format(
self.name, target.name, draw_damage)
#Wiederherstellung
elif action == 1:
#Der Wiederherstellungsbetrag sei der Wert von INT
heal_points = self.intelligence
draw_heal_points = heal_points #Für Protokolle
#Wenn Sie auf maximale HP wiederherstellen können, maximale HP-Verwenden Sie die aktuellen HP als Wiederherstellungsbetrag
if self.hp + heal_points > self.max_hp:
heal_points = self.max_hp - self.hp
#Wiederherstellung
self.hp += heal_points
#Gib das Kampfprotokoll zurück
return "{}HP{}Wiederhergestellt".format(
self.name, draw_heal_points)
Da das Schlachtdesign diesmal einfach ist, haben wir es in einer Klasse zusammengefasst, ohne zwischen dem Spieler und dem Feind zu unterscheiden.
Jeder Charakter (Brave and Demon King)
Hat den Status von.
Schadensberechnung in "Angriff" ist
Es wird nach der einfachen Formel berechnet. Auch der Umfang der Wiederherstellung mit dem Befehl "Wiederherstellung" entspricht dem Wert der Klugheit.
Als nächstes werden wir den Kampfkörper implementieren. Zunächst müssen Sie das Gesamtbild (Zustandsübergang) der Schlacht verstehen.
dq_battle.py
class GameState(Enum):
"""Spielstatus-Management-Klasse"""
TURN_START = auto() #Start drehen
COMMAND_SELECT = auto() #Befehlsauswahl
TURN_NOW = auto() #Während des Zuges (jede Charakteraktion)
TURN_END = auto() #Ende der Runde
GAME_END = auto() #Spiel ist aus
Wie oben für die Schlacht erwähnt ** "Runde starten" "Befehl auswählen" "Während der Runde" "Runde beenden" "Spiel beenden" ** Es gibt fünf Staaten.
Das Zustandsübergangsdiagramm ist wie unten gezeigt.
Auf diese Weise besteht die Grundlage des Kampfdesigns darin, den Übergang vom "Turn Start" -Zustand zum "Turn End" -Zustand endlos bis zum "Game End" -Zustand zu wiederholen (bis die HP des Helden oder des Dämonenkönigs 0 werden). Wird sein.
Lassen Sie uns nun den Kampf selbst durchführen. Schauen wir uns zuerst den gesamten Code an.
dq_battle.py
class Game():
"""Spielkörper"""
HERO_MAX_HP = 20
MAOU_MAX_HP = 50
def __init__(self):
#Charakter erzeugen
self.hero = Character(
Game.HERO_MAX_HP, Game.HERO_MAX_HP, 4, 1, 5, 7, "Mutig")
self.maou = Character(
Game.MAOU_MAX_HP, Game.MAOU_MAX_HP, 5, 2, 6, 3, "Teufel")
#Zur Charakterliste hinzufügen
self.characters = []
self.characters.append(self.hero)
self.characters.append(self.maou)
#Definieren Sie Variablen für Zustandsübergänge
self.game_state = GameState.TURN_START
#Anzahl der Züge
self.turn = 1
#Zeichenkette zum Speichern des Kampfprotokolls
self.log = ""
#Verbessere das Spiel in jeder Runde
def step(self, action):
#Hauptschleife
while (True):
if self.game_state == GameState.TURN_START:
self.__turn_start()
elif self.game_state == GameState.COMMAND_SELECT:
self.__command_select(action) #Übergeben Sie die Aktion
elif self.game_state == GameState.TURN_NOW:
self.__turn_now()
elif self.game_state == GameState.TURN_END:
self.__turn_end()
break #Verlasse die Schleife am Ende der Kurve
elif self.game_state == GameState.GAME_END:
self.__game_end()
break
#Ob das Spiel vorbei ist
done = False
if self.game_state == GameState.GAME_END:
done = True
#Gibt "Zustand s, Belohnung r, Spielende" zurück
return (self.hero.hp, self.maou.hp), self.reward, done
#Initialisiere das Spiel auf den Zustand der ersten Runde
def reset(self):
self.__init__()
return (self.hero.hp, self.maou.hp)
#Zeichne das Kampfprotokoll
def draw(self):
print(self.log, end="")
def __turn_start(self):
#Staatsübergang
self.game_state = GameState.COMMAND_SELECT
#Protokoll initialisieren
self.log = ""
#Zeichnung
s = " ***Wende" + str(self.turn) + " ***"
self.__save_log("\033[36m{}\033[0m".format(s))
self.__save_log(self.hero.get_status_s())
self.__save_log(self.maou.get_status_s())
def __command_select(self, action):
#Aktionsauswahl
self.action = action
#Zeichen Zufallszahl 0.5〜1.Sortieren Sie nach Agilität von 5 und speichern Sie in der Warteschlange
self.character_que = deque(sorted(self.characters,
key=lambda c: c.agillity*random.uniform(0.5, 1.5)))
#Staatsübergang
self.game_state = GameState.TURN_NOW
#Protokoll speichern
self.__save_log("Befehlsauswahl-> " + Character.ACTIONS[self.action])
def __turn_now(self):
#Sequentielle Aktion aus der Zeichenwarteschlange
if len(self.character_que) > 0:
now_character = self.character_que.popleft()
if now_character is self.hero:
s = now_character.action(self.maou, self.action)
elif now_character is self.maou:
s = now_character.action(self.hero, action=0) #Dämonenkönig greift immer an
#Protokoll speichern
self.__save_log(s)
#Spielende, wenn HP 0 oder weniger ist
for c in self.characters:
if c.hp <= 0:
self.game_state = GameState.GAME_END
return
#Schalten Sie das Ende aus, wenn alle die Aktion beendet haben
if len(self.character_que) == 0:
self.game_state = GameState.TURN_END
return
def __turn_end(self):
#Belohnung festlegen
self.reward = 0
#Initialisierung der Zeichenwarteschlange
self.character_que = deque()
#Drehen Sie den Fortschritt
self.turn += 1
#Staatsübergang
self.game_state = GameState.TURN_START
def __game_end(self):
if self.hero.hp <= 0:
self.__save_log("\033[31m{}\033[0m".format("Der Held ist tot"))
self.reward = -1 #Belohnung festlegen
elif self.maou.hp <= 0:
self.__save_log("\033[32m{}\033[0m".format("Besiegte den Dämonenkönig"))
self.reward = 1 #Belohnung festlegen
self.__save_log("-----Spielende-----")
def __save_log(self, s):
self.log += s + "\n"
Der Code ist etwas lang, aber es gibt nur zwei wichtige Teile des Q-Lernens.
Die erste ist die step () -Methode. Dies ist der Hauptteil der Schlacht.
dq_battle.py
#Verbessere das Spiel in jeder Runde
def step(self, action):
#Hauptschleife
while (True):
if self.game_state == GameState.TURN_START:
self.__turn_start()
elif self.game_state == GameState.COMMAND_SELECT:
self.__command_select(action) #Übergeben Sie die Aktion
elif self.game_state == GameState.TURN_NOW:
self.__turn_now()
elif self.game_state == GameState.TURN_END:
self.__turn_end()
break #Verlasse die Schleife am Ende der Kurve
elif self.game_state == GameState.GAME_END:
self.__game_end()
break
#Ob das Spiel vorbei ist
done = False
if self.game_state == GameState.GAME_END:
done = True
#Gibt "Zustand s, Belohnung r, Spielende" zurück
return (self.hero.hp, self.maou.hp), self.reward, done
Grundsätzlich ist der Verarbeitungsablauf derselbe wie das oben beschriebene Zustandsübergangsdiagramm.
Beim Q-Lernen muss der aktuelle Status jedoch ** in jeder Runde ** ausgewertet werden, sodass Sie die Hauptschleife nicht nur im Status "Spielende", sondern auch im Status "Spielende" verlassen müssen.
Im Zustand "Ende der Runde" müssen folgende Variablen ausgewertet werden, um Q-Lernen durchzuführen:
Dort sind drei.
Ob es das Ende des Spiels ist, hängt einfach davon ab, ob die HP des Helden oder die HP des Dämonenkönigs 0 geworden sind.
Wir müssen ein wenig über den Staat nachdenken. Es gibt mehrere Statistiken wie Offensivkraft und Defensivkraft, aber es gibt tatsächlich nur zwei Statistiken, die beim Q-Lernen bewertet werden sollten: "Brave HP" und "Demon King HP".
In diesem Kampfdesign sind die Werte wie Angriffs- und Verteidigungskraft immer konstant, sodass keine anderen Statistiken als HP ausgewertet werden müssen. Umgekehrt sind diese Informationen auch erforderlich, wenn sich der Status aufgrund von Polieren, Debuffing usw. ändert.
Die Belohnung r wird in jedem der Zustände "Ende des Zuges" und "Ende des Spiels" bewertet.
dq_battle.py
def __turn_end(self):
#Belohnung festlegen
self.reward = 0
#(Kürzung)
def __game_end(self):
if self.hero.hp <= 0:
self.__save_log("\033[31m{}\033[0m".format("Der Held ist tot"))
self.reward = -1 #Belohnung festlegen
elif self.maou.hp <= 0:
self.__save_log("\033[32m{}\033[0m".format("Besiegte den Dämonenkönig"))
self.reward = 1 #Belohnung festlegen
Die Belohnung für den Durchgang von Runden ist 0. Wenn Sie sich des Zwecks bewusst sind, "den Dämonenkönig mit der schnellsten Geschwindigkeit zu besiegen", können Sie die Belohnung nach dem Zug negativ machen. (Es ist jedoch schwierig, geeignete Parameter einzustellen.)
Wenn der Held am Ende des Spiels fällt, wird er mit "-1" belohnt, und wenn er den Dämonenkönig besiegt, wird er mit "+1" belohnt.
Der zweite wichtige Teil ist die Methode reset ().
dq_battle.py
#Initialisiere das Spiel auf den Zustand der ersten Runde
def reset(self):
self.__init__()
return (self.hero.hp, self.maou.hp)
Es ist nur eine Methode, um das Spiel zu initialisieren. Außerdem muss der Ausgangszustand für das Q-Lernen zurückgegeben werden.
Zusammen mit der obigen Methode step ()
** Spielinitialisierung (Zurücksetzen) → Den Zug vorrücken, bis der Kampf endet (Schritt) → Spielinitialisierung (Zurücksetzen) → Den Zug vorrücken, bis der Kampf endet (Schritt) ・ ・ ・ **
Sie können mit dem Lernen fortfahren, indem Sie das Spiel wiederholen.
Das Obige ist der grundlegende Teil des Spiels für das Q-Lernen.
Q-Learning wird innerhalb der Agentenklasse implementiert. Ein Agent ist eine Klasse wie ein Spieler, der tatsächlich ein Spiel spielt.
Da der Agent der Spieler selbst ist, kann er die Aktion (Angriff oder Wiederherstellung) auswählen und den Zustand kennen (wie die HP des Helden oder des Dämonenkönigs), aber Es ist nicht möglich, die internen Informationen des Spiels zu kennen (z. B. die Zufallszahl, die die Reihenfolge der Aktionen bestimmt).
Das Lernen basiert nur auf der "Aktion" und dem "Zustand" und der "Belohnung", die durch diese Aktion erhalten werden. Dies ist ein grundlegendes Verständnis zur Stärkung des Lernens im Allgemeinen, einschließlich des Q-Lernens.
Zuerst werde ich die gesamte Agentenklasse veröffentlichen.
q-learning.py
DIV_N = 10
class Agent:
"""Agentenklasse"""
def __init__(self, epsilon=0.2):
self.epsilon = epsilon
self.Q = []
#Ε Politik-Definiert durch die gierige Methode
def policy(self, s, actions):
if np.random.random() < self.epsilon:
#Epsilon Chance, zufällig zu handeln
return np.random.randint(len(actions))
else:
#(Wenn Q den Zustand s enthält und der Q-Wert in diesem Zustand nicht 0 ist)
if s in self.Q and sum(self.Q[s]) != 0:
#Handeln Sie so, dass der Q-Wert maximiert wird
return np.argmax(self.Q[s])
else:
return np.random.randint(len(actions))
#Status in Nummer umwandeln
def digitize_state(self, s):
hero_hp, maou_hp = s
#Tauchen Sie jeweils die HP des Helden und des Dämonenkönigs_Teilen Sie durch N.
s_digitize = [np.digitize(hero_hp, np.linspace(0, dq_battle.Game.HERO_MAX_HP, DIV_N + 1)[1:-1]),
np.digitize(maou_hp, np.linspace(0, dq_battle.Game.MAOU_MAX_HP, DIV_N + 1)[1:-1])]
# DIV_Gibt die Anzahl der Zustände bis zum Quadrat von N zurück
return s_digitize[0] + s_digitize[1]*DIV_N
#Q Lernen
def learn(self, env, actions, episode_count=1000, gamma=0.9, learning_rate=0.1):
self.Q = defaultdict(lambda: [0] * len(actions))
# episode_Kampf um die Zählung
for e in range(episode_count):
#Setzen Sie die Spielumgebung zurück
tmp_s = env.reset()
#Konvertieren Sie den aktuellen Status in einen numerischen Wert
s = self.digitize_state(tmp_s)
done = False
#Wiederholen Sie die Aktion bis zum Ende des Spiels
while not done:
# ε-Wählen Sie die Aktion gemäß der gierigen Richtlinie
a = self.policy(s, actions)
#Erhöhen Sie das Spiel um eine Runde und geben Sie den "Status, Belohnung, Spielende" zu diesem Zeitpunkt zurück
tmp_s, reward, done = env.step(a)
#Status in Nummer umwandeln
n_state = self.digitize_state(tmp_s)
#Wertschöpfung durch Aktion a(gain) =Sofortige Belohnung+Zeitabzinsungssatz*Maximaler Q-Wert in den folgenden Zuständen
gain = reward + gamma * max(self.Q[n_state])
#Q-Wert derzeit geschätzt (vor dem Lernen)
estimated = self.Q[s][a]
#Aktualisieren Sie den Q-Wert basierend auf dem aktuellen Schätzwert und dem tatsächlichen Wert, wenn Sie Aktion a ausführen
self.Q[s][a] += learning_rate * (gain - estimated)
#Ändern Sie den aktuellen Status in den nächsten Status
s = n_state
Was in der Agentenklasse etwas verwirrend ist, ist die Methode, die den Status in eine Zahl konvertiert.
q-learning.py
#Status in Nummer umwandeln
def digitize_state(self, s):
hero_hp, maou_hp = s
#Tauchen Sie jeweils die HP des Helden und des Dämonenkönigs_Teilen Sie in N.
s_digitize = [np.digitize(hero_hp, np.linspace(0, dq_battle.Game.HERO_MAX_HP, DIV_N + 1)[1:-1]),
np.digitize(maou_hp, np.linspace(0, dq_battle.Game.MAOU_MAX_HP, DIV_N + 1)[1:-1])]
# DIV_Gibt die Anzahl der Zustände bis zum Quadrat von N zurück
return s_digitize[0] + s_digitize[1]*DIV_N
Wie ich bereits kurz erwähnt habe, gibt es zwei Zustandsvariablen, die beim Lernen von Q ausgewertet werden sollten: "Brave HP" und "Devil's HP". Beim Q-Lernen muss der Zustand jedoch als einzelne Zahl dargestellt werden. Mit anderen Worten ist das Bild wie folgt.
Sie können wie oben konvertieren, dies erhöht jedoch den Status um die Anzahl der HP x HP. Wie bei einem bestimmten nationalen Rollenspiel, das kein Drakue ist, übersteigt die Anzahl der Staaten 1 Million, wenn die HP 4-stellig ist, und es ist schwierig (lacht). Teilen wir daher den Zustand nach dem Verhältnis von HP.
np.digitize(hero_hp, np.linspace(0, dq_battle.Game.HERO_MAX_HP, DIV_N + 1)[1:-1]
Eine kurze Erklärung dieses Codes Teilen Sie mit np.linspace () von 0 bis maximal HP in N, Dies ist ein Bild, das die Anzahl der Abteilungen zurückgibt, zu denen die aktuelle HP mit np.digitize () gehört.
Da diesmal N = 10 ist,
Es wird so konvertiert. Und dazu
"Tapferer Zustand (0-9) + Dämonenkönigzustand (0-9) * 10" Durch Berechnung kann die Anzahl der Zustände von 0 auf 99 auf 100 unterdrückt werden.
Wenn der Status "15" ist, können Sie intuitiv verstehen, dass die HP des Dämonenkönigs weniger als "10"% und die HP des Helden weniger als "50"% betragen.
Die Politik ist ε-gierig.
q-learning.py
#Ε Politik-Definiert durch die gierige Methode
def policy(self, s, actions):
if np.random.random() < self.epsilon:
#Epsilon Chance, zufällig zu handeln
return np.random.randint(len(actions))
else:
#(Wenn Q den Zustand s enthält und der Q-Wert in diesem Zustand nicht 0 ist)
if s in self.Q and sum(self.Q[s]) != 0:
#Handeln Sie so, dass der Q-Wert maximiert wird
return np.argmax(self.Q[s])
else:
return np.random.randint(len(actions))
Um es Anfängern kurz zu erklären, ist es im Grunde eine Richtlinie, die Aktion so zu entscheiden, dass der Aktionswert maximiert wird, und eine zufällige Aktion mit einer Wahrscheinlichkeit von ε zu übernehmen.
Indem den Aktionen ein gewisses Maß an Zufälligkeit verliehen wird, werden verschiedene Aktionen durchsucht, sodass ein angemessenes Lernen möglich ist, ohne vom Anfangswert des Q-Werts abhängig zu sein.
Übrigens haben wir zu diesem Zeitpunkt alle Variablen und Methoden, die für das Q-Lernen erforderlich sind.
Der Q-Lernalgorithmus ist wie folgt.
Wie am Anfang des Artikels erwähnt, werde ich die Theorie des Q-Lernens nicht erklären, also lassen Sie uns den obigen Algorithmus gehorsam implementieren.
q-learning.py
#Q Lernen
def learn(self, env, actions, episode_count=1000, gamma=0.9, learning_rate=0.1):
self.Q = defaultdict(lambda: [0] * len(actions))
# episode_Kampf um die Zählung
for e in range(episode_count):
#Setzen Sie die Spielumgebung zurück
tmp_s = env.reset()
#Konvertieren Sie den aktuellen Status in einen numerischen Wert
s = self.digitize_state(tmp_s)
done = False
#Wiederholen Sie die Aktion bis zum Ende des Spiels
while not done:
# ε-Wählen Sie die Aktion gemäß der gierigen Richtlinie
a = self.policy(s, actions)
#Erhöhen Sie das Spiel um eine Runde und geben Sie den "Status, Belohnung, Spielende" zu diesem Zeitpunkt zurück
tmp_s, reward, done = env.step(a)
#Status in Nummer umwandeln
n_state = self.digitize_state(tmp_s)
#Wertschöpfung durch Aktion a(gain) =Sofortige Belohnung+Zeitabzinsungssatz*Maximaler Q-Wert in den folgenden Zuständen
gain = reward + gamma * max(self.Q[n_state])
#Q-Wert derzeit geschätzt (vor dem Lernen)
estimated = self.Q[s][a]
#Aktualisieren Sie den Q-Wert basierend auf dem aktuellen Schätzwert und dem tatsächlichen Wert, wenn Sie Aktion a ausführen
self.Q[s][a] += learning_rate * (gain - estimated)
#Ändern Sie den aktuellen Status in den nächsten Status
s = n_state
Damit ist die Implementierung des Spiels und das Q-Lernen abgeschlossen.
F Bevor wir lernen, versuchen wir, was passiert, wenn Sie mit zufälligen Aktionen von Helden kämpfen.
Fügen Sie den folgenden Code hinzu.
q-learning.py
class Agent:
#(Kürzung)
#Testschlacht
def test_run(self, env, actions, draw=True, episode_count=1000):
turn_num = 0 #Anzahl der Niederlagen
win_num = 0 #Anzahl der Siege
# episode_Kampf um die Zählung
for e in range(episode_count):
tmp_s = env.reset()
s = self.digitize_state(tmp_s)
done = False
while not done:
a = self.policy(s, actions)
n_state, _, done = env.step(a)
s = self.digitize_state(n_state)
if draw:
env.draw() #Zeichne das Kampfprotokoll
if env.maou.hp <= 0:
win_num += 1
turn_num += env.turn
#Geben Sie die durchschnittliche Gewinnrate und die durchschnittliche Anzahl der Niederlage-Runden aus
if not win_num == 0:
print("Durchschnittliche Gewinnrate{:.2f}%".format(win_num*100/episode_count))
print("Durchschnittliche Anzahl von Niederlagen:{:.2f}".format(turn_num / win_num))
else:
print("Durchschnittliche Gewinnrate 0%")
if __name__ == "__main__":
game = dq_battle.Game()
agent = Agent()
actions = dq_battle.Character.ACTIONS
"""Völlig zufälliger Kampf"""
agent.epsilon = 1.0
agent.test_run(game, actions, episode_count=1000)
Durch Setzen von ε = 1,0 wird 100% völlig zufällig gehandelt. Außerdem habe ich versucht, die durchschnittliche Gewinnrate und die durchschnittliche Anzahl besiegter Runden aus den Ergebnissen von 1000 Schlachten zu berechnen.
Unten sind die Ausführungsergebnisse.
$ python q-learning.py
Durchschnittliche Gewinnrate 0.90%
Durchschnittliche Anzahl von Niederlagen:64.89
Die Gewinnrate ist ziemlich niedrig ...
Wie Sie an der Anzahl der Runden sehen können, handelt es sich in der Regel um einen langfristigen Kampf. Je länger der Kampf dauert, desto mehr wird der Held sterben, und infolgedessen wird es schwierig sein, zu gewinnen.
Fügen Sie den folgenden Code hinzu.
q-learning.py
if __name__ == "__main__":
#(Kürzung)
"""Q Lernen"""
agent.epsilon = 0.2
agent.learn(game, actions, episode_count=1000)
"""Testschlacht"""
agent.epsilon = 0
agent.test_run(game, actions, episode_count=1000)
Setzen wir ε = 0,2 und führen das Q-Lernen durch.
Danach finden 1000 Testkämpfe statt. Durch Setzen von ε = 0 (0% zufällig) wird das Verhalten gemäß dem gelernten Aktionswert ausgeführt.
Unten werden die Ausführungsergebnisse angezeigt, indem die Anzahl der zu lernenden Schlachten geändert wird.
** Ausführungsergebnis (Anzahl der Lernkämpfe: 50, Anzahl der Testkämpfe: 1000) **
$ python q-learning.py
Durchschnittliche Gewinnrate 42.60%
Durchschnittliche Anzahl von Niederlagen:56.19
** Ausführungsergebnis (500 Lernschlachten, 1000 Testschlachten) **
$ python q-learning.py
Durchschnittliche Gewinnrate 100.00%
Durchschnittliche Anzahl von Niederlagen:55.00
** Ausführungsergebnis (5000 Lernschlachten, 1000 Testschlachten) **
$ python q-learning.py
Durchschnittliche Gewinnrate 100.00%
Durchschnittliche Anzahl von Niederlagen:54.00
Die Gewinnquote beträgt 100%!
Lassen Sie uns ein wenig überlegen. Sehen wir uns den Q-Wert des gelernten Ergebnisses an.
Unten wird der Q-Wert beim Lernen mit 1000 Schlachten für einige Zustände extrahiert.
Zustand 50:[-0.19, -0.1]
Zustand 51:[-0.6623164987957537, -0.34788781183605283]
Zustand 52:[-0.2711479211007827, 0.04936802595531123]
Zustand 53:[-0.36097806076138395, 0.11066249745943924]
Zustand 54:[-0.04065992616558749, 0.12416469852733954]
Zustand 55:[0.17619052640036173, 0.09475948937059306]
Zustand 56:[0.10659739434775867, 0.05112985778828942]
Zustand 57:[0.1583472103200607, 0.016092008419030468]
Zustand 58:[0.04964633744625512, 0.0020759614034820224]
Zustand 59:[0.008345513895442138, 0.0]
Wie man den Staat sieht, ist der 10. Platz die verbleibende HP des Dämonenkönigs und der 1. Platz die verbleibende HP des Helden. Mit anderen Worten, die obige Abbildung zeigt, wie sich der Aktionswert in Abhängigkeit von den verbleibenden HP des Helden ändert, wenn die verbleibenden HP des Dämonenkönigs etwa 50% betragen.
Aus der Abbildung ist ersichtlich, dass der Befehl "Wiederherstellung" ausgewählt ist, wenn die verbleibenden HP (1. Platz) des Helden niedrig sind, und wenn die verbleibenden HP hoch sind, der Befehl "Angriff" ausgewählt ist.
Schauen wir uns auch den Q-Wert an, wenn die verbleibenden HP des Helden festgelegt sind.
Zustand 07:[2.023809062133135, 0.009000000000000001]
Zustand 17:[1.8092946131557912, 0.8310497919226313]
Zustand 27:[0.8223927076749513, 0.5279685031058523]
Zustand 37:[0.5565475393122992, 0.29257906153106145]
Zustand 47:[0.25272081107828437, 0.26657637207739293]
Zustand 57:[0.14094053800308323, 0.1533527340827757]
Zustand 67:[0.0709128688771915, 0.07570873469406877]
Zustand 77:[0.039059851207044236, 0.04408123679644829]
Zustand 87:[0.023028972190011696, 0.02386492692407677]
Zustand 97:[0.016992303227705185, 0.0075795064515745995]
Die obige Abbildung zeigt, wie sich der Aktionswert in Abhängigkeit von den verbleibenden HP des Dämonenkönigs ändert, wenn die verbleibenden HP des Helden etwa 70% betragen. Sie können sehen, dass je weniger HP der Dämonenkönig übrig hat, desto mehr "Angriff" überlegen ist.
Da dieser Artikel hauptsächlich implementiert ist, werden andere Überlegungen weggelassen. Wenn Sie es sich leisten können, wird es interessant sein, zu lernen, indem Sie die Hyperparameter ändern oder versuchen, die Kampfregeln komplizierter zu gestalten.
Da ich ein Anfänger in der Stärkung des Lernens bin, können Sie auch auf Fehler hinweisen. Ich bin froh, dass mein Wissen gestärkt wurde.
Die Quelle ist auf Github. https://github.com/nanoseeing/DQ_Q-learning
Recommended Posts