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

Камень ножницы Бумага

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

Рассказывая историю генерации данных

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

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

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

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

Давай займемся байесовским, детка

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

Подлинно байесовский метод - это следующий шаг, который требует от нас указать, какие предварительные знания мы можем захотеть включить в нашу модель в отношении вероятности камня, ножницы и бумаги. Мы делаем это, задавая распределение вероятностей, которое дает комбинации вероятностей для камня, бумаги и ножниц. Для этого подойдет так называемое распределение Дирихле. Если вы никогда не слышали о распределении Дирихле, не волнуйтесь. Для наших целей нам нужно только знать, что мы собираемся использовать версию с тремя параметрами, и каждый из трех параметров будет соответствовать одному из результатов камень / ножницы / бумага. Если один из параметров (скажем, для бумаги) больше другого (например, для камня), то бумага будет более вероятной, чем камень при распределении. Если все три параметра равны 1, распределение Дирихле становится равномерным. Это тот случай, который мы собираемся использовать для приора. Это означает, что мы не знаем, какой результат может быть более вероятным, чем другой, и поэтому мы используем так называемое неинформативное априорное значение, которое не способствует никакому исходу.

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

Кодирование модели

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

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

Теперь наша общая цель на этом этапе - написать функцию, которая возвращает совместную логарифмическую вероятность точки данных (т. Е. Три отсчета, один для камня, один для бумаги, один для ножниц) и соответствующие значения параметров (здесь достаточно имеют вероятности для камня и бумаги, тогда вероятность ножниц может быть вычислена). Теперь остальное легко: мы используем распределение Дирихле для вычисления логарифмической вероятности значений наших параметров вероятности, полиномиальное распределение для вычисления логарифмической вероятности значений подсчета, а затем мы складываем два, что дает нам совместную логарифмическую вероятность эти данные встречаются вместе с этими параметрами вероятности (p_rock и p_paper). Вот и все! Мы закодировали нашу байесовскую модель.

Оценка значений параметров

Я просто заявил, что у нас есть модель. Но как вы оцениваете параметры модели (в частности, p_rock и p_paper), когда все, что у вас есть, - это некоторые данные и функция для вероятности совместного журнала? К счастью, именно для этой работы в TensorFlow Probability встроено тяжелое оборудование. Он называется цепью Маркова Монте-Карло, и мы будем использовать последний и лучший вариант этого метода, который носит название Гамильтон Монте-Карло. Это позволяет нам делать выборку из апостериорного распределения нашей модели, то есть распределения, полученного из априорного распределения путем включения информации, содержащейся в конкретных данных. И если наша выборка достаточно велика, она в основном позволяет нам знать все об этом распределении: форму, среднее, медианное, моды и т. Д. Гамильтон Монте-Карло - одна из тех идей, которые звучат безумно, пока вы не заметите, насколько хорошо они Работа. Интуитивно понятная идея состоит в том, что вы представляете вероятность, с которой хотите произвести выборку, как некоторый многомерный ландшафт, состоящий из гор (высокая вероятность) и долин (низкая вероятность). Теперь вы позволяете мячу катиться по этой поверхности, и где бы он ни катился, он берет образцы распределения через равные промежутки времени. Но поскольку мяч будет набирать скорость при скатывании под гору, он будет намного быстрее в долинах (и, следовательно, брать там меньше проб), чем в горах. Удивительно, но это действительно может быть реализовано так, как это работает. Если вас интересуют более подробные сведения, прочтите Великолепное введение Джереми Куна в цепь Маркова в Монте-Карло в целом и в частности сообщение в блоге Ричарда Макэлрита о Гамильтоне Монте-Карло. В нашем случае этот фрагмент кода вызывает выборку Гамильтона Монте-Карло.

Сначала мы определим некоторые вымышленные наблюдаемые данные. В нашем случае мы предполагаем, что видели камень пять раз, но ножницы и бумага еще не выбраны. Затем мы делаем некоторую техническую подготовку цепи Маркова и, наконец, образец из цепи. Когда мы строим распределение выборок для p_rock (рисунок 1 слева), мы видим, что медиана составляет 0,8, что вполне разумно, учитывая тот факт, что данные, которые мы добавили, представляют собой 5 для камня и нули. для бумаги и ножниц. График также показывает, что все еще существует значительная неопределенность в отношении точного значения p_rock. Графики для p_paper и p_scissors (рисунок 1, в центре и справа) показывают, что, как и ожидалось, эти значения довольно близки к нулю. Теперь, когда мы оценили значения, мы можем напрямую использовать их для обучения с подкреплением. Но давайте сначала проверим, что наша симуляция прошла правильно.

Рисунок 1

TensorFlow 2 с вероятностью TensorFlow

Если вы сами пробовали моделировать цепь Маркова, то заметили, что выполнение соответствующей ячейки в записной книжке занимает около 17 минут. Причина этого в том, что он выполняется в нетерпеливом режиме. Tensorflow 2 имеет механизмы выполнения, которые работают аналогично графическому режиму в TensorFlow 1. Однако я не мог понять, как их можно объединить с TensorFlow Probability, чтобы получить ускорение в симуляции цепи Маркова. Насколько я понимаю, то, как мы уже используем tf.function в нашем коде (один раз в качестве декоратора и один раз в качестве функции), должно работать. Но в настоящее время это не улучшает производительность. Тот же код (с небольшими изменениями для графического режима) выполняется примерно в 10 раз быстрее в TensorFlow 1. Я ожидаю, что эта проблема скоро будет решена. Может быть, у кого-то, читающего это, есть идея, может быть, это еще вопрос ожидания следующей версии TensorFlow Probability. А до тех пор я скорее смирюсь с плохой производительностью, чем представлю ноутбук в Tensorflow 1, который скоро станет унаследованным.

Математически проверяем наши результаты

Теперь мы впервые использовали этот большой черный ящик под названием Гамильтон Монте-Карло, и было бы неплохо иметь возможность проверить, дает ли он правильные результаты. К счастью, мы находимся в особом положении: обычно для оценки параметров в байесовских моделях требуются численные методы, такие как Гамильтон Монте-Карло. Но поскольку мы сохранили все очень, очень просто, мы находимся в одной из очень, очень немногих ситуаций, в которых есть простая математическая формула для параметров. Следовательно, у нас есть удобный способ перепроверить результаты Монте-Карло: если у нас есть априор Дирихле с параметрами (1, 1, 1) и данными (r, p, s) (где r / p / s - число наблюдений камень / бумага / ножницы), соответствующее апостериорное распределение (распределение, которое мы выбрали с помощью Гамильтон Монте-Карло) является распределением Дирихле (1 + r, 1 + p, 1 + s). Когда вы сравните соответствующие графики апостериорного анализа (рис. 2) с теми, которые мы уже создали, вы заметите, что они очень похожи.

фигура 2

Обучение с подкреплением: это все развлечения и игры

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

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

Основная идея состоит в том, что мы будем использовать нашу модель для определения вероятностей, с которыми наш оппонент-человек выбирает каждый из ходов, и обновлять данные и вероятности после каждого раунда. Затем из этого распределения мы выводим вероятный ход нашего оппонента. Тогда вычислить наш ход легко: если наш противник выбирает камень, мы выбираем бумагу, если он выбирает бумагу, мы выбираем ножницы и т. Д. Следовательно, мы строим рандомизированную стратегию, которая отражает фактическую частоту, с которой наш противник выбирает каждый из ходов. Стратегия использует не только точечную оценку, но и полное распределение вероятностей каждого хода. Вы можете видеть, как эти раздачи меняются во время игры. Они показаны на небольшом графике, который обновляется после каждого хода. Интересно посмотреть, как они меняются, но знание этих распределений дает противнику-человеку несправедливое преимущество. Поэтому вы можете отключить их, установив «show_plot = False» в начале ячейки.

Куда мы отправимся отсюда?

Если вы добрались до этого последнего раздела, у вас может возникнуть (в лучшем случае) ощущение, что весь этот байесовский и марковский цепной метод Монте-Карло интригует и полезен. У вас также может возникнуть ощущение, что я пропустил много важных деталей (что верно). Есть несколько исключительно хорошо написанных книг, которые могут восполнить пробелы, и я рекомендую вам попробовать одну из них. Для тех, кто хочет взглянуть на вещи с точки зрения программирования, книга Кэма Дэвидсона-Пилона Байесовские методы для хакеров станет отличным началом. Он доступен бесплатно на Github, и все примеры недавно были перенесены на TensorFlow Вероятность. Если вы хотите взглянуть на статистику чуть больше, то Статистическое переосмысление Ричарда Макэлрита просто потрясающе. Примеры недоступны (пока?) В TensorFlow Probability. Все равно книгу прочти. Ричард Макэлрит прекрасно демонстрирует простоту концепций, которые кажутся эзотерическими, когда вы читаете о них в другом месте. Я, вероятно, также должен порекомендовать некоторую литературу по обучению с подкреплением, но я еще не встречал книги, которая мне нравилась бы так сильно, как те, которые я только что упомянул. Мне любопытно услышать о ваших любимых занятиях по обучению с подкреплением и о ваших приключениях, когда вы попробуете все это. Пожалуйста, не стесняйтесь обращаться ко мне для дальнейших обсуждений!

Первоначально опубликовано на https://www.btelligent.com.