core.result.Result
core.result.Result(file_name=None, dictionary=None)A dataset class to hold a collection of samples, implementing I/O, importance sampling, and unconditional flow training.
Attributes: samples : pd.Dataframe Contains parameter samples, as well as (possibly) log_prob, log_likelihood, weights, log_prior, delta_log_prob_target. domain : Domain Should be implemented in a subclass. prior : PriorDict Should be implemented in a subclass. likelihood : Likelihood Should be implemented in a subclass. context : dict Context data from which the samples were produced (e.g., strain data, ASDs). metadata : dict event_metadata : dict log_evidence : float log_evidence_std : float (property) effective_sample_size, n_eff : float (property) sample_efficiency : float (property)
Attributes
Methods
| Name | Description |
|---|---|
| get_all_injection_credible_levels | Get credible levels for all parameters. |
| get_injection_credible_level | Get the credible level of the injected parameter. |
| importance_sample | Calculate importance weights for samples. |
| merge | Merge several Result instances into one. Check that they are compatible, |
| parameter_subset | Return a new object of the same type, with only a subset of parameters. Drops |
| plot_corner | Generate a corner plot of the samples. |
| plot_log_probs | Make a scatter plot of the target versus proposal log probabilities. For the |
| plot_weights | Make a scatter plot of samples weights vs log proposal. |
| print_summary | Display the number of samples, and (if importance sampling is complete) the log |
| rejection_sample | Generate unweighted posterior samples from weighted ones via rejection sampling. |
| reset_event | Set the Result context and event_metadata based on an EventDataset. |
| sampling_importance_resampling | Generate unweighted posterior samples from weighted ones. New |
| split | Split the Result into a set of smaller results. The samples are evenly divided |
| train_unconditional_flow | Train an unconditional flow to represent the distribution of self.samples. |
get_all_injection_credible_levels
core.result.Result.get_all_injection_credible_levels(keys=None, weighted=False)Get credible levels for all parameters.
Adapted from Bilby.
Parameters
keys: list, optional A list of keys for which return the credible levels, if None, defaults to search_parameter_keys weighted: bool, optional Whether to use sample weights in calculating credible level.
Returns
credible_levels: dict The credible levels at which the injected parameters are found.
get_injection_credible_level
core.result.Result.get_injection_credible_level(parameter, weighted=False)Get the credible level of the injected parameter.
Calculated as CDF(injection value).
Adapted from Bilby.
Parameters
parameter: str Parameter to get credible level for weighted: bool, optional Whether to use sample weights in calculating credible level.
Returns
float: credible level
importance_sample
core.result.Result.importance_sample(num_processes=1, **likelihood_kwargs)Calculate importance weights for samples.
Importance sampling starts with samples have been generated from a proposal distribution q(theta), in this case a neural network model. Certain networks (i.e., non-GNPE) also provide the log probability of each sample, which is required for importance sampling.
Given the proposal, we re-weight samples according to the (un-normalized) target distribution, which we take to be the likelihood L(theta) times the prior pi(theta). This gives sample weights
w(theta) ~ pi(theta) L(theta) / q(theta),
where the overall normalization does not matter (and we take to have mean 1). Since q(theta) enters this expression, importance sampling is only possible when we know the log probability of each sample.
As byproducts, this method also estimates the evidence and effective sample size of the importance sampled points.
This method modifies the samples pd.DataFrame in-place, adding new columns for log_likelihood, log_prior, and weights. It also stores the log_evidence as an attribute.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| num_processes | int | Number of parallel processes to use when calculating likelihoods. (This is the most expensive task.) | 1 |
| likelihood_kwargs | dict | kwargs that are forwarded to the likelihood constructor. E.g., options for marginalization. | {} |
merge
core.result.Result.merge(parts)Merge several Result instances into one. Check that they are compatible, in the sense of having the same metadata. Finally, calculate a new log evidence for the combined result.
This is useful when recombining separate importance sampling jobs.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| parts | list[Result] | List of sub-Results to be combined. | required |
Returns
| Name | Type | Description |
|---|---|---|
| Combined Result. |
parameter_subset
core.result.Result.parameter_subset(parameters)Return a new object of the same type, with only a subset of parameters. Drops all other columns in samples DataFrame as well (e.g., log_prob, weights).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| parameters | list | List of parameters to keep. | required |
Returns
| Name | Type | Description |
|---|---|---|
| Result |
plot_corner
core.result.Result.plot_corner(parameters=None, filename='corner.pdf', **kwargs)Generate a corner plot of the samples.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| parameters | list[str] | List of parameters to include. If None, include all parameters. (Default: None) | None |
| filename | str | Where to save samples. | 'corner.pdf' |
Other Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| legend_font_size | Font size of the legend. | required |
plot_log_probs
core.result.Result.plot_log_probs(filename='log_probs.png')Make a scatter plot of the target versus proposal log probabilities. For the target, subtract off the log evidence.
plot_weights
core.result.Result.plot_weights(filename='weights.png')Make a scatter plot of samples weights vs log proposal.
print_summary
core.result.Result.print_summary()Display the number of samples, and (if importance sampling is complete) the log evidence and number of effective samples.
rejection_sample
core.result.Result.rejection_sample(
max_samples_per_draw=1,
clip_weights=False,
random_state=None,
)Generate unweighted posterior samples from weighted ones via rejection sampling.
Each original sample contributes at most max_samples_per_draw copies to the output, so the result avoids the excessive duplication that :meth:sampling_importance_resampling can produce for high-weight samples.
Algorithm (unbiased, maximum efficiency)
The weights are first scaled so that the largest weight equals max_samples_per_draw. Each sample i then contributes
floor(w_scaled[i])copies deterministically (integer part), and- one additional copy with probability
w_scaled[i] - floor(w_scaled[i])(fractional part, a single Bernoulli draw).
The expected number of copies of sample i is therefore exactly w_scaled[i] ∝ w[i], which guarantees an unbiased representation of the posterior. Using the integer part deterministically (rather than rounding stochastically) maximises the expected total number of output samples for a given max_samples_per_draw.
Optional weight clipping
When clip_weights=True, the ceil(sqrt(N)) largest weights are replaced by their mean and the weights are re-normalized to mean 1 before rejection sampling. This number of clips is the theoretically optimal choice that yields asymptotically unbiased results [1]_. Using the mean (rather than the minimum) of the clipped group preserves their total weight, which minimises the bias introduced by clipping. The net effect is reduced weight variance and a larger expected number of output samples.
If the samples DataFrame has no weights column the samples are already unweighted and are returned unchanged.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| max_samples_per_draw | int | Maximum number of copies any single input sample may contribute to the output. Default is 1 (standard rejection sampling, no duplicates). | 1 |
| clip_weights | bool | Whether to clip the ceil(sqrt(N)) largest weights to their mean before rejection sampling. Default is False. |
False |
| random_state | int or None | Seed for the random number generator, for reproducibility. | None |
Returns
| Name | Type | Description |
|---|---|---|
| pd.DataFrame | Unweighted samples (the weights column is dropped). |
References
.. [1] Elvira et al., “A Comparison Of Clipping Strategies For Importance Sampling” https://ieeexplore.ieee.org/document/8450722
reset_event
core.result.Result.reset_event(event_dataset)Set the Result context and event_metadata based on an EventDataset.
If these attributes already exist, perform a comparison to check for changes. Update relevant objects appropriately. Note that setting context and event_metadata attributes directly would not perform these additional checks and updates.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| event_dataset | New event to be used for importance sampling. | required |
sampling_importance_resampling
core.result.Result.sampling_importance_resampling(
num_samples=None,
random_state=None,
)Generate unweighted posterior samples from weighted ones. New samples are sampled with probability proportional to the sample weight. Resampling is done with replacement, until the desired number of unweighted samples is obtained.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| num_samples | int | Number of samples to resample. | None |
| random_state | int or None | Sampling seed. | None |
Returns
| Name | Type | Description |
|---|---|---|
| pd.Dataframe | Unweighted samples |
split
core.result.Result.split(num_parts)Split the Result into a set of smaller results. The samples are evenly divided among the sub-results. Additional information (metadata, context, etc.) are copied into each.
This is useful for splitting expensive tasks such as importance sampling across multiple jobs.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| num_parts | int | The number of parts to split the Result across. | required |
Returns
| Name | Type | Description |
|---|---|---|
| list of sub-Results. |
train_unconditional_flow
core.result.Result.train_unconditional_flow(
parameters,
nde_settings,
train_dir=None,
threshold_std=np.inf,
)Train an unconditional flow to represent the distribution of self.samples.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| parameters | list | List of parameters over which to train the flow. Can be a subset of the existing parameters. | required |
| nde_settings | dict | Configuration settings for the neural density estimator. | required |
| train_dir | Optional[str] | Where to save the output of network training, e.g., logs, checkpoints. If not provide, a temporary directory is used. | None |
| threshold_std | Optional[float] | Drop samples more than threshold_std standard deviations away from the mean (in any parameter) before training the flow. This is meant to remove outlier samples. | np.inf |
Returns
| Name | Type | Description |
|---|---|---|
| PosteriorModel |