Cross-validation#
PyHopper provides an easy way to perform cross-validation in the objective function with minimal code changes,
while at the same time use its pyhopper.cancellers API to discontinue evaluations if candidates turn our unpromising after the first cross-validation step.
In particular, the pyhopper.wrap_n_times() wrapper function has the optional argument pass_index_arg that will pass an additional int argument to the the wrapped function indicating which
of the n steps the current function call corresponds to.
This additional argument can then be used to perform the training-validation split, which reduces overfitting as we do not rely on a single split while at the same time make sure each candidate is evaluated with the same splits.
import pyhopper
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
def noisy_objective(param, eval_index):
print(f"x={param['x']}, eval_index={eval_index}")
X, y = load_iris(return_X_y=True)
X_train, X_val, y_train, y_val = train_test_split(
X, y, test_size=0.33, random_state=eval_index # use eval_index as random state
)
# ... train on X_train, y_train
# ... validate on X_val, y_val
return val_accuracy
search = pyhopper.Search(
{
"x": pyhopper.float(),
}
)
search.run(
pyhopper.wrap_n_times(noisy_objective, n=3, yield_after=0, pass_index_arg=True),
steps=3,
canceller=pyhopper.pruners.QuantilePruner(0.8),
quiet=True,
)
> x=-0.2101340164769267, eval_index=0
> x=-0.2101340164769267, eval_index=1
> x=-0.2101340164769267, eval_index=2
> x=-0.0846185419082141, eval_index=0
> x=-0.0846185419082141, eval_index=1
> x=-0.0846185419082141, eval_index=2