0

我有一组选择A。我想取回选择A的子集。Hyperopt 可以做到这一点吗?

输入:

{
    'A': hp.choice('A', [0, 1, 2, 3])
}

输出:

{
    'A': [0, 2]
}
4

2 回答 2

4

不,但如果您特别想要该功能,有多种方法可以做到。

  1. 您可以定义一个新表达式并将其添加到文档中给出的现有 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),否则每次运行代码之前都必须重新启动终端/内核。
    • hyperopt wiki明确禁止定义新类型的参数搜索空间,就像我们在上面所做的那样,因为这可能会影响搜索策略或执行非最优。
  2. 如果允许您选择两个带有替换的值(这意味着有时子集中的两个值将相同。这就是我们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))

希望这可以帮助。

于 2018-12-19T11:27:04.867 回答
1

是的,有,虽然代码有点麻烦。将 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)。

于 2021-08-12T20:18:11.250 回答