【问题标题】:Error trying to pass list to hyperas as a parameter尝试将列表作为参数传递给 hyperas 时出错
【发布时间】:2018-04-08 02:19:37
【问题描述】:

我正在使用 keras 和 hyperas library 进行超参数优化。

我正在尝试传递一个列表而不是硬编码列表,但它会引发错误。在 hyperas 中,您将模板值包装在“{{ some value }}”中,您可以将代码卡为列表。示例:

model.add(Dense({{choice([258,512,1024])}}))

错误:

File "hy.py", line 89, in
trials=Trials())
File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperas-0.4-py3.6.egg/hyperas/optim.py", line 67, in minimize
verbose=verbose)
File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperas-0.4-py3.6.egg/hyperas/optim.py", line 118, in base_minimizer
space=get_space(),
File "/home/peachy/Documents/tensorflow/temp_model.py", line 119, in get_space
NameError: name 'dropout' is not defined

使用一个基本示例,这是模型类。我正在从加载列表的 yml 文件加载,但这不起作用,所以我只是试图在模型类中创建一个列表并将其传递进去。它不会工作。

from __future__ import print_function

from hyperopt import Trials, STATUS_OK, tpe
from keras.datasets import mnist
from keras.layers.core import Dense, Dropout, Activation
from keras.models import Sequential
from keras.utils import np_utils

from hyperas import optim
from hyperas.distributions import choice, uniform, conditional
import common_config as cfg

def data():
    """
    Data providing function:
    This function is separated from model() so that hyperopt
    won't reload data for each evaluation run.
    """
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    x_train = x_train.reshape(60000, 784)
    x_test = x_test.reshape(10000, 784)
    x_train = x_train.astype('float32')
    x_test = x_test.astype('float32')
    x_train /= 255
    x_test /= 255
    nb_classes = 10
    y_train = np_utils.to_categorical(y_train, nb_classes)
    y_test = np_utils.to_categorical(y_test, nb_classes)
    return x_train, y_train, x_test, y_test


def model(x_train, y_train, x_test, y_test):
    """
    Model providing function:
    Create Keras model with double curly brackets dropped-in as needed.
    Return value has to be a valid python dictionary with two customary keys:
        - loss: Specify a numeric evaluation metric to be minimized
        - status: Just use STATUS_OK and see hyperopt documentation if not feasible
    The last one is optional, though recommended, namely:
        - model: specify the model just created so that we can later use it again.
    """
    ModelConfig = cfg.ModelConfig
    dropout = [0,1]
    print (dropout)
    print (type(dropout))




    model = Sequential()
    model.add(Dense(512, input_shape=(784,)))
    model.add(Activation(ModelConfig.activation))
    model.add(Dropout({{uniform(dropout)}}))
    model.add(Dense({{choice([258,512,1024])}}))
    model.add(Activation({{choice(['relu', 'sigmoid'])}}))
    model.add(Dropout({{uniform(0,1)}}))

    # If we choose 'four', add an additional fourth layer
    if conditional({{choice(['three', 'four'])}}) == 'four':
        model.add(Dense(100))

        # We can also choose between complete sets of layers

        model.add({{choice([Dropout(0.5), Activation('linear')])}})
        model.add(Activation('relu'))

    model.add(Dense(10))
    model.add(Activation('softmax'))

    model.compile(loss='categorical_crossentropy', metrics=['accuracy'],
                  optimizer={{choice(['rmsprop', 'adam', 'sgd'])}})

    model.fit(x_train, y_train,
              batch_size={{choice([64, 128])}},
              epochs=1,
              verbose=2,
              validation_data=(x_test, y_test))
    score, acc = model.evaluate(x_test, y_test, verbose=0)
    print('Test accuracy:', acc)
    return {'loss': -acc, 'status': STATUS_OK, 'model': model}


if __name__ == '__main__':
    best_run, best_model = optim.minimize(model=model,
                                          data=data,
                                          algo=tpe.suggest,
                                          max_evals=10,
                                          trials=Trials())
    X_train, Y_train, X_test, Y_test = data()
    print("Evalutation of best performing model:")
    print(best_model.evaluate(X_test, Y_test))
    print("Best performing model chosen hyper-parameters:")
    print(best_run)

值是如何从模板发送到 optim.py 文件的? 我已经检查过了,正则表达式应该能够处理列表。

我不希望任何人知道,但你将如何调试它,因为它很可能是一个库问题

编辑

解决方案 1 和 2 只会引发类型错误,这在源代码中是一个非常奇怪的检查,以查看它是否是某个字符串类型

Hyperopt 代码 pyll_util.py

def validate_label(f):
    @wraps(f)
    def wrapper(label, *args, **kwargs):
        is_real_string = isinstance(label, basestring)
        is_literal_string = (isinstance(label, Literal) and
                             isinstance(label.obj, basestring))
        if not is_real_string and not is_literal_string:
            raise TypeError('require string label')
        return f(label, *args, **kwargs)
    return wrapper

错误

Traceback (most recent call last):
  File "hy.py", line 107, in <module>
    trials=Trials())
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperas-0.4-py3.6.egg/hyperas/optim.py", line 67, in minimize
    verbose=verbose)
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperas-0.4-py3.6.egg/hyperas/optim.py", line 136, in base_minimizer
    return_argmin=True),
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperopt/fmin.py", line 307, in fmin
    return_argmin=return_argmin,
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperopt/base.py", line 635, in fmin
    return_argmin=return_argmin)
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperopt/fmin.py", line 320, in fmin
    rval.exhaust()
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperopt/fmin.py", line 199, in exhaust
    self.run(self.max_evals - n_done, block_until_done=self.async)
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperopt/fmin.py", line 173, in run
    self.serial_evaluate()
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperopt/fmin.py", line 92, in serial_evaluate
    result = self.domain.evaluate(spec, ctrl)
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperopt/base.py", line 840, in evaluate
    rval = self.fn(pyll_rval)
  File "/home/peachy/Documents/tensorflow/temp_model.py", line 101, in keras_fmin_fnct
  File "<string>", line 1, in <module>
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperopt/pyll_utils.py", line 21, in wrapper
    raise TypeError('require string label')
TypeError: require string label

通过合并列表的解决方案 3 会导致以下错误,该错误表明 %s 已与 dropout_1 一起基于生成的 temp_model 文件中。

Unexpected error: <class 'SyntaxError'>
Traceback (most recent call last):
  File "hy.py", line 107, in <module>
    trials=Trials())
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperas-0.4-py3.6.egg/hyperas/optim.py", line 67, in minimize
    verbose=verbose)
  File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperas-0.4-py3.6.egg/hyperas/optim.py", line 104, in base_minimizer
    from temp_model import keras_fmin_fnct, get_space
  File "/home/peachy/Documents/tensorflow/temp_model.py", line 133
    'Dropout_1': hp.uniform('Dropout_1', %s),
                                         ^

【问题讨论】:

    标签: python python-3.x optimization keras


    【解决方案1】:

    问题出在这一行:

    model.add(Dropout({{uniform(dropout)}}))
    

    变量dropout 是在model() 函数的范围内定义的,但在双括号{{ }} 内,您有一个完全不同的范围,由hyperas 库处理。因此,当 hyperas 尝试获取应用此超优化器的空间时,您遇到的错误是:

    File "/home/peachy/Documents/tensorflow/tf/lib/python3.6/site-packages/hyperas-0.4-py3.6.egg/hyperas/optim.py", line 118, in base_minimizer
    space=get_space(),
    File "/home/peachy/Documents/tensorflow/temp_model.py", line 119, in get_space
    NameError: name 'dropout' is not defined
    

    变量 dropout 没有定义在 hyperas 的范围内({{ }} 内的范围)。它只定义在model()函数的范围内。

    您会注意到,在hyperas README.md 中提供的所有示例中,传递给超优化器的值都是硬编码的字符串或数字。

    解决方案 1

    如果您需要改变这些参数,您可以使用eval 将参数作为参数。例如,要修复上面有问题的行并在 dropout 上使用变量下限/上限:

    lo = 0.2
    hi = 0.8
    cmd = "model.add(Dropout({{uniform(%.1f,%.1f)}}))"%( lo, hi )
    eval(cmd)
    

    解决方案 2

    或者,使用.format()(在最后的字符串中每个括号都有两个括号,总共4个):

    lo = 0.2
    hi = 0.8
    cmd = "model.add(Dropout({{{{uniform({:.1f},{:.1f})}}}}))".format(lo,hi)
    eval(cmd)
    

    解决方案 3

    如果列表中有lohi,请使用.join() 将它们组合成一个字符串并将它们传递给eval() 函数:

    mylist = [0.2, 0.8]
    argstring = ",".join( str(x) for x in mylist )
    cmd = "model.add(Dropout({{uniform(%s)}}))"%(argstring)
    eval(cmd)
    

    编辑 1:添加了两个附加示例 - 一个替代字符串格式化函数和一个列表示例。

    编辑 2: 将字符串格式化步骤与 eval() 步骤分开。

    【讨论】:

    • 是否可以修改库以接受列表,或者这是否值得付出更多的努力?
    • 修改 hyperas 以接受 {{ }} 模板中的变量将比使用 eval 更多方式工作。请记住,我们谈论的是两个完全不同的范围,它们彼此不了解。使用 eval 只是字符串操作的问题。
    • 所以不可能像这样 eval("model.add(Dropout({{uniform(%.1f)}}))"%( dropout )) 输入一个列表
    • 另外你的解决方案在 python 3 中抛出一个错误,不确定你是否使用 python 2 语法
    • 这是 Python 3 语法 - 我链接到的文档是 Python 3 文档。您可以将“eval()”替换为“print()”来测试出了什么问题(上面的 eval 语句在 Python 3.5 中有效)。如果您需要从列表中打印多个参数,这只是字符串操作 - 您可以使用列表推导式或 ",".join(mylist) 将您的参数组合成单个字符串,然后使用 eval 和 %s 而不是 %d%f.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    相关资源
    最近更新 更多