Рубрики
Без рубрики

Водить танк с питоном

Ранее я рассмотрел основные концепции в обучении подкреплению (RL) и вводил важные части … помеченные для начинающих, учебник, Python.

Веселье и игры с обучением подкрепления (4 серии части)

Ранее я рассмотрел основные концепции в обучении подкрепления (RL) и ввел важные части API Gym Openai. Вы можете просмотреть это введение здесь:

Роботы поезда для съемки лазеров в инопланетянах с финансируемым программным обеспечением Элон Маск и Microsoft

Чарльз Ландау ・ 25 июля ’19 ・ 6 минут прочитал

В этом выпуске мы тренируем командира танка. Я делюсь кучей кода для этого проекта здесь:

Чарльздландау/Rlnotebooks

Подкрепление учебных записей

Подкрепление учебных записей для публикации в Интернете.

Поскольку эти ноутбуки являются учебными и экспериментальными, я не рекомендую запускать их на местном уровне. Я проверяю и запускаю эти ноутбуки на Google Colab или Kaggle Прежде чем я запустил их – вы тоже можете сделать это!

Примечание: Установка Gym Openai

… несколько больно. Многие онлайн -записные услуги, такие как colab и Каггл Не позволяйте вам установить некоторые среды Openai, поэтому я собираюсь придерживаться Атари сейчас. Если вы заинтересованы в том, чтобы попытаться создать спортзал Openai с большей гибкостью, вы можете начать с Эта интересная рецензия Анкет

Чтобы написать агентов, которые фактически учитывают экран игры при принятии решений, нам нужно обновить наш run_job Утилита с прошлого времени:

    action = model.decision_function(obs=observation, env=env)

И наше случайное агентство необходимо будет измениться соответственно:

class RandomAgentContainer:
    """A model that takes random actions and doesn't learn"""

    def __init__(self):
        pass

    def decision_function(self, obs=None, env=None):
        if env:
            return env.action_space.sample()
        else:
            return 0

    def train_on_history(self, history):
        pass


model = RandomAgentContainer()

Теперь мы можем использовать наши случайные, чтобы изучить всю информацию, которую создает наша работа.

result = run_job("Robotank-v0", model,
        10000, episodes_per_train=0);

result.keys()


# Output
dict_keys(['history', 'env', 'parameters'])

Наша работа создала видео в игре, а также историю изображений, действий, прогнозов и наград. Это также сохранило объект окружающей среды от спортзала Openai.

Давайте начнем с попытки понять наши наблюдения в видео:

render_video(0, result['env']);

Если, как и я, вы никогда не играли в танк роботов на атари … вы можете Прочитайте руководство ! Вы можете узнать о дисплее Heads Up и многое другое.

Так или иначе, похоже, что на изображении есть куча шума. Посмотрим, сможем ли мы извлечь что -нибудь из этого …

import matplotlib
from matplotlib.image import imread
from matplotlib.pyplot import imshow
observation_sample = [im['observation'] for im in result.get('history')]

imshow(observation_sample[0])

Таким образом, используя клещи на оси и с небольшой пробной и ошибкой, мы можем найти ограничивающие ящики для радарной панели и перископа.

imshow(observation_sample[0][139:172, 60:100, :])

Итак, мы, безусловно, можем обрезать это изображение и меньше беспокоиться о шуме …

radar_bounding_box = ((139, 172), (60, 100), (None))

Читая руководство, мы знаем, что один из четырех индикаторов, занимающихся внедрением, этот радиолокационный дисплей – «R» для «радара». Другими словами, мы не можем полагаться на радар как единственный вход, потому что все эти показатели представляют подсистемы, которые могут быть отключены.

Давайте также возьмем ограничивающую коробку для Periscope:

imshow(observation_sample[0][80:124, 12:160, :])

peri_bounding_box=((80, 124), (12, 160), (None))

Давайте также проверим Информация Поле, потому что иногда у него есть данные наблюдения.

result.get('history')[0].get('info')

# Output
{'ale.lives': 4}

Я собираюсь намеренно игнорировать коробки V, C, R, T, и мы всегда сможем разобрать их позже, если мы думаем, что прирост производительности в ближайшее время. Вы видели в руководстве, как они работают, поэтому я не думаю, что это причина для беспокойства …

Давайте также попытаемся понять пространство действий.

env = result['env']

print(env.action_space)

# Output:
Discrete(18)

Хм … совсем не полезно. Но это то, что вы, естественно, подумали бы сделать … Оказывается, что извлечение значений действия имеет свое собственное пространство имен в тренажерный зал API

# https://ai.stackexchange.com/a/3557
env.unwrapped.get_action_meanings()
# Output
['NOOP',
 'FIRE',
 'UP',
 'RIGHT',
 'LEFT',
 'DOWN',
 'UPRIGHT',
 'UPLEFT',
 'DOWNRIGHT',
 'DOWNLEFT',
 'UPFIRE',
 'RIGHTFIRE',
 'LEFTFIRE',
 'DOWNFIRE',
 'UPRIGHTFIRE',
 'UPLEFTFIRE',
 'DOWNRIGHTFIRE',
 'DOWNLEFTFIRE']

Таким образом, «поход», по-видимому, означает «нетоопер», то есть «ничего не делай». Остальные, по -видимому, составляют все перестановки действий, доступных для клиента. Это то, что мы ожидаем, это пространство действий будет. Это также дискретный Действия, чтобы мы могли кодировать нашу модель, чтобы предпринять ровно одно действие за шаг.

Наконец, давайте визуализируем награды

set([r['reward'] for r in result['history']]) # Unique rewards across history
# Output
{0.0, 1.0}
import matplotlib.pyplot as plt
plt.plot([r['reward'] for r in result['history']])

Похоже, функция вознаграждения просто “заберите еще 0”. Мы можем подтвердить, визуализируя наблюдения во время вознаграждения.

# Observations when reward was given
reward_incidents = list(filter(lambda i: i['reward'], result['history']))

i = 0
imshow(reward_incidents[i]['observation'])
i = 1
imshow(reward_incidents[i]['observation'])
i = 2
imshow(reward_incidents[i]['observation'])

Это все изображения, которые, кажется, запечатлены сразу после того, как танк забивает удар.

Написание командира танка

Мозг

Агенту TankCommander должен научиться решать, какое действие предпринять. Итак, нам сначала нужно дать ему механизм для обучения. В этом случае мы собираемся использовать специальный вид графика. На этом графике есть три вида узлов:

  1. Входные узлы

    Которые берут наши входные данные и отправляют сигналы к узлам, к которым они связаны

  2. Обычные узлы

    Эти узлы могут иметь много соединений из других узлов (включая входные узлы.) Некоторые соединения сильны, а некоторые соединения слабы. Этот узел использует сигналы и силу сигнала от всех соединений, чтобы решить, какой сигнал отправлять вдоль всех своих исходящих соединений.

  3. Выходные узлы

    Эти узлы отличаются только от обычных узлов тем, что мы читаем их сигнал

Узлы организованы в «слои», которые могут разделить много соединений и иметь общую функцию для того, как они решают собирать и отправлять сигналы.

Теперь я много упростил, но график, о котором мы говорим, если правильно организовываться, является глубокой нейронной сетью. Чтобы создать тот, который мы можем использовать Tensorflow вот так:

import tensorflow as tf
from tensorflow.keras import datasets, layers, models, preprocessing, callbacks
import numpy as np
import random

inputs = layers.Input(shape=(44, 148, 3))
x = layers.Conv2D(16, (3, 3), activation='relu')(inputs)
x = layers.BatchNormalization(axis=-1)(x) # Channels @ -1
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Flatten()(x)
x = layers.Dense(64)(x)
x = layers.Activation('relu')(x)
x = layers.Dense(64)(x)
x = layers.Activation('sigmoid')(x)
x = layers.BatchNormalization(axis=-1)(x)
x = layers.Dropout(0.02)(x)
x = layers.Dense(18, activation='linear')(x)
model = models.Model(inputs, x)
model.compile(optimizer='sgd',
      loss='mae',
      metrics=['accuracy'])

Давайте разберем это:

inputs = layers.Input(shape=(44, 148, 3))

Вы помните, что это размеры для одного из наших изображений Periscope. Эти карты в наших входных узлах.

x = layers.Conv2D(16, (3, 3), activation='relu')(inputs)
x = layers.BatchNormalization(axis=-1)(x) # Channels @ -1
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Flatten()(x)
x = layers.Dense(64)(x)
x = layers.Activation('relu')(x)
x = layers.Dense(64)(x)
x = layers.Activation('sigmoid')(x)
x = layers.BatchNormalization(axis=-1)(x)
x = layers.Dropout(0.02)(x)
x = layers.Dense(18, activation='linear')(x)
model = models.Model(inputs, x)

Это устанавливает слои регулярных узлов в нашем графике и их взаимодействия. Я упрощаю.

model.compile(optimizer='sgd',
      loss='mae',
      metrics=['accuracy'])

Наконец мы компилировать модель, предоставляя ей некоторые специальные параметры. Чтобы научить наш график управлять резервуаром, нам нужно позвонить в подходит Метод, например model.fit (data, rafle_prediction) Анкет Каждый раз, когда это происходит, наша модель возвращается и обновляет силу (он же «вес») обычных соединений. Причудливое название для этого – «обратное распространение». В любом случае, параметры Model.compile Помогите определить, как выполняется обратная передача.

Опыт

Теперь, когда у нас есть мозг, мозг нуждается в опыте обучения. Как мы знаем из нашего руководства и нашего небольшого исследования данных, каждый эпизод отображает одну полную игру робота. Однако в каждой игре игрок получает несколько танков, и если танк уничтожен, игрок просто «возрождает» в новом танке. Таким образом, эпизод на самом деле не самая маленькая единица опыта, скорее, это «жизнь» одного танка.

Мы можем извлечь это из:

episodes = [list(filter(lambda h: h["episode"]==e , history)
                      ) for e in range(n_episodes)
]

game_lives = [
            list(
              filter(lambda h: h.get('info').get('ale.lives')==l, episode)
        ) for l in range(5)
]

Для каждой из этих жизней мы можем получить кумулятивную награду (сколько хитов забило до того, как жизнь закончится.)

        rewards = [obs.get('reward') for obs in game_life]
        cum_rewards = sum(rewards)

И используя это число, мы можем определить, насколько сильно мы хотим, чтобы наш мозг отреагировал на этот опыт

        # Positive experience
        if cum_rewards:
            nudge = cum_rewards * 0.03
        # Negative experience
        else:
           nudge = 0 - 0.03

Теперь, для данного шага, мы можем:

  1. Возьмите наш оригинал действие , прогноз и Periscope Изображение как данные
  2. щедро Наш прогноз Только в действие Индекс, так как мы можем учиться только на поступках, которые мы предприняли.
  3. Позвоните model.fit (image, prediction_with_nudge)

Чтобы визуализировать проблему с этим, представьте, что вам поручено ездить на велосипеде по горе с завязанными глазами. Когда вы чудесным образом ездить по горе, не убивая себя, вы можете достичь точки, когда вы, кажется, достигли дна. В любом направлении вы пытаетесь пойти, вы должны педали в гору. Вы снимаете с завязанными глазами, только чтобы понять, что вы едва прошли милю, и что вам еще предстоит уйти, прежде чем вы достигнете основания горы. Причудливый термин для этого – «местный минимум».

Чтобы решить эту проблему, мы можем просто заставить командира случайно предпринимать действия иногда:

for obs in game_life:

    action, prediction = obs.get('action')
    if self.epsilon and (random.uniform(0, 1.0) < self.epsilon):
      action = random.randrange(18)

    # Copy
    update = list(prediction)

    # Update only the target action
    update[0][action] = update[0][action] + displacement

С всего лишь 120 тысяч шагов, наш танк уже казался решающимся в стратегии, как показано в этом Длинная, длинная гифка.

Как вы можете видеть, поворот налево мощный в роботанках – целая эскадрилья убита!

… но тогда он умирает. Я думаю, что это довольно сильнее для тупичной модели, обучаемой только в просмотре Periscope. Время разрешено, я могу продолжать расти с этим – увеличивая значение Epsilon, возиться с параметрами графика и добавляя представления , все могут помочь подтолкнуть командира танка к более нюансированной стратегии.

В любом случае, вы немного узнали о реализации DL с RL в Python. Ты выучил:

  1. DL Основные понятия
  2. Исследовательский анализ данных для RL
  3. Выборочно применение вознаграждений к конкретным действиям и самым маленьким делительным единицам опыта
  4. Введение случайных действий, чтобы помочь изучить «пространство действий»

Спасибо за чтение! Обратитесь к любым вопросам.

Веселье и игры с обучением подкрепления (4 серии части)

Оригинал: “https://dev.to/charlesdlandau/drive-a-tank-with-python-3caf”