在 keras_tuner 中的 BayesianOptimization 调谐器中设置 objective 函数时遇到问题

Trouble with setting the objective function in BayesianOptimization tuner in keras_tuner

我正在尝试使用 Keras 调谐器的 BayesianOptimization 调谐器在 Keras 中调整 LSTM 模型的超参数。当我实例化调谐器时,我不断收到错误消息,这些消息似乎反对我在 objective 参数中输入的内容。这是我的代码:

    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import LSTM, Dropout, Dense
    from kerastuner.tuners import BayesianOptimization
    from kerastuner.engine.hyperparameters import HyperParameters
    from kerastuner import Objective
    
    def build_model(hp):
        model = Sequential()
        model.add(LSTM(hp.Int("input_unit", min_value=20, max_value=100, step=20),
                       batch_input_shape=(149,1,1), stateful=True, return_sequences=True))
        for i in range(hp.Int("n_layers", 1, 2)):
            model.add(LSTM(hp.Int(f"lstm_{i}_units", min_value=20, max_value=100, step=20),
                           stateful=True, return_sequences=True))
        model.add(Dropout(hp.Float("Dropout_rate", min_value=0, max_value=0.5, step=0.1)))
        model.add(Dense(1))
        model.compile(loss="mean_squared_error",
                      optimizer=hp.Choice("optimizer", values=["rmsprop", "adam"]),
                      metrics=[keras.metrics.RootMeanSquaredError(name="rmse")])
        return model
    
    tuner = BayesianOptimization(build_model,
                                 objective=Objective("root_mean_squared_error", direction="min"),
                                 max_trials=5,
                                 executions_per_trial=1)
    
    tuner.search(X_train, y_train, epochs=30, batch_size=149, shuffle=False, validation_data=(X_test, y_test))

以下是我收到的消息。如您所见,代码似乎至少部分执行了,因为我收到了一条关于到目前为止哪些超参数表现最好的消息,并且我得到了历元的摘要。在那之后,一长串错误消息,最后一条似乎与 objective 参数有关。我在实例化调谐器时指定 objective 函数的方式有问题,还是有其他问题?


    INFO:tensorflow:Reloading Oracle from existing project ./untitled_project/oracle.json
    INFO:tensorflow:Reloading Tuner from ./untitled_project/tuner0.json
    
    Search: Running Trial #3
    
    Value             |Best Value So Far |Hyperparameter
    20                |40                |input_layer
    1                 |0                 |middle_layers
    0.1               |0.2               |dropout_rate
    
    WARNING:tensorflow:Unresolved object in checkpoint: (root).layer_with_weights-1.kernel
    WARNING:tensorflow:Unresolved object in checkpoint: (root).layer_with_weights-1.bias
    WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.iter
    WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.decay
    WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.learning_rate
    WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.momentum
    WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer.rho
    WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-1.kernel
    WARNING:tensorflow:Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-1.bias
    WARNING:tensorflow:A checkpoint was restored (e.g. tf.train.Checkpoint.restore or tf.keras.Model.load_weights) but not all checkpointed values were used. See above for specific issues. Use expect_partial() on the load status object, e.g. tf.train.Checkpoint.restore(...).expect_partial(), to silence these warnings, or use assert_consumed() to make the check explicit. See https://www.tensorflow.org/guide/checkpoint#loading_mechanics for details.
    Epoch 1/30
    29/29 [==============================] - 3s 25ms/step - loss: 0.2129 - rmse: 0.4614 - val_loss: 0.2266 - val_rmse: 0.4761
    Epoch 2/30
    29/29 [==============================] - 0s 8ms/step - loss: 0.1665 - rmse: 0.4080 - val_loss: 0.2074 - val_rmse: 0.4554
    Epoch 3/30
    29/29 [==============================] - 0s 7ms/step - loss: 0.1618 - rmse: 0.4022 - val_loss: 0.2002 - val_rmse: 0.4474
    Epoch 4/30
    29/29 [==============================] - 0s 7ms/step - loss: 0.1575 - rmse: 0.3969 - val_loss: 0.1906 - val_rmse: 0.4366
    Epoch 5/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.1513 - rmse: 0.3890 - val_loss: 0.1788 - val_rmse: 0.4228
    Epoch 6/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.1421 - rmse: 0.3770 - val_loss: 0.1638 - val_rmse: 0.4047
    Epoch 7/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.1283 - rmse: 0.3583 - val_loss: 0.1440 - val_rmse: 0.3794
    Epoch 8/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.1073 - rmse: 0.3275 - val_loss: 0.1161 - val_rmse: 0.3408
    Epoch 9/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0773 - rmse: 0.2781 - val_loss: 0.0807 - val_rmse: 0.2841
    Epoch 10/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0509 - rmse: 0.2256 - val_loss: 0.0613 - val_rmse: 0.2475
    Epoch 11/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0449 - rmse: 0.2119 - val_loss: 0.0594 - val_rmse: 0.2438
    Epoch 12/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0440 - rmse: 0.2098 - val_loss: 0.0587 - val_rmse: 0.2423
    Epoch 13/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0434 - rmse: 0.2084 - val_loss: 0.0583 - val_rmse: 0.2414
    Epoch 14/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0431 - rmse: 0.2076 - val_loss: 0.0580 - val_rmse: 0.2408
    Epoch 15/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0429 - rmse: 0.2070 - val_loss: 0.0578 - val_rmse: 0.2405
    Epoch 16/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0427 - rmse: 0.2066 - val_loss: 0.0577 - val_rmse: 0.2402
    Epoch 17/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0426 - rmse: 0.2064 - val_loss: 0.0576 - val_rmse: 0.2400
    Epoch 18/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0425 - rmse: 0.2062 - val_loss: 0.0575 - val_rmse: 0.2398
    Epoch 19/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0424 - rmse: 0.2060 - val_loss: 0.0575 - val_rmse: 0.2397
    Epoch 20/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0424 - rmse: 0.2059 - val_loss: 0.0574 - val_rmse: 0.2396
    Epoch 21/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0423 - rmse: 0.2058 - val_loss: 0.0573 - val_rmse: 0.2395
    Epoch 22/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0423 - rmse: 0.2057 - val_loss: 0.0573 - val_rmse: 0.2394
    Epoch 23/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0423 - rmse: 0.2056 - val_loss: 0.0572 - val_rmse: 0.2393
    Epoch 24/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0422 - rmse: 0.2055 - val_loss: 0.0572 - val_rmse: 0.2392
    Epoch 25/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0422 - rmse: 0.2055 - val_loss: 0.0572 - val_rmse: 0.2391
    Epoch 26/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0422 - rmse: 0.2054 - val_loss: 0.0571 - val_rmse: 0.2390
    Epoch 27/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0422 - rmse: 0.2054 - val_loss: 0.0571 - val_rmse: 0.2390
    Epoch 28/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0422 - rmse: 0.2053 - val_loss: 0.0571 - val_rmse: 0.2389
    Epoch 29/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0421 - rmse: 0.2053 - val_loss: 0.0570 - val_rmse: 0.2388
    Epoch 30/30
    29/29 [==============================] - 0s 6ms/step - loss: 0.0421 - rmse: 0.2052 - val_loss: 0.0570 - val_rmse: 0.2388
    ---------------------------------------------------------------------------
    KeyError                                  Traceback (most recent call last)
    /tmp/ipykernel_371/3389478107.py in <module>
         26                              executions_per_trial=1)
         27 
    ---> 28 tuner.search(X_train, y_train, epochs=30, batch_size=149, shuffle=False, validation_data=(X_test, y_test))
    
    ~/comp_4447/dst2_env/lib/python3.9/site-packages/keras_tuner/engine/base_tuner.py in search(self, *fit_args, **fit_kwargs)
        177 
        178             self.on_trial_begin(trial)
    --> 179             results = self.run_trial(trial, *fit_args, **fit_kwargs)
        180             # `results` is None indicates user updated oracle in `run_trial()`.
        181             if results is None:
    
    ~/comp_4447/dst2_env/lib/python3.9/site-packages/keras_tuner/engine/tuner.py in run_trial(self, trial, *args, **kwargs)
        292             callbacks.append(model_checkpoint)
        293             copied_kwargs["callbacks"] = callbacks
    --> 294             obj_value = self._build_and_fit_model(trial, *args, **copied_kwargs)
        295 
        296             histories.append(obj_value)
    
    ~/comp_4447/dst2_env/lib/python3.9/site-packages/keras_tuner/engine/tuner.py in _build_and_fit_model(self, trial, *args, **kwargs)
        221         model = self._try_build(hp)
        222         results = self.hypermodel.fit(hp, model, *args, **kwargs)
    --> 223         return tuner_utils.convert_to_metrics_dict(
        224             results, self.oracle.objective, "HyperModel.fit()"
        225         )
    
    ~/comp_4447/dst2_env/lib/python3.9/site-packages/keras_tuner/engine/tuner_utils.py in convert_to_metrics_dict(results, objective, func_name)
        266         best_epoch = 0
        267         for epoch, metrics in epoch_metrics.items():
    --> 268             objective_value = objective.get_value(metrics)
        269             # Support multi-objective.
        270             if objective.name not in metrics:
    
    ~/comp_4447/dst2_env/lib/python3.9/site-packages/keras_tuner/engine/objective.py in get_value(self, logs)
         53             The objective value.
         54         """
    ---> 55         return logs[self.name]
         56 
         57     def better_than(self, a, b):
    
    KeyError: 'root_mean_squared_error'

如果:

objective=Objective("rmse", direction="min")

我不知道为什么它不起作用。刚才试了一下,修改自己的一个笔记本测试,'rmse'可以

(p.s。不过我更喜欢 Optuna,对于大型数据集,速度要快得多)

以下是一些片段:

self.compile_metrics = ['AUC', 'binary_accuracy', 'Precision', 'Recall',
                                tf.keras.metrics.RootMeanSquaredError(
                                name='rmse', dtype=None
                                )]
        
self.model.compile(
            optimizer = opt,
            #loss = 'binary_crossentropy',
            loss = 'mean_squared_error',
            metrics = self.compile_metrics,
            steps_per_execution = self.steps_per_execution,
        )

# above are snippets from my_keras_tuner_class


        
dl = my_keras_tuner_class()

tuner = kt.BayesianOptimization(
            dl.model_builder,                  # the hypermodel, found in custom class keras_tuning 
            #objective = 'val_binary_accuracy', # objective to optimize
            objective = kt.Objective("rmse", direction="min"),
            max_trials = nn_trials,            # number of trials
            distribution_strategy = tpu_strategy,
            # this project name (a dir) is created in 'directory', and is used to 
            #     resume tuning if the search is run again
            directory = f'{workdir}',   
            project_name = 'kbayesian',
            # if True, overwrite above directory if search is run again - i.e. don't resume
            overwrite = True
            
            
            
Trial 2 Complete [00h 00m 16s]
rmse: 0.42514675855636597

Best rmse So Far: 0.42514675855636597


display(model.metrics_names)
-output:
['loss', 'auc', 'binary_accuracy', 'precision', 'recall', 'rmse']


# example trial
9s 453ms/step - loss: 2.5937 - auc: 0.6732 - binary_accuracy: 0.6353 - precision: 0.6174 - recall: 0.6237 - rmse: 0.5435 - val_loss: 1.1624 - val_auc: 0.7197 - val_binary_accuracy: 0.6970 - val_precision: 0.7083 - val_recall: 0.8500 - val_rmse: 0.5045