Поджигатель - функция правдоподобия и размерность выборки - PullRequest
1 голос
/ 04 июля 2019

Я изучаю Pyro и нахожу размеры запутанными, несмотря на богатую и подробную документацию

Это эскиз моей модели:

DATA_SIZE = 1000

simulated_daily_demand = torch.distributions.Beta(torch.tensor(2.0), torch.tensor(2.0)).sample([DATA_SIZE,])


def model(SIMULATION_DAYS = 30):
    alpha = pyro.param("alpha", pyro.distributions.Uniform(0, 10))
    beta = pyro.param("beta", pyro.distributions.Uniform(0, 10))    
    total_demand = 0
    for t in range(0, SIMULATION_DAYS):
        daily_demand = pyro.sample("daily_demand", pyro.distributions.Beta(alpha, beta), obs=simulated_daily_demand)
        total_demand = total_demand + daily_demand
    return total_demand

model()

Iустановите здесь априоры по концентрациям (alpha, beta). Мое понимание заключается в том, что вызов pyro.sample с observations подходит для данных - я полагаю, что это максимизирует вероятность концентрации данных при данных.

Вывод, который я получаю:

len(model())
C:\ProgramData\Anaconda3\lib\site-packages\pyro\primitives.py:85: RuntimeWarning: trying to observe a value outside of inference at daily_demand
  RuntimeWarning)
1000

Размер `)

Полученные значения выглядят хорошо.Среднее значение simulated_daily_demand составляет примерно 0,5, а среднее значение model() составляет ~ 15, что составляет ~ 30 * 0,5.Я не понимаю размер тензора.Я ожидал бы, что он будет .size() torch.Size([1]).

Я также заметил предупреждение.Я полагаю, что Pyro жалуется, потому что хотел бы, чтобы я написал руководство и сделал некоторый вывод о параметрах (например, SVI), прежде чем я смогу выполнить выборку из «ежедневного спроса».Мне также интересно, как я мог запустить модель после вывода скрытых концентраций.Небольшой набросок кода действительно поможет, спасибо!


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

import torch
import pyro

NUM_RUNS = 5
DATA_SIZE = 1000

simulated_daily_demand = torch.distributions.Beta(torch.tensor(2.0), torch.tensor(2.0)).sample([DATA_SIZE,])


def model(hist_demand, START_INVENTORY = torch.tensor(100.0), SIMULATION_DAYS = 30):
    alpha = pyro.param("alpha", pyro.distributions.Uniform(0, 10))
    beta = pyro.param("beta", pyro.distributions.Uniform(0, 10))    
    total_demand = 0
    for t in range(0, SIMULATION_DAYS):
        with pyro.plate("obs_loop"):
            daily_demand = pyro.sample("daily_demand", pyro.distributions.Beta(alpha, beta), obs=simulated_daily_demand)
        total_demand = total_demand + daily_demand
    return total_demand

total_demand_runs = []
for r in range(0, NUM_RUNS):
    total_demand_runs.append(model(simulated_daily_demand))

, который возвращает вложенный список размеров (NUM_RUNS, SIMULATION_DAYS), содержащий тензор размера DATA_SIZE.Элементы (daily_demand) одинаковы для всех дней моделирования.Возможно, ближе, но без сигары.


import torch
import pyro
import torch.distributions.constraints as constraints

NUM_RUNS = 5
SIMULATION_DAYS = 30
DATA_SIZE = 1000


simulated_daily_demand = torch.distributions.Beta(torch.tensor(2.0), torch.tensor(2.0)).sample([DATA_SIZE, SIMULATION_DAYS])

def model(hist_demand = None, START_INVENTORY = torch.tensor(100.0), SIMULATION_DAYS = SIMULATION_DAYS):
    alpha = pyro.param("alpha", pyro.distributions.Uniform(0, 10))
    beta = pyro.param("beta", pyro.distributions.Uniform(0, 10))
    with pyro.plate("obs_loop"):
        daily_demand_vector = pyro.sample("daily_demand", pyro.distributions.Beta(
            alpha * torch.ones([SIMULATION_DAYS]), 
            beta * torch.ones([SIMULATION_DAYS])), 
            obs=hist_demand
        )
    total_demand = 0
    for t in range(0, SIMULATION_DAYS):
        total_demand = total_demand + daily_demand_vector[t]
    return total_demand

def guide(hist_demand):
    alpha = pyro.param(
        "alpha", 
        pyro.distributions.Normal(torch.tensor(2.0), torch.tensor(0.1)),
        constraint = constraints.positive
        )
    beta = pyro.param(
        "beta",
        pyro.distributions.Normal(torch.tensor(2.0), torch.tensor(0.1)),
        constraint = constraints.positive
        )
    return alpha, beta

from pyro.optim import Adam
adam_params = {"lr": 0.005, "betas": (0.95, 0.999)}
optimizer = Adam(adam_params)
svi = pyro.infer.SVI(model, guide, optimizer, loss=pyro.infer.Trace_ELBO())

n_steps = 5000
# do gradient steps
for step in range(n_steps):
    svi.step(simulated_daily_demand)

alpha_q = pyro.param("alpha").item()
beta_q = pyro.param("beta").item()

Нечто подобное имеет смысл и кажется сходящимся: SVI выдает примерно правильные значения параметров.Теперь вопрос остается открытым - как я могу запустить симуляцию, используя выведенные значения alpha и beta?

...