Я изучаю 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
?