我正在学习 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
这size()
我得到的值看起来不错。的平均值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
and运行模拟beta
?