示例#1
0
文件: polynomials.py 项目: maxfl/zfit
def legendre_integral(limits: ztyping.SpaceType, norm_range: ztyping.SpaceType,
                      params: List["zfit.Parameter"],
                      model: RecursivePolynomial):
    """Recursive integral of Legendre polynomials"""
    lower, upper = limits.limit1d
    lower_rescaled = model._polynomials_rescale(lower)
    upper_rescaled = model._polynomials_rescale(upper)
    # if np.allclose((lower_rescaled, upper_rescaled), (-1, 1)):
    #     return ztf.constant(2.)  #

    lower = ztf.convert_to_tensor(lower_rescaled)
    upper = ztf.convert_to_tensor(upper_rescaled)

    integral_0 = model.params[f"c_0"] * (upper - lower)  # if polynomial 0 is 1
    if model.degree == 0:
        integral = integral_0
    else:

        def indefinite_integral(limits):
            max_degree = model.degree + 1  # needed +1 for integral, max poly in term for n is n+1
            polys = do_recurrence(x=limits,
                                  polys=legendre_polys,
                                  degree=max_degree,
                                  recurrence=legendre_recurrence)
            one_limit_integrals = []
            for degree in range(1, max_degree):
                coeff = model.params[f"c_{degree}"]
                one_limit_integrals.append(
                    coeff * (polys[degree + 1] - polys[degree - 1]) /
                    (2. * (ztf.convert_to_tensor(degree)) + 1))
            return ztf.reduce_sum(one_limit_integrals, axis=0)

        integral = indefinite_integral(upper) - indefinite_integral(
            lower) + integral_0
        integral = tf.reshape(integral, shape=())
    integral *= 0.5 * model.space.area()  # rescale back to whole width

    return integral
示例#2
0
文件: sample.py 项目: simonUU/zfit
    def __call__(self, n_to_produce: Union[int, tf.Tensor], limits: Space,
                 dtype):
        rnd_samples = []
        thresholds_unscaled_list = []
        weights = tf.broadcast_to(ztf.constant(1., shape=(1, )),
                                  shape=(n_to_produce, ))

        for (lower, upper), area in zip(limits.iter_limits(as_tuple=True),
                                        limits.iter_areas(rel=True)):
            n_partial_to_produce = tf.cast(
                ztf.to_real(n_to_produce) * ztf.to_real(area),
                dtype=tf.int32)  # TODO(Mayou36): split right!

            lower = ztf.convert_to_tensor(lower, dtype=dtype)
            upper = ztf.convert_to_tensor(upper, dtype=dtype)

            if isinstance(limits, EventSpace):
                lower = tf.transpose(a=lower)
                upper = tf.transpose(a=upper)

            sample_drawn = tf.random.uniform(
                shape=(n_partial_to_produce, limits.n_obs + 1),
                # + 1 dim for the function value
                dtype=ztypes.float)

            rnd_sample = sample_drawn[:, :-1] * (
                upper - lower) + lower  # -1: all except func value
            thresholds_unscaled = sample_drawn[:, -1]
            # if not multiple_limits:
            #     return rnd_sample, thresholds_unscaled
            rnd_samples.append(rnd_sample)
            thresholds_unscaled_list.append(thresholds_unscaled)

        rnd_sample = tf.concat(rnd_samples, axis=0)
        thresholds_unscaled = tf.concat(thresholds_unscaled_list, axis=0)

        n_drawn = n_to_produce
        return rnd_sample, thresholds_unscaled, weights, weights, n_drawn
示例#3
0
文件: polynomials.py 项目: maxfl/zfit
def func_integral_laguerre(limits, norm_range, params: Dict, model):
    """The integral of the simple laguerre polynomials.

    Defined as :math:`\int L_{n} = (-1) L_{n+1}^{(-1)}` with :math:`L^{(\alpha)}` the generalized Laguerre polynom.

    Args:
        limits:
        norm_range:
        params:
        model:

    Returns:

    """
    lower, upper = limits.limit1d
    lower_rescaled = model._polynomials_rescale(lower)
    upper_rescaled = model._polynomials_rescale(upper)

    lower = ztf.convert_to_tensor(lower_rescaled)
    upper = ztf.convert_to_tensor(upper_rescaled)

    # The laguerre shape makes the sum for us. setting the 0th coeff to 0, since no -1 term exists.
    coeffs_laguerre_nup = {
        f'c_{int(n.split("_", 1)[-1]) + 1}': c
        for i, (n, c) in enumerate(params.items())
    }  # increase n -> n+1 of naming
    coeffs_laguerre_nup['c_0'] = tf.constant(0., dtype=model.dtype)
    coeffs_laguerre_nup = convert_coeffs_dict_to_list(coeffs_laguerre_nup)

    def indefinite_integral(limits):
        return -1 * laguerre_shape_alpha_minusone(x=limits,
                                                  coeffs=coeffs_laguerre_nup)

    integral = indefinite_integral(upper) - indefinite_integral(lower)
    integral = tf.reshape(integral, shape=())
    integral *= 0.5 * model.space.area()  # rescale back to whole width
    return integral
示例#4
0
文件: polynomials.py 项目: maxfl/zfit
 def indefinite_integral(limits):
     max_degree = model.degree + 1
     polys = do_recurrence(x=limits,
                           polys=chebyshev_polys,
                           degree=max_degree,
                           recurrence=chebyshev_recurrence)
     one_limit_integrals = []
     for degree in range(2, max_degree):
         coeff = model.params[f"c_{degree}"]
         n_float = ztf.convert_to_tensor(degree)
         integral = (n_float * polys[degree + 1] /
                     (ztf.square(n_float) - 1) -
                     limits * polys[degree] / (n_float - 1))
         one_limit_integrals.append(coeff * integral)
     return ztf.reduce_sum(one_limit_integrals, axis=0)
示例#5
0
def test_analytic_integral():
    class DistFunc3(zbasepdf.BasePDF):
        def _unnormalized_pdf(self, x, norm_range=False):
            return func3_2deps(x)

    mu_true = 1.4
    sigma_true = 1.8
    limits = -4.3, 1.9
    mu = Parameter("mu_1414", mu_true, mu_true - 2., mu_true + 7.)
    sigma = Parameter("sigma_1414", sigma_true, sigma_true - 10.,
                      sigma_true + 5.)
    gauss_params1 = CustomGaussOLD(mu=mu,
                                   sigma=sigma,
                                   obs=obs1,
                                   name="gauss_params1")
    normal_params1 = Gauss(mu=mu, sigma=sigma, obs=obs1, name="gauss_params1")
    try:
        infinity = mt.inf
    except AttributeError:  # py34
        infinity = float('inf')
    gauss_integral_infs = gauss_params1.integrate(limits=(-infinity, infinity),
                                                  norm_range=False)
    normal_integral_infs = normal_params1.integrate(limits=(-infinity,
                                                            infinity),
                                                    norm_range=False)

    DistFunc3.register_analytic_integral(func=func3_2deps_fully_integrated,
                                         limits=Space.from_axes(limits=limits3,
                                                                axes=(0, 1)))

    dist_func3 = DistFunc3(obs=['obs1', 'obs2'])
    gauss_integral_infs = zfit.run(gauss_integral_infs)
    normal_integral_infs = zfit.run(normal_integral_infs)
    func3_integrated = zfit.run(
        ztf.convert_to_tensor(dist_func3.integrate(limits=Space.from_axes(
            limits=limits3, axes=(0, 1)),
                                                   norm_range=False),
                              dtype=tf.float64))
    assert func3_integrated == func3_2deps_fully_integrated(
        limits=Space.from_axes(limits=limits3, axes=(0, 1)))
    assert gauss_integral_infs == pytest.approx(np.sqrt(np.pi * 2.) *
                                                sigma_true,
                                                rel=0.0001)
    assert normal_integral_infs == pytest.approx(1, rel=0.0001)
示例#6
0
    def __init__(self,
                 params: Dict[str, ZfitParameter],
                 distribution: tfd.Distribution,
                 dist_params,
                 dist_kwargs=None,
                 name: str = "DistributionConstraint",
                 dtype=ztypes.float,
                 **kwargs):
        """ Base class for constraints using a probability density function.

        Args:
            distribution (`tensorflow_probability.distributions.Distribution`): The probability density function
                used to constraint the parameters

        """
        super().__init__(params=params, name=name, dtype=dtype, **kwargs)

        self._distribution = distribution
        self.dist_params = dist_params
        self.dist_kwargs = dist_kwargs if dist_kwargs is not None else {}
        self._tparams = ztf.convert_to_tensor(self.get_params())
示例#7
0
    def set_weights(self, weights: ztyping.WeightsInputType):
        """Set (temporarily) the weights of the dataset.

        Args:
            weights (`tf.Tensor`, np.ndarray, None):


        """
        if weights is not None:
            weights = ztf.convert_to_tensor(weights)
            weights = ztf.to_real(weights)
            if weights.shape.ndims != 1:
                raise ShapeIncompatibleError(
                    "Weights have to be 1-Dim objects.")

        def setter(value):
            self._weights = value

        def getter():
            return self.weights

        return TemporarilySet(value=weights, getter=getter, setter=setter)
示例#8
0
 def step_size(self, value):
     if value is not None:
         value = ztf.convert_to_tensor(value)
     self._step_size = value
示例#9
0
 def loss_func():
     probs = ztf.convert_to_tensor((a_param - true_a) ** 2
                                   + (b_param - true_b) ** 2
                                   + (c_param - true_c) ** 4) + 0.42
     return tf.reduce_sum(tf.log(probs))
示例#10
0
 def __init__(self, tensor):
     if not isinstance(tensor, tf.Tensor):
         tensor = ztf.convert_to_tensor(tensor)
     self.tensor = tensor
示例#11
0
def mc_integrate(func: Callable,
                 limits: ztyping.LimitsType,
                 axes: Optional[ztyping.AxesTypeInput] = None,
                 x: Optional[ztyping.XType] = None,
                 n_axes: Optional[int] = None,
                 draws_per_dim: int = 20000,
                 method: str = None,
                 dtype: Type = ztypes.float,
                 mc_sampler: Callable = tfp.mcmc.sample_halton_sequence,
                 importance_sampling: Optional[Callable] = None) -> tf.Tensor:
    """Monte Carlo integration of `func` over `limits`.

    Args:
        func (callable): The function to be integrated over
        limits (:py:class:`~zfit.Space`): The limits of the integral
        axes (tuple(int)): The row to integrate over. None means integration over all value
        x (numeric): If a partial integration is performed, this are the value where x will be evaluated.
        n_axes (int): the number of total dimensions (old?)
        draws_per_dim (int): How many random points to draw per dimensions
        method (str): Which integration method to use
        dtype (dtype): |dtype_arg_descr|
        mc_sampler (callable): A function that takes one argument (`n_draws` or similar) and returns
            random value between 0 and 1.
        importance_sampling ():

    Returns:
        numerical: the integral
    """
    if axes is not None and n_axes is not None:
        raise ValueError("Either specify axes or n_axes")
    limits = convert_to_space(limits)

    axes = limits.axes
    partial = (axes is not None) and (x is not None
                                      )  # axes, value can be tensors

    if axes is not None and n_axes is None:
        n_axes = len(axes)
    if n_axes is not None and axes is None:
        axes = tuple(range(n_axes))

    lower, upper = limits.limits
    if np.infty in upper[0] or -np.infty in lower[0]:
        raise ValueError(
            "MC integration does (currently) not support unbound limits (np.infty) as given here:"
            "\nlower: {}, upper: {}".format(lower, upper))

    lower = ztf.convert_to_tensor(lower, dtype=dtype)
    upper = ztf.convert_to_tensor(upper, dtype=dtype)

    n_samples = draws_per_dim

    chunked_normalization = zfit.run.chunksize < n_samples
    # chunked_normalization = True
    if chunked_normalization:
        if partial:
            raise DueToLazynessNotImplementedError(
                "This feature is not yet implemented: needs new Datasets")
        n_chunks = int(np.ceil(n_samples / zfit.run.chunksize))
        chunksize = int(np.ceil(n_samples / n_chunks))
        print("starting normalization with {} chunks and a chunksize of {}".
              format(n_chunks, chunksize))
        avg = normalization_chunked(func=func,
                                    n_axes=n_axes,
                                    dtype=dtype,
                                    x=x,
                                    num_batches=n_chunks,
                                    batch_size=chunksize,
                                    space=limits)

    else:
        # TODO: deal with n_obs properly?

        samples_normed = mc_sampler(dim=n_axes,
                                    num_results=n_samples,
                                    dtype=dtype)
        # samples_normed = tf.reshape(samples_normed, shape=(n_vals, int(n_samples / n_vals), n_axes))
        # samples_normed = tf.expand_dims(samples_normed, axis=0)
        samples = samples_normed * (
            upper - lower) + lower  # samples is [0, 1], stretch it
        # samples = tf.transpose(samples, perm=[2, 0, 1])

        if partial:  # TODO(Mayou36): shape of partial integral?
            data_obs = x.obs
            new_obs = []
            x = x.value()
            value_list = []
            index_samples = 0
            index_values = 0
            if len(x.shape) == 1:
                x = tf.expand_dims(x, axis=1)
            for i in range(n_axes + x.shape[-1].value):
                if i in axes:
                    new_obs.append(limits.obs[index_samples])
                    value_list.append(samples[:, index_samples])
                    index_samples += 1
                else:
                    new_obs.append(data_obs[index_values])
                    value_list.append(
                        tf.expand_dims(x[:, index_values], axis=1))
                    index_values += 1
            value_list = [tf.cast(val, dtype=dtype) for val in value_list]
            x = value_list
            x = PartialIntegralSampleData(sample=value_list,
                                          space=Space(obs=new_obs))
        else:
            x = samples

        # convert rnd samples with value to feedable vector
        reduce_axis = 1 if partial else None
        avg = tf.reduce_mean(func(x), axis=reduce_axis)
        # avg = tfp.monte_carlo.expectation(f=func, samples=x, axis=reduce_axis)
        # TODO: importance sampling?
        # avg = tfb.monte_carlo.expectation_importance_sampler(f=func, samples=value,axis=reduce_axis)
    integral = avg * tf.cast(ztf.convert_to_tensor(limits.area()),
                             dtype=avg.dtype)
    return integral
示例#12
0
    def __init__(self,
                 data: tf.Tensor,
                 bandwidth: ztyping.ParamTypeInput,
                 obs: ztyping.ObsTypeInput,
                 name: str = "GaussianKDE"):
        """Gaussian Kernel Density Estimation using Silverman's rule of thumb

        Args:
            data: Data points to build a kernel around
            bandwidth: sigmas for the covariance matrix of the multivariate gaussian
            obs:
            name: Name of the PDF
        """
        dtype = zfit.settings.ztypes.float
        if isinstance(data, zfit.core.interfaces.ZfitData):

            raise WorkInProgressError("Currently, no dataset supported yet")
            # size = data.nevents
            # dims = data.n_obs
            # with data.
            # data = data.value()
            # if data.weights is not None:

        else:
            if not isinstance(data, tf.Tensor):
                data = ztf.convert_to_tensor(value=data)
            data = ztf.to_real(data)

            shape_data = tf.shape(data)
            size = tf.cast(shape_data[0], dtype=dtype)
            dims = tf.cast(shape_data[-1], dtype=dtype)
        bandwidth = convert_to_container(bandwidth)

        # Bandwidth definition, use silverman's rule of thumb for nd
        def reshaped_kerner_factory():
            cov = tf.linalg.diag([
                tf.square((4. / (dims + 2.))**(1 / (dims + 4)) *
                          size**(-1 / (dims + 4)) * s) for s in bandwidth
            ])
            # kernel prob output shape: (n,)
            kernel = tfd.MultivariateNormalFullCovariance(
                loc=data, covariance_matrix=cov)
            return tfd.Independent(kernel)

        # reshaped_kernel = kernel

        probs = tf.broadcast_to(1 / size, shape=(tf.cast(size, tf.int32), ))
        categorical = tfd.Categorical(
            probs=probs)  # no grad -> no need to recreate
        dist_kwargs = lambda: dict(mixture_distribution=categorical,
                                   components_distribution=
                                   reshaped_kerner_factory())
        distribution = tfd.MixtureSameFamily
        # TODO lambda for params
        params = OrderedDict(
            (f"bandwidth_{i}", h) for i, h in enumerate(bandwidth))
        super().__init__(distribution=distribution,
                         dist_params={},
                         dist_kwargs=dist_kwargs,
                         params=params,
                         obs=obs,
                         name=name)
示例#13
0
def normalization_nograd(func,
                         n_axes,
                         batch_size,
                         num_batches,
                         dtype,
                         space,
                         x=None,
                         shape_after=()):
    upper, lower = space.limits
    lower = ztf.convert_to_tensor(lower, dtype=dtype)
    upper = ztf.convert_to_tensor(upper, dtype=dtype)

    def body(batch_num, mean):
        start_idx = batch_num * batch_size
        end_idx = start_idx + batch_size
        indices = tf.range(start_idx, end_idx, dtype=tf.int32)
        samples_normed = tfp.mcmc.sample_halton_sequence(
            n_axes,
            # num_results=batch_size,
            sequence_indices=indices,
            dtype=dtype,
            randomized=False)
        # halton_sample = tf.random_uniform(shape=(n_axes, batch_size), dtype=dtype)
        samples_normed.set_shape((batch_size, n_axes))
        samples_normed = tf.expand_dims(samples_normed, axis=0)
        samples = samples_normed * (upper - lower) + lower
        func_vals = func(samples)
        if shape_after == ():
            reduce_axis = None
        else:
            reduce_axis = 1
            if len(func_vals.shape) == 1:
                func_vals = tf.expand_dims(func_vals, -1)
        batch_mean = tf.reduce_mean(func_vals,
                                    axis=reduce_axis)  # if there are gradients
        # batch_mean = tf.reduce_mean(sample)
        # batch_mean = tf.guarantee_const(batch_mean)
        # with tf.control_dependencies([batch_mean]):
        err_weight = 1 / tf.to_double(batch_num + 1)
        # err_weight /= err_weight + 1
        # print_op = tf.print(batch_mean)
        do_print = False
        if do_print:
            deps = [tf.print(batch_num + 1)]
        else:
            deps = []
        with tf.control_dependencies(deps):
            return batch_num + 1, mean + err_weight * (batch_mean - mean)

    cond = lambda batch_num, _: batch_num < num_batches

    initial_mean = tf.constant(0, shape=shape_after, dtype=dtype)
    initial_body_args = (0, initial_mean)
    _, final_mean = tf.while_loop(cond,
                                  body,
                                  initial_body_args,
                                  parallel_iterations=1,
                                  swap_memory=False,
                                  back_prop=True)
    # def normalization_grad(x):
    return final_mean
示例#14
0
文件: parameter.py 项目: simonUU/zfit
 def step_size(self, value):
     if value is not None:
         value = ztf.convert_to_tensor(value, preferred_dtype=ztypes.float)
         value = tf.cast(value, dtype=ztypes.float)
     self._step_size = value
示例#15
0
    return mu2, sigma2


def create_params3(nameadd=""):
    mu3 = zfit.Parameter("mu35" + nameadd, ztf.to_real(mu_true) - 0.2, mu_true - 1., mu_true + 1.)
    sigma3 = zfit.Parameter("sigma35" + nameadd, ztf.to_real(sigma_true) - 0.3, sigma_true - 2., sigma_true + 2.)
    yield3 = zfit.Parameter("yield35" + nameadd, yield_true + 300, 0, yield_true + 20000)
    return mu3, sigma3, yield3


obs1 = 'obs1'

mu_constr = [1.6, 0.2]  # mu, sigma
sigma_constr = [3.8, 0.2]
constr = lambda: [mu_constr[1], sigma_constr[1]]
constr_tf = lambda: ztf.convert_to_tensor(constr())
covariance = lambda: np.array([[mu_constr[1] ** 0.5, -0.05], [-0.05, sigma_constr[1] ** 0.5]])
covariance_tf = lambda: ztf.convert_to_tensor(covariance())


def create_gauss1():
    mu, sigma = create_params1()
    return Gauss(mu, sigma, obs=obs1, name="gaussian1"), mu, sigma


def create_gauss2():
    mu, sigma = create_params2()
    return Gauss(mu, sigma, obs=obs1, name="gaussian2"), mu, sigma


def create_gauss3ext():