I have a set of choices A. I would like to get back a subset of choices A. Is this possible with Hyperopt?
input:
{
'A': hp.choice('A', [0, 1, 2, 3])
}
output:
{
'A': [0, 2]
}
No, but if you specifically want that functionality, there are multiple ways to do so.
You can define a new expression and add it to existing hyperopt parameter expressions as given in the documentation. For example, in your case, you can do:
import hyperopt.pyll
from hyperopt.pyll import scope
from hyperopt.pyll.stochastic import sample
# Add a new method as you want
@scope.define
def foo(choices, num_choices):
return np.random.choice(choices, size=num_choices, replace=False)
choices = [1,2,3,4]
# Define the space like below and use in fmin
space = scope.foo(choices, 2)
# Call this multiple times to see how space behaves
print(sample(space))
See the documention of numpy.random.choice to know how that works.
Note:
foo
method will return a subset of choices (in a numpy array). So make sure that in your objective function, you are using the internal multiple values like x[0], x[1], ...
etc.scope.undefine(foo)
in the end of your code, or else you will have to restart your terminal / kernel each time before running the code. If you are allowed to choose two values with replacement (that means that sometimes both values in the subset will be same. This is the reason we used replace=False
in point 1), then the following can be done:
choices = [1,2,3,4]
space = [hp.choice('c1', choices),
hp.choice('c2', choices)]
Then in your objective function, you can access your two values as x[0]
, x[1]
.
But from your question, it seems like you want to have the sub-choices and that implies without replacement, so a sub-set of [1,1]
or [2,2]
etc. is invalid. In that case, you should use the Trials
object to define status
.
A sample program for point 2 is below:
from hyperopt import fmin, tpe, hp, STATUS_OK, STATUS_FAIL, Trials
def objective(x):
# Check if the supplied choices are valid or not
x1 = x[0]
x2 = x[1]
if x1 == x2:
# If invalid, only return the status and hyperopt will understand
return {'status': STATUS_FAIL}
# Normal flow of objective
# Do your coding here
# In the end, return this
return {
'loss': actual_loss, # Fill the actual loss here
'status': STATUS_OK
}
choices = [1,2,3,4]
space = [hp.choice('c1', choices),
hp.choice('c2', choices)]
trials = Trials()
best = fmin(objective, space=space, algo=tpe.suggest, max_evals=100, trials=trials)
from hyperopt import space_eval
print(space_eval(space, best))
Hope this helps.