Обучение Flappy Bird: Учебное пособие по обучению с подкреплением

Опубликовано: 2022-03-11

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

В этом уроке по обучению с подкреплением я покажу, как мы можем использовать PyTorch, чтобы научить нейронную сеть обучения с подкреплением играть во Flappy Bird. Но сначала нам нужно охватить ряд строительных блоков.

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

Кроме того, традиционные алгоритмы обучения не могут извлекать признаки : специалисты по искусственному интеллекту должны найти хорошее представление данных, которое затем отправляется в алгоритм обучения. Примеры традиционных методов машинного обучения включают SVM, случайный лес, дерево решений и $k$-средних, тогда как центральным алгоритмом глубокого обучения является глубокая нейронная сеть .

Входными данными для глубокой нейронной сети могут быть необработанные изображения, и специалисту по искусственному интеллекту не нужно искать какое-либо представление данных — нейронная сеть находит наилучшее представление в процессе обучения.

Многие методы глубокого обучения известны уже очень давно, но последние достижения в области аппаратного обеспечения быстро стимулировали исследования и разработки в области глубокого обучения. Nvidia несет ответственность за расширение области, поскольку ее графические процессоры позволяют проводить быстрые эксперименты по глубокому обучению.

Обучаемые параметры и гиперпараметры

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

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

Алгоритмы обучения с учителем, без учителя и с подкреплением

Один из способов классификации алгоритмов обучения — провести границу между алгоритмами с учителем и без учителя. (Но это не обязательно так просто: обучение с подкреплением находится где-то посередине между этими двумя типами.)

Когда мы говорим об обучении с учителем, мы рассматриваем пары $(x_i, y_i)$. $ x_i $ — это вход алгоритма, а $ y_i $ — это результат. Наша задача — найти функцию, которая сделает правильное отображение из $x_i$ в $y_i$.

Чтобы настроить обучаемые параметры, чтобы они определяли функцию, которая отображает $x_i$ в $y_i$, необходимо определить функцию потерь и оптимизатор. Оптимизатор минимизирует функцию потерь. Одним из примеров функции потерь является среднеквадратическая ошибка (MSE):

\[MSE = \sum_{i=1}^{n} (y_i - \widehat{y_i} )^2\]

Здесь $ y_i $ — метка истинности, а $ \widehat{y_i} $ — прогнозируемая метка. Один оптимизатор, который очень популярен в глубоком обучении, — это стохастический градиентный спуск . Существует множество вариаций, которые пытаются улучшить метод стохастического градиентного спуска: Адам, Ададельта, Адаград и так далее.

Алгоритмы без присмотра пытаются найти структуру в данных без явного указания меток. $k$-means — это один из примеров неконтролируемых алгоритмов, который пытается найти оптимальные кластеры в данных. Ниже приведено изображение с 300 точками данных. Алгоритмы $k$-средних нашли структуру в данных и присвоили каждой точке данных метку кластера. Каждый кластер имеет свой цвет.

Разделенные цветом кластеры точек данных. Кластеры были найдены неконтролируемым алгоритмом

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

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

Активное, пассивное и обратное обучение с подкреплением

Существует несколько различных подходов к этой технике. Во-первых, есть активное обучение с подкреплением, которое мы здесь используем. Напротив, существует пассивное обучение с подкреплением, где вознаграждение — это просто еще один тип наблюдения, а вместо этого решения принимаются в соответствии с фиксированной политикой.

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

Обобщение, переоснащение и недообучение

Любой фиксированный экземпляр параметров и гиперпараметров называется моделью. Эксперименты по машинному обучению обычно состоят из двух частей: обучения и тестирования.

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

Если модель слишком проста по отношению к данным, она не сможет соответствовать обучающим данным и будет плохо работать как с набором данных для обучения, так и с набором тестовых данных. В этом случае мы говорим, что модель не соответствует требованиям .

Если модель машинного обучения хорошо работает с обучающим набором данных, но плохо с тестовым набором данных, мы говорим, что она переоснащается . Переобучение — это ситуация, когда модель слишком сложна по отношению к данным. Он может идеально соответствовать обучающим данным, но он настолько адаптирован к обучающему набору данных, что плохо работает с тестовыми данными, т. е. он просто не обобщает.

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

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

Масштабируемость

Данные имеют решающее значение для построения моделей машинного обучения. Обычно традиционные алгоритмы обучения не требуют слишком много данных. Но из-за их ограниченной емкости производительность также ограничена. Ниже приведен график, показывающий, насколько хорошо масштабируются методы глубокого обучения по сравнению с традиционными алгоритмами машинного обучения.

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

Нейронные сети

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

Граф нейронной сети, показывающий каждый узел входного слоя, сопоставленный с каждым узлом скрытого слоя 1, в свою очередь сопоставленный с каждым узлом скрытого слоя 2, а затем, наконец, сопоставленный с выходным слоем, который состоит из одного узла.

Если нейронная сеть имеет более одного скрытого слоя, мы называем ее глубокой нейронной сетью. Входной набор $X$ подается в нейронную сеть и получается выходной $y$. Обучение выполняется с использованием алгоритма обратного распространения, который сочетает в себе функцию потерь и оптимизатор.

Обратное распространение состоит из двух частей: прямого прохода и обратного прохода. При прямом проходе входные данные подаются на вход нейронной сети и получается выход. Рассчитывается потеря между наземной истиной и прогнозом, а затем при обратном проходе параметры нейронных сетей настраиваются с учетом потери.

Сверточная нейронная сеть

Одним из вариантов нейронной сети является сверточная нейронная сеть . Он в основном используется для задач компьютерного зрения.

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

Ниже показано, как работает одно сверточное ядро ​​в сверточном слое. Ядро применяется к изображению, и получается свернутая функция.

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

Слои ReLU используются для введения нелинейностей в нейронную сеть. Нелинейности важны, потому что с их помощью мы можем моделировать все виды функций, а не только линейные, что делает нейронную сеть универсальным аппроксиматором функций. Это позволяет определить функцию ReLU следующим образом:

\[ReLU = \max(0, x)\]

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

Ниже приведен график функции ReLU.

Функция ReLU, похожая на простую диагональ графика y = x, но со всеми отрицательными значениями x, сопоставленными с нулем.

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

Сверточная нейронная сеть состоит из нескольких слоев: сверточных слоев, слоев ReLU и полносвязных слоев. Полностью связанные слои соединяют каждый нейрон в одном слое с каждым нейроном в другом слое, как видно из двух скрытых слоев на изображении в начале этого раздела. Последний полносвязный слой сопоставляет выходные данные предыдущего слоя со значениями number_of_actions , в данном случае.

Приложения

Глубокое обучение является успешным и превосходит классические алгоритмы машинного обучения в нескольких областях машинного обучения, включая компьютерное зрение, распознавание речи и обучение с подкреплением. Эти области глубокого обучения применяются в различных областях реального мира: финансах, медицине, развлечениях и т. д.

Обучение с подкреплением

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

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

В 2013 году лондонский ИИ-стартап DeepMind совершил прорыв в обучении управлению агентами непосредственно с помощью многомерных сенсорных входов. Они опубликовали статью « Играем в Atari с помощью глубокого обучения с подкреплением» , в которой показали, как научили искусственную нейронную сеть играть в игры Atari, просто глядя на экран. Они были приобретены Google, а затем опубликовали в Nature новую статью с некоторыми улучшениями: Контроль на уровне человека посредством глубокого обучения с подкреплением .

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

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

Граф процесса принятия решений по Маркову: состояния (отмеченные буквой «S») выполняют действия (отмеченные буквой «а»), которые затем имеют различные вероятности того, в каком состоянии агент окажется следующим; некоторые пройденные пути также указывают на награду

Агент способен выполнять действия, преобразующие окружающую среду. Назовем награду $R_t$. Это скалярный сигнал обратной связи, показывающий, насколько хорошо агент справляется на шаге $t$.

Агент нейронной сети решает, какое действие предпринять на любом этапе, основываясь на наблюдениях и наградах.

Для хорошей долгосрочной работы необходимо учитывать не только немедленные, но и будущие вознаграждения. Общая награда за один эпизод с временного шага $t$ составляет $ R_t = r_t + r_{t+1} + r_{t+2} + \ldots + r_n $. Будущее неопределенно, и чем дальше мы заходим в будущее, тем больше прогнозы на будущее могут расходиться. Поэтому используется дисконтированная будущая награда: $ R_t = r_t +\gamma r_{t+1} + \gamma^2r_{t+2} + \ldots + \gamma^{nt}r_n = r_t + \gamma R_{t+1} $. Агент должен выбрать действие, которое максимизирует дисконтированную будущую награду.

Глубокое Q-обучение

Функция $Q(s,a)$ представляет максимальное обесцененное будущее вознаграждение, когда действие $a$ выполняется в состоянии $s$:

\[Q(s_t, a_t) = \max R_{t+1}\]

Оценка будущего вознаграждения дается уравнением Беллмана: $ Q(s, a) = r + \gamma \max_{a'}Q(s', a') $ . Другими словами, максимальное вознаграждение в будущем при заданном состоянии $s$ и действии $a$ равно сумме немедленного вознаграждения плюс максимальное вознаграждение в будущем для следующего состояния.

Аппроксимация значений Q с помощью нелинейных функций (нейронных сетей) не очень стабильна. Из-за этого для стабильности используется повтор опыта. Опыт во время эпизодов тренировки сохраняется в памяти воспроизведения. Вместо самого последнего перехода используются случайные мини-пакеты из памяти воспроизведения. Это нарушает сходство последующих обучающих выборок, которые в противном случае привели бы нейронную сеть к локальному минимуму.

Есть еще два важных аспекта, которые следует упомянуть о глубоком Q-обучении: исследование и эксплуатация. При эксплуатации принимается наилучшее решение с учетом текущей информации. Исследование собирает больше информации.

Когда алгоритм выполняет действие, предложенное нейронной сетью, он выполняет эксплуатацию: он использует знания, полученные нейронной сетью. Напротив, алгоритм может выполнять случайные действия, исследуя новые возможности и вводя потенциальные новые знания в нейронную сеть.

«Алгоритм глубокого Q-обучения с воспроизведением опыта» из статьи DeepMind «Игра в Atari с глубоким обучением с подкреплением» показан ниже.

Алгоритм Deep Q-learning with Experience Replay в псевдокоде

DeepMind называет сверточные сети, обученные с помощью их подхода, глубокими Q-сетями (DQN).

Пример глубокого Q-обучения с использованием Flappy Bird

Flappy Bird — популярная мобильная игра, изначально разработанная вьетнамским художником и программистом видеоигр Донг Нгуен. В нем игрок управляет птицей и пытается пролететь между зелеными трубами, не задев их.

Ниже приведен скриншот клона Flappy Bird, закодированного с помощью PyGame:

Скриншот из FlapPyBird, клона Flappy Bird, закодированного с помощью PyGame.

С тех пор клон был разветвлен и изменен: фон, звуки и различные стили птиц и труб были удалены, а код был скорректирован, чтобы его можно было легко использовать с простыми структурами обучения с подкреплением. Модифицированный игровой движок взят из этого проекта TensorFlow:

Скриншот DeepLearningFlappyBird, форка клона с упрощенной графикой

Но вместо использования TensorFlow я создал структуру глубокого обучения с подкреплением, используя PyTorch. PyTorch — это среда глубокого обучения для быстрых и гибких экспериментов. Он предоставляет тензоры и динамические нейронные сети на Python с сильным ускорением графического процессора.

Архитектура нейронной сети такая же, как у DeepMind, использованного в статье « Управление на уровне человека с помощью глубокого обучения с подкреплением» .

Слой Вход Размер фильтра Страйд Количество фильтров Активация Выход
конв1 84x84x4 8x8 4 32 РеЛУ 20x20x32
конв2 20x20x32 4x4 2 64 РеЛУ 9x9x64
конв3 9x9x64 3х3 1 64 РеЛУ 7x7x64
фк4 7x7x64 512 РеЛУ 512
fc5 512 2 Линейный 2

Есть три сверточных слоя и два полносвязных слоя. Каждый слой использует активацию ReLU, кроме последнего, который использует линейную активацию. Нейросеть выдает два значения, представляющие единственно возможные действия игрока: «Взлететь» и «Ничего не делать».

Входные данные состоят из четырех последовательных черно-белых изображений 84x84. Ниже приведен пример четырех изображений, которые передаются в нейронную сеть.

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

Четыре последовательных черно-белых кадра клона Flappy Bird, переданные непосредственно в нейронную сеть.

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

Это часть кода, который определяет нейронную сеть. Веса нейронных сетей инициализируются, чтобы следовать равномерному распределению $\mathcal{U}(-0,01, 0,01)$. Часть смещения параметров нейронных сетей устанавливается равной 0,01. Было опробовано несколько различных инициализаций (форма Ксавьера, норма Ксавьера, форма Кайминга, норма Кайминга, форма и норма), но приведенная выше инициализация заставила нейронную сеть сходиться и обучаться быстрее всего. Размер нейросети 6,8 МБ.

 class NeuralNetwork(nn.Module): def __init__(self): super(NeuralNetwork, self).__init__() self.number_of_actions = 2 self.gamma = 0.99 self.final_epsilon = 0.0001 self.initial_epsilon = 0.1 self.number_of_iterations = 2000000 self.replay_memory_size = 10000 self.minibatch_size = 32 self.conv1 = nn.Conv2d(4, 32, 8, 4) self.relu1 = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(32, 64, 4, 2) self.relu2 = nn.ReLU(inplace=True) self.conv3 = nn.Conv2d(64, 64, 3, 1) self.relu3 = nn.ReLU(inplace=True) self.fc4 = nn.Linear(3136, 512) self.relu4 = nn.ReLU(inplace=True) self.fc5 = nn.Linear(512, self.number_of_actions) def forward(self, x): out = self.conv1(x) out = self.relu1(out) out = self.conv2(out) out = self.relu2(out) out = self.conv3(out) out = self.relu3(out) out = out.view(out.size()[0], -1) out = self.fc4(out) out = self.relu4(out) out = self.fc5(out) return out

Вы заметите, что в конструкторе определены гиперпараметры. Оптимизация гиперпараметров не предназначена для целей этого сообщения в блоге. Вместо этого гиперпараметры в основном используются из статей DeepMind. Здесь масштаб некоторых гиперпараметров ниже, чем в статье DeepMind, потому что Flappy Bird менее сложна, чем игры Atari, которые они использовали для настройки.

Кроме того, эпсилон изменен, чтобы быть более разумным для этой игры. DeepMind использует единицу эпсилон, но здесь мы используем 0,1. Это связано с тем, что более высокие эпсилоны заставляют птицу много махать крыльями, что толкает птицу к верхней границе экрана, что всегда в конечном итоге приводит к тому, что птица врезается в трубу.

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

 optimizer = optim.Adam(model.parameters(), lr=1e-6) criterion = nn.MSELoss()

Игра должна быть запущена:

 game_state = GameState()

Память воспроизведения определяется как список Python:

 replay_memory = []

Теперь нам нужно инициализировать первое состояние. Действие является двумерным тензором:

  • [1, 0] означает «ничего не делать»
  • [0, 1] означает «взлететь вверх»

Метод frame_step дает нам следующий экран, вознаграждение и информацию о том, является ли следующее состояние терминальным. Награда составляет 0.1 за каждое движение птицы без смерти, когда она не проходит через трубу, 1 , если птица успешно проходит через трубу, и -1 , если птица разбивается.

Функция resize_and_bgr2gray пол, изменяет размер экрана до изображения 84x84 и меняет цветовое пространство с BGR на черно-белое. Функция image_to_tensor преобразует изображение в тензор PyTorch и помещает его в память GPU, если доступна CUDA. Наконец, последние четыре последовательных экрана объединяются вместе и готовы к отправке в нейронную сеть.

 action = torch.zeros([model.number_of_actions], dtype=torch.float32) action[0] = 1 image_data, reward, terminal = game_state.frame_step(action) image_data = resize_and_bgr2gray(image_data) image_data = image_to_tensor(image_data) state = torch.cat((image_data, image_data, image_data, image_data)).unsqueeze(0)

Начальный эпсилон устанавливается с помощью этой строки кода:

 epsilon = model.initial_epsilon

Далее следует основной бесконечный цикл. Комментарии написаны в коде, и вы можете сравнить код с алгоритмом Deep Q-learning with Experience Replay, написанным выше.

Алгоритм отбирает мини-пакеты из памяти воспроизведения и обновляет параметры нейронной сети. Действия выполняются с использованием эпсилон-жадного исследования . Эпсилон со временем отжигается. Минимизируемая функция потерь равна $ L = \frac{1}{2}\left[\max_{a'}Q(s', a') - Q(s, a)\right]^2 $ . $ Q(s, a) $ — это истинное значение, рассчитанное с использованием уравнения Беллмана, а $ \max_{a'}Q(s', a') $ получается из нейронной сети. Нейронная сеть выдает два значения Q для двух возможных действий, и алгоритм выполняет действие с наибольшим значением Q.

 while iteration < model.number_of_iterations: # get output from the neural network output = model(state)[0] # initialize action action = torch.zeros([model.number_of_actions], dtype=torch.float32) if torch.cuda.is_available(): # put on GPU if CUDA is available action = action.cuda() # epsilon greedy exploration random_action = random.random() <= epsilon if random_action: print("Performed random action!") action_index = [torch.randint(model.number_of_actions, torch.Size([]), dtype=torch.int) if random_action else torch.argmax(output)][0] if torch.cuda.is_available(): # put on GPU if CUDA is available action_index = action_index.cuda() action[action_index] = 1 # get next state and reward image_data_1, reward, terminal = game_state.frame_step(action) image_data_1 = resize_and_bgr2gray(image_data_1) image_data_1 = image_to_tensor(image_data_1) state_1 = torch.cat((state.squeeze(0)[1:, :, :], image_data_1)).unsqueeze(0) action = action.unsqueeze(0) reward = torch.from_numpy(np.array([reward], dtype=np.float32)).unsqueeze(0) # save transition to replay memory replay_memory.append((state, action, reward, state_1, terminal)) # if replay memory is full, remove the oldest transition if len(replay_memory) > model.replay_memory_size: replay_memory.pop(0) # epsilon annealing epsilon = epsilon_decrements[iteration] # sample random minibatch minibatch = random.sample(replay_memory, min(len(replay_memory), model.minibatch_size)) # unpack minibatch state_batch = torch.cat(tuple(d[0] for d in minibatch)) action_batch = torch.cat(tuple(d[1] for d in minibatch)) reward_batch = torch.cat(tuple(d[2] for d in minibatch)) state_1_batch = torch.cat(tuple(d[3] for d in minibatch)) if torch.cuda.is_available(): # put on GPU if CUDA is available state_batch = state_batch.cuda() action_batch = action_batch.cuda() reward_batch = reward_batch.cuda() state_1_batch = state_1_batch.cuda() # get output for the next state output_1_batch = model(state_1_batch) # set y_j to r_j for terminal state, otherwise to r_j + gamma*max(Q) y_batch = torch.cat(tuple(reward_batch[i] if minibatch[i][4] else reward_batch[i] + model.gamma * torch.max(output_1_batch[i]) for i in range(len(minibatch)))) # extract Q-value q_value = torch.sum(model(state_batch) * action_batch, dim=1) # PyTorch accumulates gradients by default, so they need to be reset in each pass optimizer.zero_grad() # returns a new Tensor, detached from the current graph, the result will never require gradient y_batch = y_batch.detach() # calculate loss loss = criterion(q_value, y_batch) # do backward pass loss.backward() optimizer.step() # set state to be state_1 state = state_1

Теперь, когда все детали на месте, вот общий обзор потока данных с использованием нашей нейронной сети:

Окончательный общий обзор потока данных с использованием нашей нейронной сети: состояние ввода состоит из четырех последовательных экранов. Отсюда нейронная сеть выдает два значения Q для двух возможных действий («ничего не делать» и «летать вверх»).

Вот одна короткая последовательность с обученной нейронной сетью.

Анимация клона Flappy Bird, воспроизводимого получившейся обученной нейронной сетью.

Нейронная сеть, показанная выше, была обучена с использованием высокопроизводительного графического процессора Nvidia GTX 1080 в течение нескольких часов; при использовании вместо этого решения на основе процессора эта конкретная задача заняла бы несколько дней. FPS игрового движка во время обучения был выставлен на очень большое число: 999…999 — другими словами, как можно больше кадров в секунду. На этапе тестирования FPS был установлен на 30.

Ниже приведена диаграмма, показывающая, как максимальное значение Q менялось во время итераций. Показана каждая 10 000-я итерация. Нисходящий всплеск означает, что для определенного кадра (одна итерация — это один кадр) нейронная сеть предсказывает, что птица получит очень низкую награду в будущем, т. е. она очень скоро рухнет.

Диаграмма, показывающая, как максимальное значение Q изменилось во время итераций. Начиная с нуля и с несколькими скачками вниз, он показывает общую тенденцию к максимуму значения Q около 12 или 13 после примерно миллиона итераций.

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

Глубокое обучение с подкреплением: 2D, 3D и даже реальная жизнь

В этом учебном пособии по обучению с подкреплением PyTorch я показал, как компьютер может научиться играть во Flappy Bird без каких-либо предварительных знаний об игре, используя только метод проб и ошибок, как это сделал бы человек, впервые столкнувшийся с игрой.

Интересно, что алгоритм можно реализовать в несколько строк кода с помощью фреймворка PyTorch. Статья, на которой основан метод в этом блоге, относительно старая, и доступно множество новых статей с различными модификациями, которые обеспечивают более быструю сходимость. С тех пор глубокое обучение с подкреплением используется для игр в 3D-игры и в реальных робототехнических системах.

Такие компании, как DeepMind, Maluuba и Vicarious, интенсивно работают над глубоким обучением с подкреплением. Такая технология использовалась в AlphaGo, которая обыграла Ли Седоля, одного из лучших игроков мира в го. В то время считалось, что потребуется не менее десяти лет, прежде чем машины смогут победить лучших игроков в го.

Поток интереса и инвестиций в глубокое обучение с подкреплением (и в искусственный интеллект в целом) может даже привести к потенциальному искусственному общему интеллекту (ИИА) — интеллекту человеческого уровня (или даже выше), который может быть выражен в форме алгоритма и моделируется на компьютерах. Но AGI должен стать предметом другой статьи.


Использованная литература:

  • Демистификация глубокого обучения с подкреплением
  • Глубокое обучение с подкреплением для Flappy Bird
  • «Сверточная нейронная сеть» в Википедии
  • «Обучение с подкреплением» в Википедии
  • «Марковский процесс принятия решений» в Википедии
  • Курс Университетского колледжа Лондона по RL
Связанный: Учебник по глубокому обучению: от персептронов к глубоким сетям