我有一组选择A。我想取回选择A的子集。Hyperopt 可以做到这一点吗?
输入:
{
'A': hp.choice('A', [0, 1, 2, 3])
}
输出:
{
'A': [0, 2]
}
不,但如果您特别想要该功能,有多种方法可以做到。
您可以定义一个新表达式并将其添加到文档中给出的现有 hyperopt 参数表达式中。例如,在您的情况下,您可以执行以下操作:
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))
请参阅numpy.random.choice 的文档以了解其工作原理。
注意:
foo
方法将返回选择的子集(在 numpy 数组中)。因此,请确保在您的目标函数中,您使用的是内部多个值,例如x[0], x[1], ...
等。scope.undefine(foo)
,否则每次运行代码之前都必须重新启动终端/内核。如果允许您选择两个带有替换的值(这意味着有时子集中的两个值将相同。这就是我们replace=False
在第 1 点中使用的原因),那么可以执行以下操作:
choices = [1,2,3,4]
space = [hp.choice('c1', choices),
hp.choice('c2', choices)]
然后在您的目标函数中,您可以将两个值访问为x[0]
, x[1]
。
但是从您的问题来看,您似乎想要拥有子选择,这意味着无需替换,因此[1,1]
or的子集[2,2]
是无效的。在这种情况下,您应该使用Trials
对象来定义status
.
第 2 点的示例程序如下:
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))
希望这可以帮助。
是的,有,虽然代码有点麻烦。将 A 的每个元素分别定义为包含和排除之间的选择。例如:
space = {
"A0": hp.choice("A0", [False, True]),
"A1": hp.choice("A1", [False, True]),
"A2": hp.choice("A2", [False, True]),
...
}
在目标函数中解释这一点的代码也很容易:
A = [i for i in range(num_choices) if space["A"+str(i)]]
# A = [0, 2] for example
这将返回 A 的真正随机子集(从空集到整个 A)。