Beispiel #1
0
    def append_simulations(
        self,
        theta: Tensor,
        x: Tensor,
        from_round: int = 0,
    ) -> "RatioEstimator":
        r"""
        Store parameters and simulation outputs to use them for later training.

        Data are stored as entries in lists for each type of variable (parameter/data).

        Stores $\theta$, $x$, prior_masks (indicating if simulations are coming from the
        prior or not) and an index indicating which round the batch of simulations came
        from.

        Args:
            theta: Parameter sets.
            x: Simulation outputs.
            from_round: Which round the data stemmed from. Round 0 means from the prior.
                With default settings, this is not used at all for `SNRE`. Only when
                the user later on requests `.train(discard_prior_samples=True)`, we
                use these indices to find which training data stemmed from the prior.
        Returns:
            NeuralInference object (returned so that this function is chainable).
        """

        validate_theta_and_x(theta, x)

        self._theta_roundwise.append(theta)
        self._x_roundwise.append(x)
        self._prior_masks.append(
            mask_sims_from_prior(int(from_round), theta.size(0)))
        self._data_round_index.append(int(from_round))

        return self
Beispiel #2
0
    def append_simulations(
        self, theta: Tensor, x: Tensor, proposal: Optional[Any] = None,
    ) -> "PosteriorEstimator":
        r"""
        Store parameters and simulation outputs to use them for later training.

        Data are stored as entries in lists for each type of variable (parameter/data).

        Stores $\theta$, $x$, prior_masks (indicating if simulations are coming from the
        prior or not) and an index indicating which round the batch of simulations came
        from.

        Args:
            theta: Parameter sets.
            x: Simulation outputs.
            proposal: The distribution that the parameters $\theta$ were sampled from.
                Pass `None` if the parameters were sampled from the prior. If not
                `None`, it will trigger a different loss-function.

        Returns:
            NeuralInference object (returned so that this function is chainable).
        """

        validate_theta_and_x(theta, x)
        self._check_proposal(proposal)

        if (
            proposal is None
            or proposal is self._prior
            or (
                isinstance(proposal, RestrictedPrior) and proposal._prior is self._prior
            )
        ):
            # The `_data_round_index` will later be used to infer if one should train
            # with MLE loss or with atomic loss (see, in `train()`:
            # self._round = max(self._data_round_index))
            self._data_round_index.append(0)
            self._prior_masks.append(mask_sims_from_prior(0, theta.size(0)))
        else:
            if not self._data_round_index:
                # This catches a pretty specific case: if, in the first round, one
                # passes data that does not come from the prior.
                self._data_round_index.append(1)
            else:
                self._data_round_index.append(max(self._data_round_index) + 1)
            self._prior_masks.append(mask_sims_from_prior(1, theta.size(0)))

        self._theta_roundwise.append(theta)
        self._x_roundwise.append(x)
        self._proposal_roundwise.append(proposal)

        return self
Beispiel #3
0
    def append_simulations(
        self,
        theta: Tensor,
        x: Tensor,
        proposal: Optional[Any] = None,
    ) -> "PosteriorEstimator":
        r"""
        Store parameters and simulation outputs to use them for later training.

        Data are stored as entries in lists for each type of variable (parameter/data).

        Stores $\theta$, $x$, prior_masks (indicating if simulations are coming from the
        prior or not) and an index indicating which round the batch of simulations came
        from.

        Args:
            theta: Parameter sets.
            x: Simulation outputs.
            proposal: The distribution that the parameters $\theta$ were sampled from.
                Pass `None` if the parameters were sampled from the prior. If not
                `None`, it will trigger a different loss-function.

        Returns:
            NeuralInference object (returned so that this function is chainable).
        """

        validate_theta_and_x(theta, x)
        self._check_proposal(proposal)
        self._prior_masks = [None for _ in self._prior_masks]
        if (proposal is None or proposal is self._prior
                or (isinstance(proposal, RestrictedPrior)
                    and proposal._prior is self._prior)):
            # The `_data_round_index` will later be used to infer if one should train
            # with MLE loss or with atomic loss (see, in `train()`:
            # self._round = max(self._data_round_index))
            self._data_round_index.append(0)
            self._prior_masks.append(mask_sims_from_prior(0, theta.size(0)))
        else:
            if not self._data_round_index:
                # This catches a pretty specific case: if, in the first round, one
                # passes data that does not come from the prior.
                self._data_round_index.append(1)
            else:
                self._data_round_index.append(max(self._data_round_index) + 1)
            self._prior_masks.append(mask_sims_from_prior(1, theta.size(0)))

        # Delete old samples as we do not want to use them
        self._theta_roundwise = [None for _ in self._theta_roundwise]
        self._x_roundwise = [None for _ in self._x_roundwise]
        self._proposal_roundwise = [None for _ in self._proposal_roundwise]

        self._theta_roundwise.append(theta)
        self._x_roundwise.append(x)
        self._proposal_roundwise.append(proposal)

        if self._prior is None or isinstance(self._prior, ImproperEmpirical):
            if proposal is not None:
                raise ValueError(
                    "You had not passed a prior at initialization, but now you "
                    "passed a proposal. If you want to run multi-round SNPE, you have "
                    "to specify a prior (set the `.prior` argument or re-initialize "
                    "the object with a prior distribution). If the samples you passed "
                    "to `append_simulations()` were sampled from the prior, you can "
                    "run single-round inference with "
                    "`append_simulations(..., proposal=None)`.")
            theta_prior = self.get_simulations()[0]
            self._prior = ImproperEmpirical(theta_prior,
                                            ones(theta_prior.shape[0]))

        return self