Оптимизировать количество скрытых слоев и нейронов с помощью RandomizedSearchCV (scikit-learn) -> Нет ненужных тренировок?

#python #optimization #scikit-learn #neural-network #hyperparameters

#python #оптимизация #scikit-learn #нейронная сеть #гиперпараметры

Вопрос:

Я хочу оптимизировать количество скрытых слоев и количество единиц в каждом скрытом слое. Для этого я использовал RandomizedSearchCV из sklearn таким образом:

     from tensorflow.keras.wrappers.scikit_learn import KerasRegressor
    from sklearn.model_selection import RandomizedSearchCV
    from tensorflow import keras
    models = keras.models
    layers = keras.layers

    def tuneModel(n_layer, n1_units, n2_units):
        model = models.Sequential()

        # input layer   first hidden layer
        model.add(layers.Dense(n1_units, input_dim=100, activation="relu"))       
        
        # second hidden layer
        if n_layer == 2:
            model.add(layers.Dense(n2_units, activation="relu"))   
    
        # output layer
        model.add(layers.Dense(2))                                                  
        
        model.compile(loss="mse", optimizer=opt)
        return model
    
    model = KerasRegressor(build_fn=tuneModel, verbose=0)
    
    param_grid = dict(n_layer=[1,2],
                      n1_units=[16, 32, 64, 128],                  
                      n2_units=[16, 32, 64, 128],
                      batch_size=[64],
                      epochs=[100]
                      )

    grid = RandomizedSearchCV(estimator=model,
                              param_distributions=param_grid, 
                              scoring="neg_mean_squared_error",
                              cv=5,
                              n_iter=8
                              )
    
    grid_result = grid.fit(x,y)
 

Это сильно уменьшенный пример для демонстрации моей проблемы.
Это работает хорошо, но будут происходить ненужные тренировки. Например, если n_layer = 1 и n1_units = 16, существует четыре комбинации, которые обучают одну и ту же сеть:

n_layer = 1, n1_units = 16, n2_units = 16

n_layer = 1, n1_units = 16, n2_units = 32

n_layer = 1, n1_units = 16, n2_units = 64

n_layer = 1, n1_units = 16, n2_units = 128

Потому что параметр n2_units не используется для сети из одного уровня.

Можно ли построить сеть по-другому, чтобы этого не произошло?

Надеюсь, мои объяснения понятны 🙂

Ответ №1:

Я бы передал размеры слоев в виде кортежа вместо отдельных параметров. Например.

 def tuneModel(layer_sizes): 
    model = models.Sequential()
    model.add(keras.Input(shape=(100,)))

    for layer_size in layer_sizes:
        model.add(layers.Dense(layer_size, activation="relu"))

    model.add(layers.Dense(2))

    model.compile(loss="mse", optimizer=opt)
    return model

sizes = [16, 32, 64, 128]
shapes = (
    list(itertools.product(sizes, repeat=1))
      list(itertools.product(sizes, repeat=2))
)

param_grid = dict(
    layer_sizes=shapes,
    batch_size=[64],
    epochs=[100]
)
 

Комментарии:

1. Большое спасибо! Я не видел этого способа. Это работает отлично.