Поджигатель - функция правдоподобия и размерность выборки
Я изучаю 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()
Я установил здесь приоры по концентрациям (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
?