尝试将列表作为参数传递给hyperas时出错

时间:2017-10-26 15:54:26

标签: python python-3.x optimization keras

我正在使用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),
                                         ^

1 个答案:

答案 0 :(得分:0)

问题在于这一行:

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作为参数参数。例如,要修复上面有问题的行,并在退出时使用变量下限/上限:

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()步骤分开。