Skip to content

Commit

Permalink
more info
Browse files Browse the repository at this point in the history
  • Loading branch information
GreenWizard2015 committed Jan 1, 2021
1 parent ff1bea0 commit 8209e77
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 14 deletions.
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Надя, [01.01.21 20:46]
# Deep Maze

[English](README_en.md)

[Video v.0](https://www.youtube.com/watch?v=rSkxOtRhY24)

[Video v.1 (current version)](https://youtu.be/-w3PGBhAnzM)

Этот проект является симуляцией изучения простого grid world-a ботом с ограниченным полем зрения. Очки начисляются исключительно за открытие новых участков мира, что требует, как минимум, планирования и навигации.

Типовые настройки мира:
Expand All @@ -12,14 +17,18 @@
Видимая область - 17x17
```

В данный момент, используется простой Q-learning, без какой-либо памяти, поэтому в состояние мира был добавлен срез с данными о прошлых передвижениях агента. Таким образом, агент получает данные о проходимости окружающих его клеток и о передвижениях (проходились ли вообще и если да - то как давно, чтобы не использовать LSTM).
В данный момент, используется простой Q-learning, без какой-либо памяти, поэтому в состояние мира был добавлен срез с данными о прошлых передвижениях агента. Таким образом, агент получает данные о проходимости окружающих его клеток и о передвижениях (проходил ли по ячейке и как давно). Текущая версия окружения является чересчур упрощённой и может быть легко решена алгоритмически, но полученный опыт, приёмы и наблюдения могут быть применены к более реальным задачам. Например, карта может быть расширена до тысяч ячеек, с искажениями и другими осложняющими факторами.

Агенты очень часто застревали в сложных участках, поэтому было добавлено детектирование данного поведения, остановка агента и запуск того же агента в режиме исследования. Полученные таким способом данные помещаются в отдельную память, чтобы потом обучить агента как действовать в подобных ситуациях. Эмпирически эффект заметен, но нельзя однозначно утверждать пользу подобного подхода.

Изначально использовалась CNN (что логичнее для карт), но простая Dense-сетка давала сравнимые результат. Возможно, конечно, что остальные доработки могли привести к более заметному улучшению предсказаний CNN. Кроме того, были испробованы различные варианты наград, начальных условий, предобработки и др.

Длительная тренировка одного агента не давала ощутимого прогресса, поэтому, в итоге, были натренированы 4 версии той же сети и затем их решения объединялись вместе (см. [DQNEnsembleAgent.py](Agent/DQNEnsembleAgent.py)). Ансамбль из агентов позволяет получать более стабильные результаты в сложных ситуациях. Например, если агент попадает в сложный участок пространства, то существенно выше шанс что он сможет попытаться найти выход, чем когда агент основывается на предсказании лишь одной сети.

Общий принцип работы ансамбля:

![](img/ensemble.png)

Ниже показано сравнение верхней границы (кол-во открытой области в 10 симуляциях из 100, по 20 прогонов):

![](img/20201231-high.jpg)
Expand All @@ -32,6 +41,8 @@

Опять же, прямо ощутимого улучшения нет, но ансамбль немного стабильнее открывает 20-25% карты.

Следующим шагом будет дистилляция ансамбля в единую сеть, а так же использование полноценной сети для комбинации предсказаний подсетей. Есть большая вероятность того, что это позволит уловить более глубокие корреляции т. к. обучаемая сеть будет иметь представление о соотношение Q-values.
Следующим шагом будет дистилляция ансамбля в единую сеть, а так же использование полноценной сети для комбинации предсказаний подсетей. Есть большая вероятность того, что это позволит уловить более глубокие корреляции т. к. обучаемая сеть будет уже иметь представление о соотношение Q-values (сами значения индивидуальны для каждой сети).

# Области применения

Продолжение, правки, фиксы и видео следуют, а пока Happy New Year :)
Подобного рода задачи встречаются повсеместно в робототехнике, например.
7 changes: 7 additions & 0 deletions README_en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Deep Maze

[Video v.0](https://www.youtube.com/watch?v=rSkxOtRhY24)

[Video v.1 (current version)](https://youtu.be/-w3PGBhAnzM)

Coming soon.
Binary file added img/ensemble.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 57 additions & 10 deletions view_maze.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,23 @@ class Colors:
RED = (255, 0, 0)
PURPLE = (255, 0, 255)

RLAgent = namedtuple('RLAgent', 'name agent environment')
class DeathDetector:
def __init__(self, env, maxStepsUnchanged=100):
self._env = env
self._maxStepsUnchanged = maxStepsUnchanged

self._lastScore = env.score
self._lastValuableStep = env.steps
return

def deathRatio(self):
if self._lastScore < self._env.score:
self._lastScore = self._env.score
self._lastValuableStep = self._env.steps

return min((1, (self._env.steps - self._lastValuableStep) / self._maxStepsUnchanged))

RLAgent = namedtuple('RLAgent', 'name agent environment detector')

class App:
MODES = ['manual', 'random', 'agent']
Expand Down Expand Up @@ -74,10 +90,9 @@ def on_init(self):
def _assignMaze2Agents(self):
agents = []
for agent in self._agents:
agents.append(RLAgent(
agent.name, agent.agent,
self._initMaze.copy()
))
env = self._initMaze.copy()
detector = DeathDetector(env)
agents.append(RLAgent(agent.name, agent.agent, env, detector))

self._agents = agents
return
Expand All @@ -94,15 +109,16 @@ def _createNewAgent(self):
name = os.path.basename(filename)

self._agents.append(RLAgent(
name[:-3], agent, self._initMaze.copy()
name[:-3], agent, None, None
))

self._agents.insert(0, RLAgent(
'ensemble',
DQNEnsembleAgent(models),
self._initMaze.copy()
None, None
))

self._assignMaze2Agents()
self._activeAgent = 0
self._paused = True
return
Expand Down Expand Up @@ -180,7 +196,36 @@ def on_loop(self):
maze.apply(act)
pass

def _renderMazeMinimap(self, env):
anchor = np.array((450, 650))
maze, moves = env.minimap()

COLOR_A = pygame.Color(*Colors.GREEN)
COLOR_B = pygame.Color(*Colors.WHITE)

h, w = maze.shape
dx, dy = delta = 2 * np.array([64, 64]) / np.array([w, h])
for ix in range(w):
for iy in range(h):
isWall = 0 < maze[ix, iy]
isUnknownArea = maze[ix, iy] < 0

clr = Colors.WHITE
if 0 < moves[ix, iy]:
clr = COLOR_B.lerp(COLOR_A, max((0.25, moves[ix, iy])) )
if isWall: clr = Colors.PURPLE
if isUnknownArea: clr = Colors.BLACK

y, x = (delta * np.array([ix, iy])) + anchor
pygame.draw.rect(self._display_surf, clr, [x, y, dx - 1, dy - 1], 0)

self._drawText('Observed state:', (anchor[1], anchor[0] - 25), Colors.BLUE)
return

def _renderMaze(self, env):
COLOR_A = pygame.Color(*Colors.GREEN)
COLOR_B = pygame.Color(*Colors.WHITE)

fog = env.fog
moves = env.moves
maze = env.maze
Expand All @@ -191,11 +236,11 @@ def _renderMaze(self, env):
for iy in range(h):
isDiscovered = 0 < fog[ix, iy]
isWall = 0 < maze[ix, iy]
isWasHere = 0 < moves[ix, iy]
y, x = delta * np.array([ix, iy])

clr = Colors.WHITE
if isWasHere: clr = Colors.GREEN
if 0 < moves[ix, iy]:
clr = COLOR_B.lerp(COLOR_A, max((0.25, moves[ix, iy])) )
if isWall: clr = Colors.PURPLE

if not isDiscovered:
Expand All @@ -204,6 +249,7 @@ def _renderMaze(self, env):
# current pos
x, y = delta * env.pos
pygame.draw.rect(self._display_surf, Colors.RED, [x, y, dx - 1, dy - 1], 0)
self._renderMazeMinimap(env)
return

def _renderAgentsMaze(self):
Expand Down Expand Up @@ -233,12 +279,13 @@ def _renderInfo(self):
if 'agent' == self._mode:
self._drawText('Speed: x%.0f' % (self._speed), line(1), Colors.BLUE)
for i, agent in enumerate(self._agents):
deathRatio = agent.detector.deathRatio()
self._drawText(
'%s%s | %.1f (%d)' % (
'>> ' if i == self._activeAgent else '',
agent.name, agent.environment.score * 100.0, agent.environment.steps
),
line(2 + i), Colors.BLUE
line(2 + i), Colors.BLUE if deathRatio < 1 else Colors.BLACK
)
return

Expand Down

0 comments on commit 8209e77

Please sign in to comment.