AttributeError: 'BayesianRegression' object has no attribute 'save_to_buffer'

When running pyro model saving in Bayesian Regression-Introduction (Part 1), AttributeError: ‘BayesianRegression’ object has no attribute ‘save_to_buffer’

import os, torch, pyro
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import pyro.distributions as dist

smoke_test = ('CI' in os.environ)
pyro.enable_validation(True)
pyro.set_rng_seed(1)

plt.style.use('default')

DATA_URL = 'https://d2hg8soec8ck9v.cloudfront.net/datasets/rugged_data.csv'
data = pd.read_csv(DATA_URL, encoding='ISO-8859-1')
df = data[['rugged', 'cont_africa', 'rgdppc_2000']]
df = df[np.isfinite(df.rgdppc_2000)]
df['rgdppc_2000'] = np.log(df['rgdppc_2000'])

from torch import nn
from pyro.nn import PyroModule

assert issubclass(PyroModule[nn.Linear], nn.Linear)
assert issubclass(PyroModule[nn.Linear], PyroModule)

df['cont_africa_x_rugged'] = df['cont_africa'] * df['rugged']
data = torch.tensor(df[['cont_africa', 'rugged', 'cont_africa_x_rugged', 'rgdppc_2000']].values, dtype=torch.float)
x_data, y_data = data[:, :-1], data[:, -1]
num_iterations = 100 if not smoke_test else 2

from pyro.nn import PyroSample

class BayesianRegression(PyroModule):
    def __init__(self, in_features, out_features):
        super().__init__()
        self.linear = PyroModule[nn.Linear](in_features, out_features)
        self.linear.weight = PyroSample(dist.Normal(0., 1.).expand([out_features, in_features]).to_event(2))
        self.linear.bias = PyroSample(dist.Normal(0., 10.).expand([out_features]).to_event(1))
    #
    def forward(self, x, y=None):
        sigma = pyro.sample('sigma', dist.Uniform(0., 10.))
        mean = self.linear(x).squeeze(-1)
        with pyro.plate('data', x.shape[0]):
            obs = pyro.sample('obs', dist.Normal(mean, sigma), obs=y)
        return mean

from pyro.infer.autoguide import AutoDiagonalNormal

model = BayesianRegression(3, 1)
guide = AutoDiagonalNormal(model)

from pyro import optim
from pyro.infer import SVI, Trace_ELBO

adam = optim.Adam({'lr':0.03})
svi = SVI(model, guide, adam, loss=Trace_ELBO())

pyro.clear_param_store()
signal = 1
if signal == 1:
    for j in range(num_iterations):
        loss = svi.step(x_data, y_data)
        if j % 100 == 0:
            print('[iteration %04d] loss: %.4f' % (j + 1, loss / len(data)))

from collections import defaultdict
from pyro import poutine
from pyro.poutine.util import prune_subsample_sites
import warnings

class Predict(torch.nn.Module):
    def __init__(self, model, guide):
        super().__init__()
        self.model = model
        self.guide = guide

    def forward(self, *args, **kwargs):
        samples = {}
        guide_trace = poutine.trace(self.guide).get_trace(*args, **kwargs)
        model_trace = poutine.trace(poutine.replay(self.model, guide_trace)).get_trace(*args, **kwargs)
        for site in prune_subsample_sites(model_trace).stochastic_nodes:
            samples[site] = model_trace.nodes[site]['value']
        return tuple(v for _, v in sorted(samples.items()))

predict_fn = Predict(model, guide)

predict_module = torch.jit.trace_module(predict_fn, {"forward": (x_data,)}, check_trace=False)

torch.jit.save(model, guide, 'tmp/reg_predict.pt')
pred_loaded = torch.jit.load('tmp/reg_predict.pt')
predictions_h = pred_loaded(x_data)

i have no idea what the issue is but i’d generally be cautious about using pytorch jit. it has changed so many times over the past 3 years that we were never able to make it work reliably with pyro.

this seems to work:

predict_fn = Predict(model, guide)
torch.save(predict_fn, 'tmp/reg_predict.pt')
pred_loaded = torch.load('tmp/reg_predict.pt')
print(pred_loaded(x_data))

I need to save the trained model, but trying torch.save can’t import the model. Is there a better case for saving models?

  • The model preservation issue has been resolved. Thank you very much!
import os, torch, pyro
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import pyro.distributions as dist

smoke_test = ('CI' in os.environ)
pyro.enable_validation(True)
pyro.set_rng_seed(1)

plt.style.use('default')

DATA_URL = 'https://d2hg8soec8ck9v.cloudfront.net/datasets/rugged_data.csv'
data = pd.read_csv(DATA_URL, encoding='ISO-8859-1')
df = data[['rugged', 'cont_africa', 'rgdppc_2000']]
df = df[np.isfinite(df.rgdppc_2000)]
df['rgdppc_2000'] = np.log(df['rgdppc_2000'])

from torch import nn
from pyro.nn import PyroModule

assert issubclass(PyroModule[nn.Linear], nn.Linear)
assert issubclass(PyroModule[nn.Linear], PyroModule)

df['cont_africa_x_rugged'] = df['cont_africa'] * df['rugged']
data = torch.tensor(df[['cont_africa', 'rugged', 'cont_africa_x_rugged', 'rgdppc_2000']].values, dtype=torch.float)
x_data, y_data = data[:, :-1], data[:, -1]
num_iterations = 100 if not smoke_test else 2

from pyro.nn import PyroSample

class BayesianRegression(PyroModule):
    def __init__(self, in_features, out_features):
        super().__init__()
        self.linear = PyroModule[nn.Linear](in_features, out_features)
        self.linear.weight = PyroSample(dist.Normal(0., 1.).expand([out_features, in_features]).to_event(2))
        self.linear.bias = PyroSample(dist.Normal(0., 10.).expand([out_features]).to_event(1))
    #
    def forward(self, x, y=None):
        sigma = pyro.sample('sigma', dist.Uniform(0., 10.))
        mean = self.linear(x).squeeze(-1)
        with pyro.plate('data', x.shape[0]):
            obs = pyro.sample('obs', dist.Normal(mean, sigma), obs=y)
        return mean

from pyro.infer.autoguide import AutoDiagonalNormal

model = BayesianRegression(3, 1)
guide = AutoDiagonalNormal(model)

from pyro import optim
from pyro.infer import SVI, Trace_ELBO

adam = optim.Adam({'lr':0.03})
svi = SVI(model, guide, adam, loss=Trace_ELBO())

pyro.clear_param_store()
signal = 0
if signal == 1:
    for j in range(num_iterations):
        loss = svi.step(x_data, y_data)
        if j % 100 == 0:
            print('[iteration %04d] loss: %.4f' % (j + 1, loss / len(data)))

        torch.save({"model": model}, 'save_model\model.pth')
        torch.save({"guide": guide}, 'save_model\model_guide.pth')
        # torch.save(model.state_dict(), 'save_model\model1.pth')
        torch.save({"model": model, "guide": guide}, 'save_model\model_new.pth')
torch.load("save_model\model.pth")
torch.load("save_model\model_guide.pth")
# new_model1 = model.load_state_dict(torch.load('save_model\model1.pth'))


new_model = torch.load('save_model\model_new.pth')
guide = new_model['guide']
# 模型评估
from pyro.infer import Predictive

def summary(samples):
    site_stats = {}
    for k, v in samples.items():
        site_stats[k] = {
            'mean': torch.mean(v, 0),
            'std':torch.std(v, 0),
            '5%':v.kthvalue(int(len(v) * 0.05), dim=0)[0],
            '95%':v.kthvalue(int(len(v) * 0.95), dim=0)[0],
         }
    return site_stats

predictive = Predictive(model, guide=guide, num_samples=800,
                        return_sites=('linear.weight', 'obs', '_RETURN'))
samples = predictive(x_data)
pred_summary = summary(samples)

mu = pred_summary["_RETURN"]
y = pred_summary["obs"]