首页 > 解决方案 > 模型构建函数没有返回有效的 Keras Model 实例,找到了 tensorflow.python.keras.engine.sequential.Sequential 对象

问题描述

我想借助在 kerastuner 中实现的贝叶斯优化来优化 LSTM 的超参数。到目前为止效果很好。我想在我的优化中添加另一件事,即贝叶斯优化可以找到最佳的特征组合。为此,我使用带有 0 的 hp.Int 来排除该功能,使用等于 1 的 hp.Int 来包含该功能。这意味着,tuner.search() 中使用的训练特性将随着每次试验而改变。

这是我的代码:

import os
import datetime

import IPython
import IPython.display
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
import tensorflow as tf
from tensorflow import keras
from kerastuner import HyperModel, Objective
from kerastuner import BayesianOptimization
import keras.backend as K
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import (
    Dense,
    Dropout,
    LSTM,
    GRU
)

#data preparation is left out of the code

class RNNHyperModel(HyperModel):
    def __init__(self, input_shape):
        self.input_shape = input_shape

    def build(self, hp):

        # feature selection within BO:
        use = {}


        for i in list(train_df.columns):

            use[str(i)] = hp.Int(
                            str(i), 
                            min_value=0,
                            max_value=1,
                            default=1)
        
        use_df = pd.DataFrame.from_dict(use, orient='index', columns = ['use'])
        list_use_features=list(use_df[use_df.use == 1].index)

        use_train_df = train_df[list_use_features]
        use_val_df = val_df[list_use_features]
        use_test_df = test_df[list_use_features]

        # get the selected features into a numpy array
        train_X = train_df.to_numpy()
        test_X = test_df.to_numpy()
        val_X = val_df.to_numpy()

        # reshape input to be 3D [samples, timesteps, features]
        train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
        test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
        val_X = val_X.reshape((val_X.shape[0], 1, val_X.shape[1]))
        #print(train_X, train_X.shape, train_y, train_y.shape)

        #implement hyperparameters for BO

        activation = hp.Choice('activation', 
                            [
                              'relu',
                              'tanh',
                              'linear',
                              'selu',
                              'elu'
                              #PReLU and LeakyReLU als zusätzlichen layer einfügen
                            ])

        num_rnn_layers = hp.Int(
                            'num_rnn_layers', 
                            min_value=0,
                            max_value=12,
                            default=3)

        recurrent_dropout = hp.Float(
                            'recurrent_dropout', 
                            min_value=0.0,
                            max_value=0.99,
                            default=0)
        num_units = hp.Int(
                            'num_units', 
                            min_value=0,
                            max_value=64,
                            default=32)

        model = tf.keras.models.Sequential()
        
        for i in range(num_rnn_layers):
            model.add(LSTM(num_units, return_sequences=True, activation=activation, recurrent_dropout = recurrent_dropout))
            
        model.add(Dense(units=1))



        model.compile(
            optimizer=keras.optimizers.Adam(
                hp.Float(
                    'learning_rate',
                    min_value=1e-10,
                    max_value=1e-2,
                    sampling='LOG',
                    default=1e-6
                ),

            ),
            loss=tf.losses.MeanSquaredError(),
            metrics=[tf.metrics.MeanAbsoluteError()]
        )
        return model, train_X, val_X, test_X

INPUT_SHAPE = (12, 1, 21)
hypermodel = RNNHyperModel(input_shape=INPUT_SHAPE)

tuner = BayesianOptimization(
    hypermodel,
    max_trials=70,
    objective='val_loss',
    seed=2,
    num_initial_points=10,
    directory=os.path.normpath('C:/'),
    overwrite=True,
    tune_new_entries=True, 
    allow_new_entries=True,
)

tuner.search(train_X, train_y, callbacks=[tf.keras.callbacks.EarlyStopping(monitor='val_loss',  
              patience=20)], validation_data = (val_X, val_y))

我跑的时候有问题

tuner = BayesianOptimization(
    hypermodel,
    max_trials=10,
    objective='val_loss',
    seed=2,
    num_initial_points=10,
    directory=os.path.normpath('C:/'),
    overwrite=True,
    tune_new_entries=True, 
    allow_new_entries=True,
)

. 然后我收到错误消息:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-213-e925add95826> in <module>
----> 1 tuner = BayesianOptimization(
      2     hypermodel,
      3     max_trials=10,
      4     objective='val_loss',
      5     seed=2,

~\anaconda3\envs\myenv\lib\site-packages\kerastuner\tuners\bayesian.py in __init__(self, hypermodel, objective, max_trials, num_initial_points, seed, hyperparameters, tune_new_entries, allow_new_entries, **kwargs)
    326             tune_new_entries=tune_new_entries,
    327             allow_new_entries=allow_new_entries)
--> 328         super(BayesianOptimization, self, ).__init__(oracle=oracle,
    329                                                      hypermodel=hypermodel,
    330                                                      **kwargs)

~\anaconda3\envs\myenv\lib\site-packages\kerastuner\engine\multi_execution_tuner.py in __init__(self, oracle, hypermodel, executions_per_trial, **kwargs)
     55                  executions_per_trial=1,
     56                  **kwargs):
---> 57         super(MultiExecutionTuner, self).__init__(
     58             oracle, hypermodel, **kwargs)
     59         if isinstance(oracle.objective, list):

~\anaconda3\envs\myenv\lib\site-packages\kerastuner\engine\tuner.py in __init__(self, oracle, hypermodel, max_model_size, optimizer, loss, metrics, distribution_strategy, directory, project_name, logger, tuner_id, overwrite)
     96                 distribution_strategy=distribution_strategy)
     97 
---> 98         super(Tuner, self).__init__(oracle=oracle,
     99                                     hypermodel=hypermodel,
    100                                     directory=directory,

~\anaconda3\envs\myenv\lib\site-packages\kerastuner\engine\base_tuner.py in __init__(self, oracle, hypermodel, directory, project_name, logger, overwrite)
     89         self._display = tuner_utils.Display()
     90 
---> 91         self._populate_initial_space()
     92 
     93         if not overwrite and tf.io.gfile.exists(self._get_tuner_fname()):

~\anaconda3\envs\myenv\lib\site-packages\kerastuner\engine\base_tuner.py in _populate_initial_space(self)
    104         """
    105         hp = self.oracle.get_space()
--> 106         self.hypermodel.build(hp)
    107         self.oracle.update_space(hp)
    108 

~\anaconda3\envs\myenv\lib\site-packages\kerastuner\engine\hypermodel.py in _build_wrapper(self, hp, *args, **kwargs)
     63             # to the search space.
     64             hp = hp.copy()
---> 65         return self._build(hp, *args, **kwargs)
     66 
     67 

~\anaconda3\envs\myenv\lib\site-packages\kerastuner\engine\hypermodel.py in build(self, hp)
    118             # Stop if `build()` does not return a valid model.
    119             if not isinstance(model, keras.models.Model):
--> 120                 raise RuntimeError(
    121                     'Model-building function did not return '
    122                     'a valid Keras Model instance, found {}'.format(model))

RuntimeError: Model-building function did not return a valid Keras Model instance, found (<tensorflow.python.keras.engine.sequential.Sequential object at 0x0000020888F67A00>`

更具体地说,如果我只定义类 RNNHyperModel 而没有特征选择过程来创建模型,那么一切正常。:

class RNNHyperModel(HyperModel):
    def __init__(self, input_shape):
        self.input_shape = input_shape

    def build(self, hp):


        #implement hyperparameters for BO

        activation = hp.Choice('activation', 
                            [
                              'relu',
                              'tanh',
                              'linear',
                              'selu',
                              'elu'
                              #PReLU and LeakyReLU als zusätzlichen layer einfügen
                            ])

        num_rnn_layers = hp.Int(
                            'num_rnn_layers', 
                            min_value=0,
                            max_value=12,
                            default=3)

        recurrent_dropout = hp.Float(
                            'recurrent_dropout', 
                            min_value=0.0,
                            max_value=0.99,
                            default=0)
        num_units = hp.Int(
                            'num_units', 
                            min_value=0,
                            max_value=64,
                            default=32)

        model = tf.keras.models.Sequential()
        
        for i in range(num_rnn_layers):
            model.add(LSTM(num_units, return_sequences=True, activation=activation, recurrent_dropout = recurrent_dropout))
            
        model.add(Dense(units=1))



        model.compile(
            optimizer=keras.optimizers.Adam(
                hp.Float(
                    'learning_rate',
                    min_value=1e-10,
                    max_value=1e-2,
                    sampling='LOG',
                    default=1e-6
                ),

            ),
            loss=tf.losses.MeanSquaredError(),
            metrics=[tf.metrics.MeanAbsoluteError()]
        )
        return model

我已经检查了一些较旧的帖子,但那里提供的答案(即从 tensorflow 导入 keras)并没有解决我的问题。

我检查了结果,tuner.search_space_summary()这符合预期,即我的特征表示为 0 或 1 的 Int。我添加了一个简短的特征示例:

Search space summary
|-Default search space size: 25
Arbeitslose (Int)
|-default: 1
|-max_value: 1
|-min_value: 0
|-sampling: None
|-step: 1
touristische_Übernachtungen (Int)
|-default: 1
|-max_value: 1
|-min_value: 0
|-sampling: None
|-step: 1

事实上,我有两个问题,但如果有人可以帮助我解决第一个问题,我也许可以自己解决第二个问题:

  1. 如何解决模型构建函数未返回有效 Keras 模型的问题?
  2. 在我的 RNNHyperModel 类中返回 train_X 是否足以让 tuner.search() 识别它?因为之前的错误,我无法尝试。是否有更智能的解决方案可以根据每次试验中选择的超参数来调整 train_X 集?

提前感谢您的帮助。

标签: pythontensorflowkerashyperparameterskeras-tuner

解决方案


推荐阅读