Dies ist mein erster Qiita-Beitrag. Wir beraten und entwickeln hauptsächlich maschinelles Lernen in einem Unternehmen namens Ridge-i.
Jetzt, da ich die Möglichkeit habe, über die Stärkung des Lernens zu unterrichten, werde ich die dritte Zeile als Basis verwenden.
--Monte Carlo
Ich habe es mit Jupyter (ipython) implementiert und Unterrichtsmaterialien erstellt.
Übrigens, wenn Sie ein starker Spieler sind, sollte nur die Auslosung wiederholt werden. (Es ist ein berühmter WarGame-Typ.)
Als Schlussfolgerung
--Monte Carlo Einfach zu implementieren. Fast kein Verlust in 100 Versuchen (manchmal verliert in etwa 50) --Q-Learning Achten Sie auf das erneuerbare Design. Das stärkste in 100.000 Schlachten, wenn es sich um 3 Linien handelt
Die Implementierung dauerte nur 1-2 Stunden bis zum Q-Learning, aber es dauerte ungefähr 6 Stunden, bis DQN richtig gelernt hatte. (Weinen)
Um die Lerneffizienz zu verbessern, ist es besser, das Board richtig zu drehen und zu drehen, aber diesmal habe ich es mit Schwerpunkt auf Klarheit ausgewählt. Außerdem habe ich die Benutzeroberfläche nicht richtig entworfen und die Variablen ausgeblendet, sodass ich sie manchmal verletze. Ignoriere diesen Bereich.
Klicken Sie hier für Github. https://github.com/narisan25/TTT-RL
Wenn Sie die theoretischen Details erfahren möchten, kontaktieren Sie uns bitte separat. Auch darauf hingewiesen, verbessert, beraten, sehr willkommen.
Dies ist eine grobe Skizze. Es gibt viele Punkte, die verbessert werden müssen, aber dieses Mal konzentrieren wir uns auf Klarheit und Geschwindigkeit (bewegen Sie sich einfach)
Geben Sie 1 für X, 0 für leer und -1 für ○ in das Array 0-9 ein.
EMPTY=0
PLAYER_X=1
PLAYER_O=-1
MARKS={PLAYER_X:"X",PLAYER_O:"O",EMPTY:" "}
DRAW=2
class TTTBoard:
def __init__(self,board=None):
if board==None:
self.board = []
for i in range(9):self.board.append(EMPTY)
else:
self.board=board
self.winner=None
def get_possible_pos(self):
pos=[]
for i in range(9):
if self.board[i]==EMPTY:
pos.append(i)
return pos
def print_board(self):
tempboard=[]
for i in self.board:
tempboard.append(MARKS[i])
row = ' {} | {} | {} '
hr = '\n-----------\n'
print((row + hr + row + hr + row).format(*tempboard))
def check_winner(self):
win_cond = ((1,2,3),(4,5,6),(7,8,9),(1,4,7),(2,5,8),(3,6,9),(1,5,9),(3,5,7))
for each in win_cond:
if self.board[each[0]-1] == self.board[each[1]-1] == self.board[each[2]-1]:
if self.board[each[0]-1]!=EMPTY:
self.winner=self.board[each[0]-1]
return self.winner
return None
def check_draw(self):
if len(self.get_possible_pos())==0 and self.winner is None:
self.winner=DRAW
return DRAW
return None
def move(self,pos,player):
if self.board[pos]== EMPTY:
self.board[pos]=player
else:
self.winner=-1*player
self.check_winner()
self.check_draw()
def clone(self):
return TTTBoard(self.board.copy())
def switch_player(self):
if self.player_turn == self.player_x:
self.player_turn=self.player_o
else:
self.player_turn=self.player_x
Machen Sie es zu einem Observer + Mediator-Modell. Auf diese Weise können Sie Züge, Gewinne und Verluste, Anzeigen usw. verwalten und gleichzeitig verhindern, dass der Spieler das Spielfeld direkt berührt.
class TTT_GameOrganizer:
act_turn=0
winner=None
def __init__(self,px,po,nplay=1,showBoard=True,showResult=True,stat=100):
self.player_x=px
self.player_o=po
self.nwon={px.myturn:0,po.myturn:0,DRAW:0}
self.nplay=nplay
self.players=(self.player_x,self.player_o)
self.board=None
self.disp=showBoard
self.showResult=showResult
self.player_turn=self.players[random.randrange(2)]
self.nplayed=0
self.stat=stat
def progress(self):
while self.nplayed<self.nplay:
self.board=TTTBoard()
while self.board.winner==None:
if self.disp:print("Turn is "+self.player_turn.name)
act=self.player_turn.act(self.board)
self.board.move(act,self.player_turn.myturn)
if self.disp:self.board.print_board()
if self.board.winner != None:
# notice every player that game ends
for i in self.players:
i.getGameResult(self.board)
if self.board.winner == DRAW:
if self.showResult:print ("Draw Game")
elif self.board.winner == self.player_turn.myturn:
out = "Winner : " + self.player_turn.name
if self.showResult: print(out)
else:
print ("Invalid Move!")
self.nwon[self.board.winner]+=1
else:
self.switch_player()
#Notice other player that the game is going
self.player_turn.getGameResult(self.board)
self.nplayed+=1
if self.nplayed%self.stat==0 or self.nplayed==self.nplay:
print(self.player_x.name+":"+str(self.nwon[self.player_x.myturn])+","+self.player_o.name+":"+str(self.nwon[self.player_o.myturn])
+",DRAW:"+str(self.nwon[DRAW]))
def switch_player(self):
if self.player_turn == self.player_x:
self.player_turn=self.player_o
else:
self.player_turn=self.player_x
Es ist eine einfache, die Sie einfach dort platzieren, wo Sie sie platzieren können.
import random
class PlayerRandom:
def __init__(self,turn):
self.name="Random"
self.myturn=turn
def act(self,board):
acts=board.get_possible_pos()
i=random.randrange(len(acts))
return acts[i]
def getGameResult(self,board):
pass
class PlayerHuman:
def __init__(self,turn):
self.name="Human"
self.myturn=turn
def act(self,board):
valid = False
while not valid:
try:
act = input("Where would you like to place " + str(self.myturn) + " (1-9)? ")
act = int(act)
#if act >= 1 and act <= 9 and board.board[act-1]==EMPTY:
if act >= 1 and act <= 9:
valid=True
return act-1
else:
print ("That is not a valid move! Please try again.")
except Exception as e:
print (act + "is not a valid move! Please try again.")
return act
def getGameResult(self,board):
if board.winner is not None and board.winner!=self.myturn and board.winner!=DRAW:
print("I lost...")
Lassen Sie uns zunächst zufällig mit Menschen kämpfen. Schade, wenn du verlierst.
def Human_vs_Random():
p1=PlayerHuman(PLAYER_X)
p2=PlayerRandom(PLAYER_O)
game=TTT_GameOrganizer(p1,p2)
game.progress()
Human_vs_Random()
Turn is Random
| |
-----------
| | O
-----------
| |
Turn is Human
Where would you like to place 1 (1-9)? 1
X | |
-----------
| | O
-----------
| |
Turn is Random
X | |
-----------
O | | O
-----------
| |
Turn is Human
Where would you like to place 1 (1-9)? 2
X | X |
-----------
O | | O
-----------
| |
Turn is Random
X | X |
-----------
O | O | O
-----------
| |
I lost...
Winner : Random
Human:0,Random:1,DRAW:0
Was im Protokoll verblieb, war ein Beispiel für den Verlust der Pflege.
Wie erwartet ist es langweilig, wenn es nur zufällig ist. Wenn es also einen Ort gibt, an dem Sie mit Ihrem nächsten Zug gewinnen können, versuchen Sie, ihn richtig auszurichten. (Zufällig wenn nicht)
class PlayerAlphaRandom:
def __init__(self,turn,name="AlphaRandom"):
self.name=name
self.myturn=turn
def getGameResult(self,winner):
pass
def act(self,board):
acts=board.get_possible_pos()
#see only next winnable act
for act in acts:
tempboard=board.clone()
tempboard.move(act,self.myturn)
# check if win
if tempboard.winner==self.myturn:
#print ("Check mate")
return act
i=random.randrange(len(acts))
return acts[i]
Von hier aus betreten wir nun den Bereich des verbesserten Lernens. In Monte Carlo werden wir eine bestimmte Anzahl von Malen bis zum Ende des Spiels gemäß einer bestimmten Richtlinie versuchen und nach einem guten Zug suchen, indem wir die Gewinnrate sehen.
Der wichtige Punkt von Monte Carlo ist, dass die Stärke von der Anzahl der "festen Zeiten" und "einer bestimmten Politik" abhängt.
Für "eine bestimmte Richtlinie" habe ich den zuvor erwähnten verbesserten Zufall verwendet. Nach dem Versuch "eine bestimmte Anzahl von Malen", wenn es 100 Mal überschreitet, scheint es, dass der falsche Zug nicht ausgeführt wird. Wenn es ungefähr 50 Mal ist, verlieren Sie manchmal abhängig von der Zufallszahl.
Von hier aus können Sie die Erfolgsbilanz in die dynamische Planung einfließen lassen oder von Montecult Tree Exploration (MCTS) ableiten, um starke und schwache Richtlinien zu kombinieren, aber ich werde sie diesmal nicht erwähnen.
class PlayerMC:
def __init__(self,turn,name="MC"):
self.name=name
self.myturn=turn
def getGameResult(self,winner):
pass
def win_or_rand(self,board,turn):
acts=board.get_possible_pos()
#see only next winnable act
for act in acts:
tempboard=board.clone()
tempboard.move(act,turn)
# check if win
if tempboard.winner==turn:
return act
i=random.randrange(len(acts))
return acts[i]
def trial(self,score,board,act):
tempboard=board.clone()
tempboard.move(act,self.myturn)
tempturn=self.myturn
while tempboard.winner is None:
tempturn=tempturn*-1
tempboard.move(self.win_or_rand(tempboard,tempturn),tempturn)
if tempboard.winner==self.myturn:
score[act]+=1
elif tempboard.winner==DRAW:
pass
else:
score[act]-=1
def getGameResult(self,board):
pass
def act(self,board):
acts=board.get_possible_pos()
scores={}
n=50
for act in acts:
scores[act]=0
for i in range(n):
#print("Try"+str(i))
self.trial(scores,board,act)
#print(scores)
scores[act]/=n
max_score=max(scores.values())
for act, v in scores.items():
if v == max_score:
#print(str(act)+"="+str(v))
return act
p1=PlayerMC(PLAYER_X,"M1")
p2=PlayerMC(PLAYER_O,"M2")
game=TTT_GameOrganizer(p1,p2,10,False)
game.progress()
Draw Game
Winner : M2
Draw Game
Draw Game
Draw Game
Draw Game
Draw Game
Winner : M2
Draw Game
Draw Game
M1:0,M2:2,DRAW:8
Es ist fast ein Unentschieden. Wenn Sie Lust dazu haben, probieren Sie 100 Versuche aus. Ich denke, es wird alles ein Unentschieden.
Q-Learning
Apropos Stärkung des Lernens, Q-Learning. Während des Spiels ist die Belohnung 0, wenn Sie gewinnen, erhalten Sie +1. Wenn Sie verlieren, erhalten Sie -1 und die Auslosung ist 0. Basierend darauf werden wir das Wörterbuch von Q (s, a) mit der folgenden Aktualisierungsformel aktualisieren.
Q(s,a) = Q(s,a) + alpha (reward + gammma* max(Q(s',a')- Q(s,a))
Das Wichtigste ist, zufällige Bewegungen mit dem Konzept von ε-gierig zu empfehlen. Andernfalls werden Sie bald in das lokale Optimum fallen. Der Wert des ersten Q ist ebenfalls wichtig. Andernfalls möchten Sie nicht sofort danach suchen. Ein egoistisches Kind.
Ich war überrascht, am Ende des Spiels herauszufinden, was mit max (Q) zu tun ist, und vergaß, während des Spiels zu aktualisieren.
class PlayerQL:
def __init__(self,turn,name="QL",e=0.2,alpha=0.3):
self.name=name
self.myturn=turn
self.q={} #set of s,a
self.e=e
self.alpha=alpha
self.gamma=0.9
self.last_move=None
self.last_board=None
self.totalgamecount=0
def policy(self,board):
self.last_board=board.clone()
acts=board.get_possible_pos()
#Explore sometimes
if random.random() < (self.e/(self.totalgamecount//10000+1)):
i=random.randrange(len(acts))
return acts[i]
qs = [self.getQ(tuple(self.last_board.board),act) for act in acts]
maxQ= max(qs)
if qs.count(maxQ) > 1:
# more than 1 best option; choose among them randomly
best_options = [i for i in range(len(acts)) if qs[i] == maxQ]
i = random.choice(best_options)
else:
i = qs.index(maxQ)
self.last_move = acts[i]
return acts[i]
def getQ(self, state, act):
# encourage exploration; "optimistic" 1.0 initial values
if self.q.get((state, act)) is None:
self.q[(state, act)] = 1
return self.q.get((state, act))
def getGameResult(self,board):
r=0
if self.last_move is not None:
if board.winner is None:
self.learn(self.last_board,self.last_move, 0, board)
pass
else:
if board.winner == self.myturn:
self.learn(self.last_board,self.last_move, 1, board)
elif board.winner !=DRAW:
self.learn(self.last_board,self.last_move, -1, board)
else:
self.learn(self.last_board,self.last_move, 0, board)
self.totalgamecount+=1
self.last_move=None
self.last_board=None
def learn(self,s,a,r,fs):
pQ=self.getQ(tuple(s.board),a)
if fs.winner is not None:
maxQnew=0
else:
maxQnew=max([self.getQ(tuple(fs.board),act) for act in fs.get_possible_pos()])
self.q[(tuple(s.board),a)]=pQ+self.alpha*((r+self.gamma*maxQnew)-pQ)
#print (str(s.board)+"with "+str(a)+" is updated from "+str(pQ)+" refs MAXQ="+str(maxQnew)+":"+str(r))
#print(self.q)
def act(self,board):
return self.policy(board)
pQ=PlayerQL(PLAYER_O,"QL1")
p2=PlayerQL(PLAYER_X,"QL2")
game=TTT_GameOrganizer(pQ,p2,100000,False,False,10000)
game.progress()
QL1:4371,QL2:4436,DRAW:1193
QL1:8328,QL2:8456,DRAW:3216
QL1:11903,QL2:11952,DRAW:6145
QL1:14268,QL2:14221,DRAW:11511
QL1:15221,QL2:15099,DRAW:19680
QL1:15730,QL2:15667,DRAW:28603
QL1:16136,QL2:16090,DRAW:37774
QL1:16489,QL2:16439,DRAW:47072
QL1:16832,QL2:16791,DRAW:56377
QL1:17128,QL2:17121,DRAW:65751
Bei der Auslosung ist es fast konvergiert. Sie können sehen, dass Sieg und Niederlage durch ε geteilt werden.
Setzen Sie ε auf Null, eliminieren Sie zufällige Elemente und versuchen Sie, mit der besten Bewegung anzugreifen
pQ.e=0
p2=PlayerMC(PLAYER_X,"M1")
game=TTT_GameOrganizer(pQ,p2,100,False,False,10)
game.progress()
QL1:1,M1:0,DRAW:9
QL1:1,M1:0,DRAW:19
QL1:2,M1:0,DRAW:28
QL1:2,M1:0,DRAW:38
QL1:3,M1:0,DRAW:47
QL1:4,M1:0,DRAW:56
QL1:5,M1:0,DRAW:65
QL1:5,M1:0,DRAW:75
QL1:6,M1:0,DRAW:84
QL1:6,M1:0,DRAW:94
Von Zeit zu Zeit verlor auch Monte Carlo. Immerhin kann Monte Carlo den Launen der Zufallszahlen nicht entkommen. Übrigens, wenn Sie in diesem Zustand gegen Q-Learning kämpfen, wird es sehr weh tun.
DQN (Deep Q Network)
Nun, diesmal ist das Hauptthema. Das ist DQN. Der Engpass beim Q-Learning besteht darin, dass die Q (s, a) -Tabelle riesig wird. Es wäre schön, wenn es in drei Reihen angeordnet wäre, aber in Go hätten sowohl S als auch a ein riesiges Gedächtnis. In Q-Network wird Q (s) verwendet, um die erwartete Belohnung für jedes a auszugeben und argmax zu nehmen. Mit Deep Q Network, "Sie werden eine Funktion finden, die selbst gewinnt !?", Ist es nicht in Ordnung, etwa 1000 Mal zu spielen? Ich war verrückt danach.
・ ・ ・ ・ Aber ich blieb stecken.
Es wird überhaupt nicht stärker. Darüber hinaus gibt es zu viele Hyperparameter. Wie viele versteckte Ebenen sollte ich haben? Ist der Fehler bei KMU in Ordnung? Ist Optimizer Adam oder SGD? Ehrlich gesagt wollte ich Grid Search. Da es jedoch überhaupt keinen Lehrer gibt, ist es nicht möglich, den Verlust zu messen. Die Genauigkeit kann nur durch den Kampf gegen den Gegner festgestellt werden.
Selbst wenn ich lernte, wurde der variable Link abgeschnitten und ich lernte überhaupt nicht. Ich mache das wirklich gerne. Außerdem ist es langsam, weil ich verschiedene Dinge auf einem Computer ohne GPU gemacht habe. .. .. Ohne GPU dauert das Lernen ca. 5-10 Minuten.
import chainer
from chainer import Function, gradient_check, Variable, optimizers, serializers, utils
import chainer.functions as F
import chainer.links as L
import numpy as np
from chainer import computational_graph as c
# Network definition
class MLP(chainer.Chain):
def __init__(self, n_in, n_units, n_out):
super(MLP, self).__init__(
l1=L.Linear(n_in, n_units), # first layer
l2=L.Linear(n_units, n_units), # second layer
l3=L.Linear(n_units, n_units), # Third layer
l4=L.Linear(n_units, n_out), # output layer
)
def __call__(self, x, t=None, train=False):
h = F.leaky_relu(self.l1(x))
h = F.leaky_relu(self.l2(h))
h = F.leaky_relu(self.l3(h))
h = self.l4(h)
if train:
return F.mean_squared_error(h,t)
else:
return h
def get(self,x):
# input x as float, output float
return self.predict(Variable(np.array([x]).astype(np.float32).reshape(1,1))).data[0][0]
class DQNPlayer:
def __init__(self, turn,name="DQN",e=1,dispPred=False):
self.name=name
self.myturn=turn
self.model = MLP(9, 162,9)
self.optimizer = optimizers.SGD()
self.optimizer.setup(self.model)
self.e=e
self.gamma=0.95
self.dispPred=dispPred
self.last_move=None
self.last_board=None
self.last_pred=None
self.totalgamecount=0
self.rwin,self.rlose,self.rdraw,self.rmiss=1,-1,0,-1.5
def act(self,board):
self.last_board=board.clone()
x=np.array([board.board],dtype=np.float32).astype(np.float32)
pred=self.model(x)
if self.dispPred:print(pred.data)
self.last_pred=pred.data[0,:]
act=np.argmax(pred.data,axis=1)
if self.e > 0.2: #decrement epsilon over time
self.e -= 1/(20000)
if random.random() < self.e:
acts=board.get_possible_pos()
i=random.randrange(len(acts))
act=acts[i]
i=0
while board.board[act]!=EMPTY:
#print("Wrong Act "+str(board.board)+" with "+str(act))
self.learn(self.last_board,act, -1, self.last_board)
x=np.array([board.board],dtype=np.float32).astype(np.float32)
pred=self.model(x)
#print(pred.data)
act=np.argmax(pred.data,axis=1)
i+=1
if i>10:
print("Exceed Pos Find"+str(board.board)+" with "+str(act))
acts=self.last_board.get_possible_pos()
act=acts[random.randrange(len(acts))]
self.last_move=act
#self.last_pred=pred.data[0,:]
return act
def getGameResult(self,board):
r=0
if self.last_move is not None:
if board.winner is None:
self.learn(self.last_board,self.last_move, 0, board)
pass
else:
if board.board== self.last_board.board:
self.learn(self.last_board,self.last_move, self.rmiss, board)
elif board.winner == self.myturn:
self.learn(self.last_board,self.last_move, self.rwin, board)
elif board.winner !=DRAW:
self.learn(self.last_board,self.last_move, self.rlose, board)
else: #DRAW
self.learn(self.last_board,self.last_move, self.rdraw, board)
self.totalgamecount+=1
self.last_move=None
self.last_board=None
self.last_pred=None
def learn(self,s,a,r,fs):
if fs.winner is not None:
maxQnew=0
else:
x=np.array([fs.board],dtype=np.float32).astype(np.float32)
maxQnew=np.max(self.model(x).data[0])
update=r+self.gamma*maxQnew
#print(('Prev Board:{} ,ACT:{}, Next Board:{}, Get Reward {}, Update {}').format(s.board,a,fs.board,r,update))
#print(('PREV:{}').format(self.last_pred))
self.last_pred[a]=update
x=np.array([s.board],dtype=np.float32).astype(np.float32)
t=np.array([self.last_pred],dtype=np.float32).astype(np.float32)
self.model.zerograds()
loss=self.model(x,t,train=True)
loss.backward()
self.optimizer.update()
#print(('Updated:{}').format(self.model(x).data))
#print (str(s.board)+"with "+str(a)+" is updated from "+str(pQ)+" refs MAXQ="+str(maxQnew)+":"+str(r))
#print(self.q)
Die Quelle ist lang. .. .. Ich denke, es gibt Hinweise auf Versuch und Irrtum, aber ich habe es nicht gereinigt.
Damit lernen Sie zunächst, wie man schlägt und gewinnt.
pDQ=DQNPlayer(PLAYER_X)
p2=PlayerAlphaRandom(PLAYER_O)
game=TTT_GameOrganizer(pDQ,p2,20000,False,False,1000)
game.progress()
DQN:206,AlphaRandom:727,DRAW:67
DQN:468,AlphaRandom:1406,DRAW:126
DQN:861,AlphaRandom:1959,DRAW:180
DQN:1458,AlphaRandom:2315,DRAW:227
DQN:2185,AlphaRandom:2560,DRAW:255
DQN:3022,AlphaRandom:2704,DRAW:274
DQN:3832,AlphaRandom:2856,DRAW:312
DQN:4632,AlphaRandom:3023,DRAW:345
DQN:5481,AlphaRandom:3153,DRAW:366
DQN:6326,AlphaRandom:3280,DRAW:394
DQN:7181,AlphaRandom:3400,DRAW:419
DQN:8032,AlphaRandom:3522,DRAW:446
DQN:8902,AlphaRandom:3618,DRAW:480
DQN:9791,AlphaRandom:3705,DRAW:504
DQN:10673,AlphaRandom:3793,DRAW:534
DQN:11545,AlphaRandom:3893,DRAW:562
DQN:12420,AlphaRandom:3986,DRAW:594
DQN:13300,AlphaRandom:4074,DRAW:626
DQN:14183,AlphaRandom:4158,DRAW:659
DQN:15058,AlphaRandom:4246,DRAW:696
Es ist viel stärker geworden. Wie erwartet scheint es, dass Sie den verbesserten Zufall schlagen können.
pDQ.e=1
game=TTT_GameOrganizer(pDQ,pQ,30000,False,False,1000)
game.progress()
DQN:4,QL1:436,DRAW:560
DQN:6,QL1:790,DRAW:1204
DQN:6,QL1:1135,DRAW:1859
DQN:6,QL1:1472,DRAW:2522
DQN:6,QL1:1801,DRAW:3193
DQN:6,QL1:2123,DRAW:3871
DQN:6,QL1:2439,DRAW:4555
DQN:6,QL1:2777,DRAW:5217
DQN:7,QL1:3128,DRAW:5865
DQN:9,QL1:3648,DRAW:6343
DQN:13,QL1:4132,DRAW:6855
DQN:13,QL1:4606,DRAW:7381
DQN:13,QL1:5087,DRAW:7900
DQN:14,QL1:5536,DRAW:8450
DQN:14,QL1:6011,DRAW:8975
DQN:14,QL1:6496,DRAW:9490
DQN:14,QL1:7394,DRAW:9592
DQN:14,QL1:7925,DRAW:10061
DQN:16,QL1:8357,DRAW:10627
DQN:16,QL1:8777,DRAW:11207
Ich frage mich, ob es endlich stärker geworden ist. .. .. Es ist eine empfindliche Stärke. .. Ich habe immer noch viele Verluste in diesem Protokoll, aber nach 100.000 Schlachten hätte ich mich fast für ein Unentschieden entschieden.
pDQ.e=0
p2=PlayerHuman(PLAYER_O)
game=TTT_GameOrganizer(pDQ,p2,2)
game.progress()
Turn is Human
Where would you like to place -1 (1-9)? 1
//anaconda/lib/python3.5/site-packages/ipykernel/__main__.py:69: VisibleDeprecationWarning: converting an array with ndim > 0 to an index will result in an error in the future
O | |
-----------
| |
-----------
| |
Turn is DQN
O | |
-----------
| X |
-----------
| |
Turn is Human
Where would you like to place -1 (1-9)? 2
O | O |
-----------
| X |
-----------
| |
Turn is DQN
O | O | X
-----------
| X |
-----------
| |
Turn is Human
Where would you like to place -1 (1-9)? 7
O | O | X
-----------
| X |
-----------
O | |
Turn is DQN
O | O | X
-----------
X | X |
-----------
O | |
Turn is Human
Where would you like to place -1 (1-9)? 6
O | O | X
-----------
X | X | O
-----------
O | |
Turn is DQN
O | O | X
-----------
X | X | O
-----------
O | | X
Turn is Human
Where would you like to place -1 (1-9)? 7
O | O | X
-----------
X | X | O
-----------
O | | X
I lost...
Invalid Move!
Turn is Human
Where would you like to place -1 (1-9)? 2
| O |
-----------
| |
-----------
| |
Turn is DQN
| O |
-----------
| X |
-----------
| |
Turn is Human
Where would you like to place -1 (1-9)? 1
O | O |
-----------
| X |
-----------
| |
Turn is DQN
O | O | X
-----------
| X |
-----------
| |
Turn is Human
Where would you like to place -1 (1-9)? 7
O | O | X
-----------
| X |
-----------
O | |
Turn is DQN
O | O | X
-----------
X | X |
-----------
O | |
Turn is Human
Where would you like to place -1 (1-9)? 6
O | O | X
-----------
X | X | O
-----------
O | |
Turn is DQN
O | O | X
-----------
X | X | O
-----------
O | | X
Turn is Human
Where would you like to place -1 (1-9)? 8
O | O | X
-----------
X | X | O
-----------
O | O | X
Draw Game
DQN:1,Human:0,DRAW:1
Nun, es war so ein Schachzug.
Q-Learning war ziemlich einfach zu implementieren, aber mit Deep Q Network war es sehr oft ohne Versuch und Irrtum unentschlossen. Selbst wenn ich es zum ersten Mal mit Relu implementiert habe, wurde es überhaupt nicht stärker und es wurde mit Leaky Relu besser. Vielleicht konnte ich es mit Relu nicht gut ausdrücken, weil -1 auf dem Brett ist. Aus irgendeinem Grund arbeitete Adam auch nicht und SGD arbeitete. Es ist komisch. Ich dachte, Adam sei der Stärkste. Wenn Sie nicht von Anfang an gegen Alpha Random spielen und gegen Q-Learning (starker Typ) kämpfen, verlieren Sie schnell die Motivation und verlieren. Zunächst scheint es, dass Sie die Schwachen bekämpfen müssen, um sie zu motivieren.
Das Schwierigste war auch
――Wie man DQN beibringt, was man nicht tun sollte
Das ist der Punkt.
Dieses Mal, wenn ich einen Ort traf, an dem es bereits ein Stück gab, gab ich gewaltsam eine negative Belohnung und lernte 10 Mal, was gut funktionierte. Soll ich einen Ort betreten, an dem ich ihn treffen kann?
Wenn Sie Fragen haben oder sich verbessern möchten, lassen Sie es mich bitte wissen. Ratschläge und Vorschläge, immer mehr willkommen.
Trotzdem dauerte es länger als erwartet, obwohl ich dachte, dass die dritte Zeile ungefähr 2-3 Stunden dauern würde. Ich bin mir sehr bewusst, dass es eine lächerliche Lücke zwischen dem gibt, was ich weiß, was ich implementieren kann (kann Code schreiben) und was ich tun kann (es funktioniert richtig). Wir empfehlen Ihnen, es selbst zu implementieren, ohne diese Quelle zu sehr zu betrachten.
Nun, ich frage mich, ob ich eine Othello-Version machen werde, wenn ich Zeit habe. .. .. Ich mache mir Sorgen um die nächste Herausforderung, ob ich die 3NN-Konfiguration von AlphaGo richtig ausprobieren soll.
Recommended Posts