Beispiel #1
0
def lstsq_laplace_factor_approx(
        model_approx: EPMeanField,
        factor: Factor,
        delta: float = 0.5,
        opt_kws: Optional[Dict[str, Any]] = None):
    """
    """
    factor_approx = model_approx.factor_approximation(factor)

    opt = LeastSquaresOpt(
        factor_approx, **({} if opt_kws is None else opt_kws))

    mode, covar, result = opt.least_squares()
    message = (
        "optimise.lsq_sq_laplace_factor_approx: "
        f"nfev={result.nfev}, njev={result.njev}, "
        f"optimality={result.optimality}, "
        f"cost={result.cost}, "
        f"status={result.status}, message={result.message}",)
    status = Status(result.success, message)

    model_dist = MeanField({
        v: factor_approx.factor_dist[v].from_mode(
            mode[v],
            covar.get(v))
        for v in mode
    })

    projection, status = factor_approx.project(
        model_dist, delta=delta, status=status)

    return model_approx.project(projection, status=status)
Beispiel #2
0
def laplace_factor_approx(
        model_approx: EPMeanField,
        factor: Factor,
        delta: float = 1.,
        status: Status = Status(),
        opt_kws: Optional[Dict[str, Any]] = None
):
    opt_kws = {} if opt_kws is None else opt_kws
    factor_approx = model_approx.factor_approximation(factor)
    res = find_factor_mode(
        factor_approx,
        return_cov=True,
        status=status,
        **opt_kws
    )

    model_dist = factor_approx.model_dist.project_mode(res)
    projection, status = factor_approx.project(
        model_dist,
        delta=delta,
        status=res.status
    )

    new_approx, status = model_approx.project(
        projection, status=status)

    return new_approx, status
Beispiel #3
0
def project_model(model_approx: EPMeanField,
                  factor: Factor,
                  sampler: AbstractSampler,
                  delta: float = 0.5,
                  **kwargs) -> Tuple[EPMeanField, Status]:
    """
    """
    factor_approx = model_approx.factor_approximation(factor)
    sample = sampler(factor_approx, **kwargs)
    model_dist = project_factor_approx_sample(factor_approx, sample)
    projection, status = factor_approx.project(model_dist, delta=delta)
    return model_approx.project(projection, status=status)
Beispiel #4
0
    def optimise(
            self,
            factor: Factor,
            model_approx: EPMeanField,
            status: Status = Status(),
    ) -> Tuple[EPMeanField, Status]:
        delta = self.deltas[factor]
        sample_kws = self.sample_kws[factor]

        factor_approx = model_approx.factor_approximation(factor)
        sample = self(factor_approx, **sample_kws)
        model_dist = project_factor_approx_sample(factor_approx, sample)
        projection, status = factor_approx.project(model_dist, delta=delta)
        return model_approx.project(projection, status=status)
Beispiel #5
0
    def optimise(
            self,
            factor: Factor,
            model_approx: EPMeanField,
            status: Optional[Status] = Status(),
    ) -> Tuple[EPMeanField, Status]:

        whiten = self.transforms[factor]
        opt_kws = self.opt_kws[factor]
        start = self.initial_values.get(factor)

        factor_approx = model_approx.factor_approximation(factor)
        opt = OptFactor.from_approx(factor_approx, transform=whiten)
        res = opt.maximise(start, status=status, **opt_kws)

        # Calculate covariance of deterministic values
        # TODO: estimate this Jacobian using Broyden's method
        # https://en.wikipedia.org/wiki/Broyden%27s_method
        value = factor_approx.factor(res.mode)
        res.mode.update(value.deterministic_values)
        jacobian = factor_approx.factor.jacobian(res.mode, opt.free_vars)
        update_det_cov(res, jacobian)

        self.transforms[factor] = self.transform_cls.from_dense(
            res.full_hess_inv)

        # Project Laplace's approximation
        new_model_dist = factor_approx.model_dist.from_mode_covariance(
            res.mode, res.hess_inv, res.log_norm)
        return self.update_model_approx(new_model_dist, factor_approx,
                                        model_approx, status)
Beispiel #6
0
 def mean_field_approximation(self) -> EPMeanField:
     """
     Returns a EPMeanField of the factor graph
     """
     return EPMeanField.from_approx_dists(self.graph, self.message_dict)