Пример #1
0
            nsamples=5000)
print(x.samples.shape)

plt.figure()
plt.plot(x.samples[:, 0], x.samples[:, 1], 'o')
plt.show()

# %% md
# DREAM algorithm: compare with :class:`.MetropolisHastings` (inputs parameters are set as their default values)
# ---------------------------------------------------------------------------------------------------------------------

# %%

# Define a function to sample seed uniformly distributed in the 2d space ([-20, 20], [-4, 4])
prior_sample = lambda nsamples: np.array([[-2, -2]]) + np.array(
    [[4, 4]]) * JointIndependent([Uniform(), Uniform()]).rvs(nsamples=nsamples)

fig, ax = plt.subplots(ncols=2, figsize=(12, 4))
seed = prior_sample(nsamples=7)

x = MetropolisHastings(dimension=2,
                       burn_length=500,
                       jump=50,
                       seed=seed.tolist(),
                       log_pdf_target=log_Rosenbrock,
                       nsamples=1000)
ax[0].plot(x.samples[:, 0], x.samples[:, 1], 'o')

x = DREAM(dimension=2,
          burn_length=500,
          jump=50,
Пример #2
0
rstate = np.random.RandomState(123)
data_noisy = data_clean + rstate.randn(*data_clean.shape)

from scipy.stats import norm


def log_target(x, data, x_domain):
    log_target_value = np.zeros(x.shape[0])
    for i, xx in enumerate(x):
        h_xx = xx[0] * x_domain + xx[1] * x_domain**2
        log_target_value[i] = np.sum(
            [norm.logpdf(hxi - datai) for hxi, datai in zip(h_xx, data)])
    return log_target_value


proposal = JointIndependent([Normal(scale=0.1), Normal(scale=0.05)])

sampler = MetropolisHastings(nsamples=500,
                             dimension=2,
                             log_pdf_target=log_target,
                             burn_length=10,
                             jump=10,
                             n_chains=1,
                             args_target=(data_noisy, domain),
                             proposal=proposal)

print(sampler.samples.shape)
samples = sampler.samples

plt.plot(samples[:, 0], samples[:, 1], 'o', alpha=0.5)
plt.plot(1., 2., marker='x', color='orange')
Пример #3
0
    return x**2 + y**2


# %% md
#
# Create a distribution object, generate samples and evaluate the function at the samples.

# %%

np.random.seed(1)

dist_1 = Uniform(loc=-5.12, scale=10.24)
dist_2 = Uniform(loc=-5.12, scale=10.24)

marg = [dist_1, dist_2]
joint = JointIndependent(marginals=marg)

n_samples = 100
x = joint.rvs(n_samples)
y = function(x[:, 0], x[:, 1])

# %% md
#
# Visualize the 2D function.

# %%

xmin, xmax = -6, 6
ymin, ymax = -6, 6
X1 = np.linspace(xmin, xmax, 50)
X2 = np.linspace(ymin, ymax, 50)
Пример #4
0
          for n in range(1, Ne + 1)]
    ev = np.array(ev)

    return ev[:Ne]


# %% md
#
# Create a distribution object.

# %%

pdf_lx = Normal(loc=2, scale=0.02)
pdf_ly = Normal(loc=1, scale=0.01)
margs = [pdf_lx, pdf_ly]
joint = JointIndependent(marginals=margs)

# %% md
#
# Define the number of input dimensions and choose the number of output dimensions (number of eigenvalues).

# %%

dim_in = 2
dim_out = 10

# %% md
#
# Construct PCE models by varying the maximum degree of polynomials (and therefore the number of polynomial basis) and
# compute the validation error for all resulting models.
Пример #5
0
    def __init__(
        self,
        pdf_target: Union[Callable, list[Callable]] = None,
        log_pdf_target: Union[Callable, list[Callable]] = None,
        args_target: tuple = None,
        burn_length: Annotated[int, Is[lambda x: x >= 0]] = 0,
        jump: int = 1,
        dimension: int = None,
        seed: list = None,
        save_log_pdf: bool = False,
        concatenate_chains: bool = True,
        n_chains: int = None,
        proposal: Distribution = None,
        proposal_is_symmetric: bool = False,
        random_state: RandomStateType = None,
        nsamples: PositiveInteger = None,
        nsamples_per_chain: PositiveInteger = None,
    ):
        """
        Metropolis-Hastings algorithm :cite:`MCMC1` :cite:`MCMC2`

        :param pdf_target: Target density function from which to draw random samples. Either `pdf_target` or
         `log_pdf_target` must be provided (the latter should be preferred for better numerical stability).

         If `pdf_target` is a callable, it refers to the joint pdf to sample from, it must take at least one input
         **x**, which are the point(s) at which to evaluate the pdf. Within :class:`.MCMC` the pdf_target is evaluated
         as:
         :code:`p(x) = pdf_target(x, \*args_target)`

         where **x** is a :class:`numpy.ndarray  of shape :code:`(nsamples, dimension)` and `args_target` are additional
         positional arguments that are provided to :class:`.MCMC` via its `args_target` input.

         If `pdf_target` is a list of callables, it refers to independent marginals to sample from. The marginal in
         dimension :code:`j` is evaluated as:
         :code:`p_j(xj) = pdf_target[j](xj, \*args_target[j])` where **x** is a :class:`numpy.ndarray` of shape
         :code:`(nsamples, dimension)`
        :param log_pdf_target: Logarithm of the target density function from which to draw random samples.
         Either `pdf_target` or `log_pdf_target` must be provided (the latter should be preferred for better numerical
         stability).

         Same comments as for input `pdf_target`.
        :param args_target: Positional arguments of the pdf / log-pdf target function. See `pdf_target`
        :param burn_length: Length of burn-in - i.e., number of samples at the beginning of the chain to discard (note:
         no thinning during burn-in). Default is :math:`0`, no burn-in.
        :param jump: Thinning parameter, used to reduce correlation between samples. Setting :code:`jump=n` corresponds
         to skipping :code:`n-1` states between accepted states of the chain. Default is :math:`1` (no thinning).
        :param dimension: A scalar value defining the dimension of target density function. Either `dimension` and
         `n_chains` or `seed` must be provided.
        :param seed: Seed of the Markov chain(s), shape :code:`(n_chains, dimension)`.
         Default: :code:`zeros(n_chains x dimension)`.

         If seed is not provided, both n_chains and dimension must be provided.
        :param save_log_pdf: Boolean that indicates whether to save log-pdf values along with the samples.
         Default: :any:`False`
        :param concatenate_chains: Boolean that indicates whether to concatenate the chains after a run, i.e., samples
         are stored as an :class:`numpy.ndarray` of shape :code:`(nsamples * n_chains, dimension)` if :any:`True`,
         :code:`(nsamples, n_chains, dimension)` if :any:`False`.
         Default: :any:`True`
        :param n_chains: The number of Markov chains to generate. Either dimension and `n_chains` or `seed` must be
         provided.
        :param proposal: Proposal distribution, must have a log_pdf/pdf and rvs method. Default: standard
         multivariate normal
        :param proposal_is_symmetric: Indicates whether the proposal distribution is symmetric, affects computation of
         acceptance probability alpha Default: :any:`False`, set to :any:`True` if default proposal is used
        :param random_state: Random seed used to initialize the pseudo-random number generator. Default is
         :any:`None`.

        :param nsamples: Number of samples to generate.
        :param nsamples_per_chain: Number of samples to generate per chain.
        """
        self.nsamples = nsamples
        self.nsamples_per_chain = nsamples_per_chain
        super().__init__(
            pdf_target=pdf_target,
            log_pdf_target=log_pdf_target,
            args_target=args_target,
            dimension=dimension,
            seed=seed,
            burn_length=burn_length,
            jump=jump,
            save_log_pdf=save_log_pdf,
            concatenate_chains=concatenate_chains,
            random_state=random_state,
            n_chains=n_chains,
        )

        self.logger = logging.getLogger(__name__)
        # Initialize algorithm specific inputs
        self.proposal = proposal
        self.proposal_is_symmetric = proposal_is_symmetric
        if self.proposal is None:
            if self.dimension is None:
                raise ValueError(
                    "UQpy: Either input proposal or dimension must be provided."
                )
            from UQpy.distributions import JointIndependent, Normal

            self.proposal = JointIndependent([Normal()] * self.dimension)
            self.proposal_is_symmetric = True
        else:
            self._check_methods_proposal(self.proposal)

        self.logger.info("\nUQpy: Initialization of " +
                         self.__class__.__name__ + " algorithm complete.")

        if (nsamples is not None) or (nsamples_per_chain is not None):
            self.run(
                nsamples=nsamples,
                nsamples_per_chain=nsamples_per_chain,
            )
# where :math:`\tilde{w}` are the normalized weights.
#
# [1] *Sequential Monte Carlo Methods in Practice*, A. Doucet, N. de Freitas, and N. Gordon, 2001, Springer, New York

from UQpy.distributions import Uniform, JointIndependent
from UQpy.sampling import ImportanceSampling
import matplotlib.pyplot as plt
import numpy as np


def log_Rosenbrock(x, param):
    return (-(100 * (x[:, 1] - x[:, 0]**2)**2 + (1 - x[:, 0])**2) / param)


proposal = JointIndependent(
    [Uniform(loc=-8, scale=16),
     Uniform(loc=-10, scale=60)])
print(proposal.get_parameters())

w = ImportanceSampling(log_pdf_target=log_Rosenbrock,
                       args_target=(20, ),
                       proposal=proposal,
                       nsamples=5000)

#%% md
#
# Look at distribution of weights
# -------------------------------

#%%
h_func.run(samples=param_true)

# Add noise
error_covariance = 1.
data_clean = np.array(h_func.qoi_list[0])
noise = Normal(loc=0.,
               scale=np.sqrt(error_covariance)).rvs(nsamples=50).reshape(
                   (50, ))
data_3 = data_clean + noise
print('Shape of data: {}'.format(data_3.shape))

inference_model = ComputationalModel(n_parameters=2,
                                     runmodel_object=h_func,
                                     error_covariance=error_covariance)

sampling = ImportanceSampling(proposal=JointIndependent([Normal(scale=2, )] *
                                                        2))
bayes_estimator =\
    BayesParameterEstimation(inference_model=inference_model,
                             data=data_3,
                             sampling_class=sampling,
                             nsamples=5000)

s = bayes_estimator.sampler.samples
w = bayes_estimator.sampler.weights
print(sum(w))

# print results
fig, ax = plt.subplots(1, 2)
for i in range(2):
    ax[i].hist(x=s[:, i],
               weights=None,
Пример #8
0
import numpy as np
from UQpy.sampling import ImportanceSampling
from UQpy.distributions import JointIndependent, Uniform


def log_rosenbrock(x, param):
    return -(100 * (x[:, 1] - x[:, 0]**2)**2 + (1 - x[:, 0])**2) / param


def rosenbrock(x):
    return np.exp(-(100 * (x[:, 1] - x[:, 0]**2)**2 + (1 - x[:, 0])**2) / 20)


proposal = JointIndependent(
    [Uniform(loc=-8, scale=16),
     Uniform(loc=-10, scale=60)])
proposal2 = JointIndependent(
    [Uniform(loc=-8, scale=16),
     Uniform(loc=-10, scale=60)])
del proposal2.log_pdf


def test_pdf_target():
    w = ImportanceSampling(pdf_target=rosenbrock,
                           proposal=proposal,
                           random_state=123,
                           nsamples=2000)
    assert (w.weights.shape == (2000, )
            and np.all(np.round(w.samples[-1], 3) == [-6.434, 27.373]))

Пример #9
0
print('posterior probabilities of all three models')
print(model_posterior_probas)

#%% md
#
# Define the models for use in UQpy

#%%

candidate_models = []
for n, model_name in enumerate(model_names):
    run_model = RunModel(model_script='local_pfn_models.py',
                         model_object_name=model_name,
                         vec=False)
    prior = JointIndependent([
        Normal(loc=m, scale=std)
        for m, std in zip(model_prior_means[n], model_prior_stds[n])
    ])
    model = ComputationalModel(n_parameters=model_n_params[n],
                               runmodel_object=run_model,
                               prior=prior,
                               error_covariance=error_covariance,
                               name=model_name)
    candidate_models.append(model)

#%% md
#
# Run MCMC for one model

#%%

# Quadratic model
         linewidth=2,
         color='r')
plt.title('data as histogram and true distribution to be estimated')
plt.show()

#%% md
#
# In a Bayesian setting, the definition of a prior pdf is a key point. The prior for the parameters must be defined in
# the model. Note that if no prior is given, an improper, uninformative, prior is chosen, :math:`p(\theta)=1` for all
# :math:`\theta`.

#%%

p0 = Uniform(loc=0., scale=15)
p1 = Lognormal(s=1., loc=0., scale=1.)
prior = JointIndependent(marginals=[p0, p1])

candidate_model = DistributionModel(distributions=Normal(loc=None, scale=None),
                                    n_parameters=2,
                                    prior=prior)

# Learn the unknown parameters using MCMC
from UQpy.sampling import MetropolisHastings

mh1 = MetropolisHastings(jump=10,
                         burn_length=10,
                         seed=[1.0, 0.2],
                         random_state=123)

bayes_estimator = BayesParameterEstimation(inference_model=candidate_model,
                                           data=data_1,
Пример #11
0
def function(x):
    return 100 * (np.exp(-2 / (x[:, 0]**1.75)) + np.exp(-2 / (x[:, 1]**1.5)) +
                  np.exp(-2 / (x[:, 2]**1.25)))


# %% md
#
# Define the input probability distributions.

# %%

# input distributions
dist = Uniform(loc=0, scale=1)
marg = [dist] * 3
joint = JointIndependent(marginals=marg)

# %% md
#
# Compute reference mean and variance values using Monte Carlo sampling.

# %%

# reference moments via Monte Carlo Sampling
n_samples_mc = 1000000
xx = joint.rvs(n_samples_mc)
yy = function(xx)
mean_ref = yy.mean()
var_ref = yy.var()

# %% md
from UQpy.sampling import ImportanceSampling

#%% md
#
# First data is generated from a true model. A distribution with copulas does not possess a fit method, thus sampling is
# performed using importance sampling/resampling.

#%%

# dist_true exhibits dependence between the two dimensions, defined using a gumbel copula
dist_true = JointCopula(marginals=[Normal(), Normal()],
                        copula=Gumbel(theta=2.))

# generate data using importance sampling: sample from a bivariate gaussian without copula, then weight samples
u = ImportanceSampling(
    proposal=JointIndependent(marginals=[Normal(), Normal()]),
    log_pdf_target=dist_true.log_pdf,
    nsamples=500)
print(u.samples.shape)
print(u.weights.shape)
# Resample to obtain 5,000 data points
u.resample(nsamples=5000)
data_2 = u.unweighted_samples
print('Shape of data: {}'.format(data_2.shape))

fig, ax = plt.subplots()
ax.scatter(data_2[:, 0], data_2[:, 1], alpha=0.2)
ax.set_title(
    'Data points from true bivariate normal with gumbel dependency structure')
plt.show()
Пример #13
0
# %% md
#
# Plot the failure domain

# %%

x = np.linspace(2, 8, 1000)
y = np.linspace(25, 225, 1000)

X, Y = np.meshgrid(x, y)
Z = np.zeros((1000, 1000))

d1 = Normal(loc=5, scale=1)
d2 = Normal(loc=125, scale=20)

dist = JointIndependent(marginals=[d1, d2])

for i in range(len(x)):
    Z[i, :] = dist.pdf(
        np.append(np.atleast_2d(X[i, :]), np.atleast_2d(Y[i, :]), 0).T)

fig, ax = plt.subplots()
CS = ax.contour(X, Y, Z, 15)
plt.plot(m, k_hi, 'k')
plt.plot(m, k_lo, 'k')
# plt.fill_between(m,k_lo,k_hi)
plt.xlim([mu_m - 3 * sigma_m, mu_m + 3 * sigma_m])
plt.ylim([mu_k - 3 * sigma_k, mu_k + 3 * sigma_k])
plt.xlabel(r'Mass ($m$)')
plt.ylabel(r'Stiffness ($k$)')
plt.grid(True)
Пример #14
0
data_clean = np.array(h_func.qoi_list[0])
print(data_clean.shape)

# Add noise, use a RandomState for reproducible results
error_covariance = 1.
noise = Normal(loc=0.,
               scale=np.sqrt(error_covariance)).rvs(nsamples=50,
                                                    random_state=123).reshape(
                                                        (50, ))
data_3 = data_clean + noise
print('Shape of data: {}'.format(data_3.shape))
print(data_3[:4])

p0 = Normal()
p1 = Normal()
prior = JointIndependent(marginals=[p0, p1])

inference_model = ComputationalModel(n_parameters=2,
                                     runmodel_object=h_func,
                                     error_covariance=error_covariance,
                                     prior=prior)

proposal = JointIndependent([Normal(scale=0.1), Normal(scale=0.05)])

mh1 = MetropolisHastings(jump=10,
                         burn_length=0,
                         proposal=proposal,
                         seed=[0.5, 2.5],
                         random_state=456)

bayes_estimator = BayesParameterEstimation(inference_model=inference_model,
Пример #15
0
from UQpy.distributions import Normal, JointIndependent
from UQpy.distributions import Gumbel, JointCopula

#%% md
#
# Define a Copula
# ---------------
# The definition of bivariate distribution with a copula, is similar to defining a multivariate distribution from
# independent marginals. In both cases a list of marginals needs to be defined. In case of

#%%
marginals = [Normal(loc=0., scale=1), Normal(loc=0., scale=1)]
copula = Gumbel(theta=3.)

# dist_1 is a multivariate normal with independent marginals
dist_1 = JointIndependent(marginals)
print('Does the distribution with independent marginals have an rvs method?')
print(hasattr(dist_1, 'rvs'))

# dist_2 exhibits dependence between the two dimensions, defined using a gumbel copula
dist_2 = JointCopula(marginals=marginals, copula=copula)
print('Does the distribution with copula have an rvs method?')
print(hasattr(dist_2, 'rvs'))

#%% md
#
# Plot the pdf of the distribution before and after the copula
# -------------------------------------------------------------
#

#%%
Пример #16
0
print(seed)
print(x.samples[0, :, :])

# %% md
#
# The algorithm-specific parameters for MetropolisHastings are proposal and proposal_is_symmetric
# -------------------------------------------------------------------------------------------------
# The default proposal is standard normal (symmetric).

# %%

# Define a few proposals to try out
from UQpy.distributions import JointIndependent, Normal, Uniform

proposals = [
    JointIndependent([Normal(), Normal()]),
    JointIndependent(
        [Uniform(loc=-0.5, scale=1.5),
         Uniform(loc=-0.5, scale=1.5)]),
    Normal()
]

proposals_is_symmetric = [True, False, False]

fig, ax = plt.subplots(ncols=3, figsize=(16, 4))
for i, (proposal, symm) in enumerate(zip(proposals, proposals_is_symmetric)):
    print(i)
    try:
        x = MetropolisHastings(dimension=2,
                               burn_length=500,
                               jump=100,