Вероятностное программирование становится одним из самых активных направлений развития машинного обучения. Какие основные языки нам следует знать?

Недавно я начал новый информационный бюллетень, посвященный образованию в области искусственного интеллекта. TheSequence - это информационный бюллетень, ориентированный на искусственный интеллект (то есть без рекламы, без новостей и т. Д.), На чтение которого уходит 5 минут. Цель состоит в том, чтобы держать вас в курсе проектов, исследовательских работ и концепций машинного обучения. Пожалуйста, попробуйте, подписавшись ниже:



Вероятностное мышление - невероятно ценный инструмент для принятия решений. От экономистов до игроков в покер, люди, которые могут мыслить категориями вероятностей, склонны принимать более правильные решения, когда сталкиваются с неопределенными ситуациями. Области вероятностей и теория игр создавались веками и десятилетиями, но не переживают возрождения с быстрой эволюцией искусственного интеллекта (ИИ). Можем ли мы включить вероятности как первоклассный гражданин программного кода? Добро пожаловать в мир вероятностных языков программирования (PPL)

Использование статистики для преодоления неопределенности - одна из основ большого сегмента рынка машинного обучения. Вероятностные рассуждения долгое время считались одной из основ алгоритмов вывода и представлены всеми основными фреймворками и платформами машинного обучения. В последнее время вероятностные рассуждения получили широкое распространение в таких технологических гигантах, как Uber, Facebook или Microsoft, что помогло продвинуть исследовательскую и технологическую повестку дня в этой сфере. В частности, PPL стали одной из наиболее активных областей развития машинного обучения, что привело к появлению некоторых новых интересных технологий.

Что такое вероятностные языки программирования?

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

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

Чтобы проиллюстрировать простоту PPL, давайте воспользуемся одной из самых известных проблем современной статистики: необъективным подбрасыванием монеты. Идея этой задачи - вычислить смещение монеты. Предположим, что xi = 1, если результат подбрасывания i-й монеты - решка, и xi = 0, если это решка. В нашем контексте предполагается, что отдельные подбрасывания монеты независимы и одинаково распределены (IID) и что каждый подбрасывание следует распределению Бернулли с параметром θ: p (xi = 1 | θ) = θ и p (xi = 0 | θ) = 1 - θ . Скрытая (т.е. ненаблюдаемая) переменная θ - это смещение монеты. Задача состоит в том, чтобы вывести θ по результатам ранее наблюдаемых подбрасываний монеты, то есть p (θ | x1, x2, ..., xN).

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

# Model 
theta = Uniform(0.0, 1.0) 
x = Bernoulli(probs=theta, sample_shape=10) 
Data 5 data = np.array([0, 1, 0, 0, 0, 0, 0, 0, 0, 1]) 
Inference 
qtheta = Empirical( 8 tf.Variable(tf.ones(1000) ∗ 0.5)) 
inference = ed.HMC({theta: qtheta}, 
data={x: data}) 
inference.run() 
Results 13 mean, stddev = ed.get_session().run( [qtheta.mean(),qtheta.stddev()]) 
print("Posterior mean:", mean) 
print("Posterior stddev:", stddev)

Святой Грааль: Deep PPL

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

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

3 глубоких PPL, о которых вам нужно знать

В последние годы область вероятностных языков программирования (PPL) бурно развивается благодаря исследованиям и инновациям. Большинство этих инноваций возникло в результате объединения PPL и методов глубокого обучения для создания нейронных сетей, которые могут эффективно справляться с неопределенностью. Технологические гиганты, такие как Google, Microsoft или Uber, несут ответственность за расширение границ Deep PPL в крупномасштабных сценариях. Эти усилия воплотились в совершенно новые стеки Deep PPL, которые становятся все более популярными в сообществе машинного обучения. Давайте рассмотрим некоторые из самых последних достижений в области Deep PPL.

Эдвард

Эдвард - это полный по Тьюрингу вероятностный язык программирования (PPL), написанный на Python. Изначально Эдвард был сторонником команды Google Brain, но теперь у него есть обширный список участников. Оригинальная исследовательская работа Эдварда была опубликована в марте 2017 года, и с тех пор стек получил широкое распространение в сообществе машинного обучения. Эдвард объединяет три области: байесовскую статистику и машинное обучение, глубокое обучение и вероятностное программирование. Библиотека легко интегрируется с фреймворками глубокого обучения, такими как Keras и TensorFlow.

1 # Model
2 theta = Uniform(0.0, 1.0)
3 x = Bernoulli(probs=theta, sample_shape=10)
4 # Data
5 data = np.array([0, 1, 0, 0, 0, 0, 0, 0, 0, 1])
6 # Inference
7 qtheta = Empirical(
8 tf.Variable(tf.ones(1000) ∗ 0.5))
9 inference = ed.HMC({theta: qtheta},
10 data={x: data})
11 inference.run()
12 # Results
13 mean, stddev = ed.get_session().run(
14 [qtheta.mean(),qtheta.stddev()])
15 print("Posterior mean:", mean)
16 print("Posterior stddev:", stddev)
1 # Inference Guide
2 qalpha = tf.Variable(1.0)
3 qbeta = tf.Variable(1.0)
4 qtheta = Beta(qalpha, qbeta)
5 # Inference
6 inference = ed.KLqp({theta: qtheta}, {x: data})
7 inference.run()

Поджигатель

Pyro - это глубокий вероятностный язык программирования (PPL), выпущенный Uber AI Labs. Pyro построен на основе PyTorch и основан на четырех фундаментальных принципах:

  • Универсальный: Pyro - это универсальный PPL - он может представлять любое вычислимое распределение вероятностей. Как? Начав с универсального языка с итерацией и рекурсией (произвольный код Python), а затем добавив случайную выборку, наблюдение и вывод.
  • Масштабируемость: Pyro масштабируется до больших наборов данных с небольшими накладными расходами на рукописный код. Как? Создавая современные методы оптимизации черного ящика, которые используют минипакеты данных для приблизительного вывода.
  • Минимальный: Pyro гибок и удобен в обслуживании. Как? Pyro реализован с помощью небольшого ядра мощных составных абстракций. По возможности, тяжелая работа делегируется PyTorch и другим библиотекам.
  • Гибкость: Pyro нацелен на автоматизацию, когда вы этого хотите, и контроль, когда вам это нужно. Как? Pyro использует высокоуровневые абстракции для выражения генеративных моделей и моделей вывода, позволяя экспертам легко настраивать вывод.

Как и другие PPL, Pyro объединяет модели глубокого обучения и статистический вывод, используя простой синтаксис, как показано в следующем коде:

1 # Model
2 def coin():
3 theta = pyro.sample("theta", Uniform(
4 Variable(torch.Tensor([0])),
5 Variable(torch.Tensor([1])))
6 pyro.sample("x", Bernoulli(
7 theta ∗ Variable(torch.ones(10)))
8 # Data
9 data = {"x": Variable(torch.Tensor(
10 [0, 1, 0, 0, 0, 0, 0, 0, 0, 1]))}
11 # Inference
12 cond = pyro.condition(coin, data=data)
13 sampler = pyro.infer.Importance(cond,
14 num_samples=1000)
15 post = pyro.infer.Marginal(sampler, sites=["theta"])
16 # Result
17 samples = [post()["theta"].data[0] for _ in range(1000)]
18 print("Posterior mean:", np.mean(samples))
19 print("Posterior stddev:", np.std(samples))# Inference Guide
2 def guide():
3 qalpha = pyro.param("qalpha", Variable(torch.Tensor([1.0]), requires_grad=True))
4 qbeta = pyro.param("qbeta", Variable(torch.Tensor([1.0]), requires_grad=True))
5 pyro.sample("theta", Beta(qalpha, qbeta))
6 # Inference
7 svi = SVI(cond, guide, Adam({}), loss="ELBO", num_particles=7)
8 for step in range(1000):
9 svi.step()

Infer.Net

Microsoft недавно открыла исходный код Infer.Net - фреймворка, который упрощает вероятностное программирование для разработчиков .Net. Microsoft Research работает над Infer.Net с 2004 года, но только недавно, с появлением глубокого обучения, этот фреймворк стал действительно популярным. Infer.Net предоставляет несколько сильных отличий, что делает его отличным выбором для разработчиков, которые решаются на Deep PPL:

  • Богатый язык моделирования ». Поддержка одномерных и многомерных переменных, как непрерывных, так и дискретных. Модели могут быть построены на основе широкого диапазона факторов, включая арифметические операции, линейную алгебру, ограничения диапазона и положительности, булевы операторы, дискретные операторы Дирихле, гауссовские и многие другие.
  • Множественные алгоритмы вывода ». Встроенные алгоритмы включают распространение ожиданий, распространение убеждений (особый случай EP), вариативную передачу сообщений и выборку Гиббса.
  • Разработан для крупномасштабного вывода: Infer.NET компилирует модели в исходный код вывода, который может выполняться независимо без дополнительных затрат. Его также можно интегрировать непосредственно в ваше приложение.
  • Расширяемый пользователем. Пользователь может добавлять распределения вероятностей, факторы, операции с сообщениями и алгоритмы вывода. Infer.NET использует архитектуру подключаемых модулей, что делает его открытым и адаптируемым.

Давайте посмотрим на наш пример подбрасывания монеты в Infer.Net.

Variable<bool> firstCoin = Variable.Bernoulli(0.5);
Variable<bool> secondCoin = Variable.Bernoulli(0.5);
Variable<bool> bothHeads = firstCoin & secondCoin;
InferenceEngine engine = new InferenceEngine();
Console.WriteLine("Probability both coins are heads: "+engine.Infer(bothHeads));

Область Deep PPL неуклонно становится важным основополагающим блоком экосистемы машинного обучения. Pyro, Edward и Infer.Net - это всего лишь три недавних примера Deep PPL, но не единственные подходящие. Пересечение фреймворков глубокого обучения и PPL открывает невероятно обширные возможности для инноваций, и новые варианты использования, вероятно, в ближайшем будущем раздвинут границы Deep Learning.