-
Notifications
You must be signed in to change notification settings - Fork 0
/
agent.py
145 lines (116 loc) · 4.87 KB
/
agent.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import torch
import random
import numpy as np
from collections import deque
from jogo import JogoCobraIA, Direction, Point
from modelo_busca import QNet, QTrainer
from Grafico import plot
Memoria_M = 100_000
Carga = 1000 #Batch
LR = 0.001
class Agent:
def __init__(self):
self.n_jogos = 0
self.epsilon = 0 # aleatoriedade
self.gamma = 0.9 # taxa de desconto
self.memory = deque(maxlen=Memoria_M) # popleft() remove um elemento do lado esquerdo do deque e retorna o valor.
self.model = QNet(11, 256, 3)
self.trainer = QTrainer(self.model, lr=LR, gamma=self.gamma)
def get_estado(self, jogo):
cabeca = jogo.cobra[0]
point_l = Point(cabeca.x - 20, cabeca.y)
point_r = Point(cabeca.x + 20, cabeca.y)
point_u = Point(cabeca.x, cabeca.y - 20)
point_d = Point(cabeca.x, cabeca.y + 20)
dir_l = jogo.direction == Direction.LEFT
dir_r = jogo.direction == Direction.RIGHT
dir_u = jogo.direction == Direction.UP
dir_d = jogo.direction == Direction.DOWN
estado = [
# Perigo direto
(dir_r and jogo._ocorre_colisao(point_r)) or
(dir_l and jogo._ocorre_colisao(point_l)) or
(dir_u and jogo._ocorre_colisao(point_u)) or
(dir_d and jogo._ocorre_colisao(point_d)),
# Perigo à direita
(dir_u and jogo._ocorre_colisao(point_r)) or
(dir_d and jogo._ocorre_colisao(point_l)) or
(dir_l and jogo._ocorre_colisao(point_u)) or
(dir_r and jogo._ocorre_colisao(point_d)),
# Perigo à esquerda
(dir_d and jogo._ocorre_colisao(point_r)) or
(dir_u and jogo._ocorre_colisao(point_l)) or
(dir_r and jogo._ocorre_colisao(point_u)) or
(dir_l and jogo._ocorre_colisao(point_d)),
# Mover direção
dir_l,
dir_r,
dir_u,
dir_d,
#local da comida
jogo.comida.x < jogo.cabeca.x, #comida à esquerda
jogo.comida.x > jogo.cabeca.x, #comida à direita
jogo.comida.y < jogo.cabeca.y, #comida para cima
jogo.comida.y > jogo.cabeca.y #comida para baixo
]
return np.array(estado, dtype=int)
def remember(self, estado, acao, recompensa, prox_estado, pronto):
self.memory.append((estado, acao, recompensa, prox_estado, pronto)) # popleft se Memoria_M for alcançado
def train_long_memory(self):
if len(self.memory) > Carga:
mini_sample = random.sample(self.memory, Carga) # lista de tuplas
else:
mini_sample = self.memory
estados, acaos, recompensas, prox_estados, prontos = zip(*mini_sample)
self.trainer.train_step(estados, acaos, recompensas, prox_estados, prontos)
#for estado, acao, recompensa, nexrt_estado, pronto in mini_sample:
#self.trainer.train_step(estado, acao, recompensa, prox_estado, pronto)
def train_short_memory(self, estado, acao, recompensa, prox_estado, pronto):
self.trainer.train_step(estado, acao, recompensa, prox_estado, pronto)
def get_acao(self, estado):
# movimentos aleatórios: exploração
self.epsilon = 80 - self.n_jogos
final_move = [0,0,0]
if random.randint(0, 200) < self.epsilon:
move = random.randint(0, 2)
final_move[move] = 1
else:
estado0 = torch.tensor(estado, dtype=torch.float)
prediction = self.model(estado0)
move = torch.argmax(prediction).item()
final_move[move] = 1
return final_move
def train():
plot_pontos = []
plot_medias = []
total_ponto = 0
recorde = 0
agent = Agent()
jogo = JogoCobraIA()
while True:
# voltar no estado antigo
estado_old = agent.get_estado(jogo)
# mexa-se
final_move = agent.get_acao(estado_old)
# executa o movimento e obtém um novo estado
recompensa, pronto, pontuacao = jogo.play_step(final_move)
estado_new = agent.get_estado(jogo)
# treina memória curta
agent.train_short_memory(estado_old, final_move, recompensa, estado_new, pronto)
# lembrar
agent.remember(estado_old, final_move, recompensa, estado_new, pronto)
if pronto:
# treina memória longa, resultado do gráfico
jogo.reset()
agent.n_jogos += 1
agent.train_long_memory()
if pontuacao > recorde:
recorde = pontuacao
print('Jogo', agent.n_jogos, 'Ponto', pontuacao, 'Recorde:', recorde)
plot_pontos.append(pontuacao)
total_ponto += pontuacao
media = total_ponto / agent.n_jogos
plot_medias.append(media)
plot(plot_pontos, plot_medias)
if __name__ == '__main__':
train()