-
Notifications
You must be signed in to change notification settings - Fork 6
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
Modify how losses are computed in a multi-replicas hyperopt #2145
base: master
Are you sure you want to change the base?
Changes from all commits
628e455
98a3dc1
a6c8bda
4e398cf
983f2f2
14c202a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,7 +44,7 @@ | |
log = logging.getLogger(__name__) | ||
|
||
|
||
def _average_best(fold_losses: np.ndarray, proportion: float = 0.9, axis: int = 0) -> float: | ||
def _average_best(fold_losses: np.ndarray, proportion: float = 0.05, axis: int = 0) -> float: | ||
""" | ||
Compute the average of the input array along the specified axis, among the best `proportion` | ||
of replicas. | ||
|
@@ -72,7 +72,7 @@ def _average_best(fold_losses: np.ndarray, proportion: float = 0.9, axis: int = | |
return _average(best_losses, axis=axis) | ||
|
||
|
||
def _average(fold_losses: np.ndarray, axis: int = 0) -> float: | ||
def _average(fold_losses: np.ndarray, axis: int = 0, **kwargs) -> float: | ||
""" | ||
Compute the average of the input array along the specified axis. | ||
|
||
|
@@ -90,7 +90,7 @@ def _average(fold_losses: np.ndarray, axis: int = 0) -> float: | |
return np.average(fold_losses, axis=axis).item() | ||
|
||
|
||
def _best_worst(fold_losses: np.ndarray, axis: int = 0) -> float: | ||
def _best_worst(fold_losses: np.ndarray, axis: int = 0, **kwargs) -> float: | ||
""" | ||
Compute the maximum value of the input array along the specified axis. | ||
|
||
|
@@ -108,7 +108,7 @@ def _best_worst(fold_losses: np.ndarray, axis: int = 0) -> float: | |
return np.max(fold_losses, axis=axis).item() | ||
|
||
|
||
def _std(fold_losses: np.ndarray, axis: int = 0) -> float: | ||
def _std(fold_losses: np.ndarray, axis: int = 0, **kwargs) -> float: | ||
""" | ||
Compute the standard deviation of the input array along the specified axis. | ||
|
||
|
@@ -195,7 +195,8 @@ def __init__( | |
def compute_loss( | ||
self, | ||
penalties: dict[str, np.ndarray], | ||
experimental_loss: np.ndarray, | ||
validation_loss: np.ndarray, | ||
kfold_loss: np.ndarray, | ||
pdf_object: N3PDF, | ||
experimental_data: list[DataGroupSpec], | ||
fold_idx: int = 0, | ||
|
@@ -250,20 +251,31 @@ def compute_loss( | |
|
||
# update hyperopt metrics | ||
# these are saved in the phi_vector and chi2_matrix attributes, excluding penalties | ||
self._save_hyperopt_metrics(phi_per_fold, experimental_loss, penalties, fold_idx) | ||
self._save_hyperopt_metrics(phi_per_fold, kfold_loss, penalties, fold_idx) | ||
|
||
# Prepare the output loss, including penalties if necessary | ||
if self._penalties_in_loss: | ||
# include penalties to experimental loss | ||
experimental_loss += sum(penalties.values()) | ||
kfold_loss += sum(penalties.values()) | ||
|
||
# add penalties to phi in the form of a sum of per-replicas averages | ||
phi_per_fold += sum(np.mean(penalty) for penalty in penalties.values()) | ||
|
||
# define loss for hyperopt according to the chosen loss_type | ||
if self.loss_type == "chi2": | ||
# calculate statistics of chi2 over replicas for a given k-fold | ||
loss = self.reduce_over_replicas(experimental_loss) | ||
# calculate statistics of chi2 over replicas for a given k-fold_statistic | ||
|
||
# Construct the final loss as a sum of | ||
# 1. The validation chi2 | ||
# 2. The distance to 2 for the kfold chi2 | ||
# If a proportion allow as a keyword argument, use 80% and 10% | ||
# as a proxy of | ||
# "80% of the replicas should be good, but only a small % has to cover the folds" | ||
# The values of 80% and 10% are completely empirical and should be investigated further | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on a similar line maybe we can pass the values from the runcard? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tbh, it would be a good idea. It was added quickly there for the sake of the meeting, but it would be good to have it as an input parameter. |
||
|
||
validation_loss_average = self.reduce_over_replicas(validation_loss, proportion=0.8) | ||
kfold_loss_average = self.reduce_over_replicas(kfold_loss, proportion=0.1) | ||
loss = validation_loss_average + (max(kfold_loss_average, 2.0) - 2.0) | ||
elif self.loss_type == "phi2": | ||
loss = phi_per_fold**2 | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure we do want to have a default value for
proportion
?