Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new prediction function that does not return the error/variance #49

Merged
merged 9 commits into from
Aug 12, 2024
9 changes: 8 additions & 1 deletion docs/source/getting_started/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,15 @@ model.
Which shows that the emulator can predict the model with
high accuracy.

Note that the `predict_values()` method also returns the estimated
variance of the values it returns. In cases where the variance is
not required, the method `predict_values_no_error()` can instead be
used. In some cases, this latter function can be much faster than the
one additionally returning the variances.


.. image:: predict_vs_model.png

This covers the most basic way to use SWIFT-Emulator and
should give a good baseline for using some of the
additional features it offers.
additional features it offers.
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ It includes functionality to:
SWIFT that processed by VELOCIraptor and the swift-pipeline.

Information about `SWIFT` can be found
`here <http://swift.dur.ac.uk/>`_, Information about
`here <http://www.swiftsim.com/>`_, Information about
`VELOCIraptor` can be found
`here <https://velociraptor-stf.readthedocs.io/en/latest/>`_
and tnformation about the `SWIFT-pipeline` can be found
Expand Down
54 changes: 51 additions & 3 deletions swiftemulator/emulators/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ def predict_values(
self, independent: np.array, model_parameters: Dict[str, float]
) -> np.array:
"""
Predict values from the trained emulator contained within this object.
Predict values and the associated variance from the trained emulator contained
within this object.

Parameters
----------
Expand Down Expand Up @@ -124,6 +125,52 @@ def predict_values(

raise NotImplementedError

def predict_values_no_error(
self, independent: np.array, model_parameters: Dict[str, float]
) -> np.array:
"""
Predict values from the trained emulator contained within this object.
In cases where the error estimates are not required, this method is
significantly faster than predict_values().

Parameters
----------

independent, np.array
Independent continuous variables to evaluate the emulator
at. If the emulator is discrete, these are only allowed to be
the discrete independent variables that the emulator was trained at
(disregarding the additional 'independent' model parameters, below.)

model_parameters: Dict[str, float]
The point in model parameter space to create predicted
values at.

Returns
-------

dependent_predictions, np.array
Array of predictions, if the emulator is a function f, these
are the predicted values of f(independent) evaluted at the position
of the input ``model_parameters``.

Raises
------

AttributeError
When the model has not been trained before trying to make a
prediction, or when attempting to evaluate the model at
disallowed independent variables.
"""

if self.emulator is None:
raise AttributeError(
"Please train the emulator with fit_model before attempting "
"to make predictions."
)

raise NotImplementedError

def interactive_plot(
self,
x: np.array,
Expand All @@ -140,10 +187,10 @@ def interactive_plot(
the parameter values will be used instead. If no reference data is
passed to be overplotted then the plot will display a line which
corresponds to the predictions for the initial parameter values.

Parameters
----------

x: np.array
Array of data for which the emulator should make predictions.

Expand All @@ -164,6 +211,7 @@ def interactive_plot(
Array containing y-values of reference data to plot.
Must be the same shape as x_data
"""

import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

Expand Down
71 changes: 69 additions & 2 deletions swiftemulator/emulators/gaussian_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ def predict_values(
self, independent: np.array, model_parameters: Dict[str, float]
) -> np.array:
"""
Predict values from the trained emulator contained within this object.
Predict values and the associated variance from the trained emulator
contained within this object.

Parameters
----------
Expand All @@ -253,7 +254,14 @@ def predict_values(
of the input model_parameters.

dependent_prediction_errors, np.array
Errors on the model predictions.
Errors (variances) on the model predictions.

Raises
------

AttributeError
When the model has not been trained before trying to make a
prediction.
"""

if self.emulator is None:
Expand All @@ -279,3 +287,62 @@ def predict_values(
)

return model, errors

def predict_values_no_error(
self, independent: np.array, model_parameters: Dict[str, float]
) -> np.array:
"""
Predict values from the trained emulator contained within this object.
In cases where the error estimates are not required, this method is
significantly faster than predict_values().

Parameters
----------

independent, np.array
Independent continuous variables to evaluate the emulator
at.

model_parameters: Dict[str, float]
The point in model parameter space to create predicted
values at.

Returns
-------

dependent_predictions, np.array
Array of predictions, if the emulator is a function f, these
are the predicted values of f(independent) evaluted at the position
of the input model_parameters.

Raises
------

AttributeError
When the model has not been trained before trying to make a
prediction.
"""

if self.emulator is None:
raise AttributeError(
"Please train the emulator with fit_model before attempting "
"to make predictions."
)

model_parameter_array = np.array(
[model_parameters[parameter] for parameter in self.parameter_order]
)

t = np.empty(
(len(independent), len(model_parameter_array) + 1), dtype=np.float32
)

for line, value in enumerate(independent):
t[line][0] = value
t[line][1:] = model_parameter_array

model = self.emulator.predict(
y=self.dependent_variables, t=t, return_cov=False, return_var=False
)

return model
97 changes: 96 additions & 1 deletion swiftemulator/emulators/gaussian_process_bins.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ def predict_values(
self, independent: np.array, model_parameters: Dict[str, float]
) -> np.array:
"""
Predict values from the trained emulator contained within this object.
Predict values and the associated variance from the trained emulator contained
within this object.

Parameters
----------
Expand Down Expand Up @@ -365,3 +366,97 @@ def predict_values(
np.array(dependent_predictions),
np.array(dependent_prediction_errors),
)

def predict_values_no_error(
self, independent: np.array, model_parameters: Dict[str, float]
) -> np.array:
"""
Predict values from the trained emulator contained within this object.
In cases where the error estimates are not required, this method is
significantly faster than predict_values().

Parameters
----------

independent, np.array
Independent continuous variables to evaluate the emulator
at. If the emulator is discrete, these are only allowed to be
the discrete independent variables that the emulator was trained at
(disregarding the additional 'independent' model parameters, below).
These can be found in this object in the ``bin_centers`` attribute.

model_parameters: Dict[str, float]
The point in model parameter space to create predicted
values at.

Returns
-------

dependent_predictions, np.array
Array of predictions, if the emulator is a function f, these
are the predicted values of f(independent) evaluted at the position
of the input ``model_parameters``.

Raises
------

AttributeError
When the model has not been trained before trying to make a
prediction, or when attempting to evaluate the model at
disallowed independent variables.
"""

if self.bin_gaussian_process is None:
raise AttributeError(
"Please train the emulator with fit_model before attempting "
"to make predictions."
)

# First calculate which indices in bin_centers (and hence
# bin_gaussian_processes) correspond to the requested ``independent``
# variables.

array_centers = np.array(self.bin_centers)
gpe_ordering = []

for requested_independent_variable in independent:
try:
gpe_ordering.append(
np.where(array_centers == requested_independent_variable)[0][0]
)
except IndexError:
raise AttributeError(
f"Requested independent variable {independent} not valid, ",
f"this instance of GPE Bins is only valid at {array_centers}.",
)

model_parameter_array = np.array(
[model_parameters[parameter] for parameter in self.parameter_order]
)

# George must predict a value for more than one point at a time, so
# generate two fake points either side of the one of interest.
model_parameter_array_sample = np.append(
0.98 * model_parameter_array, model_parameter_array
)
model_parameter_array_sample = np.append(
model_parameter_array_sample, 1.02 * model_parameter_array
).reshape(3, len(model_parameter_array))

dependent_predictions = []

for emulator_index in gpe_ordering:
gp = self.bin_gaussian_process[emulator_index]
model_values = self.bin_model_values[emulator_index]

model = gp.predict(
y=model_values["dependent"],
t=model_parameter_array_sample,
return_cov=False,
return_var=False,
)

# Remove fake points required to ensure george returns a prediction.
dependent_predictions.append(model[1])

return np.array(dependent_predictions)
Loading
Loading