Source code for mcfly.modelgen

#
# mcfly
#
# Copyright 2020 Netherlands eScience Center
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import warnings
import numpy as np
from mcfly.models import CNN, DeepConvLSTM, ResNet, InceptionTime
from mcfly.task import Task


[docs]def generate_models(x_shape, number_of_output_dimensions, number_of_models, model_types=['CNN', 'DeepConvLSTM', 'ResNet', 'InceptionTime'], task=Task.classification, metrics=['accuracy'], **hyperparameter_ranges): """ Generate one or multiple untrained Keras models with random hyperparameters. The number of models per given model type will be roughly balanced. Parameters ---------- x_shape : tuple Shape of the input dataset: (num_samples, num_timesteps, num_channels) number_of_output_dimensions : int Number of classes for classification task or number of targets for regression. number_of_models : int Number of models to generate. Should at least be >= the number of given model types. model_types : list, optional Expects list containg names of mcfly default models ('CNN' 'DeepConvLSTM', 'ResNet', or 'InceptionTime'), or custom model classes (see mcfly.models for examples on how such a class is build and what it must contain). Default is to use all built-in mcfly models. task: str Task type, either 'classification' or 'regression' metrics : list Metrics to calculate on the validation set. See https://keras.io/metrics/ for possible values. low_lr : float minimum of log range for learning rate: learning rate is sampled between `10**(-low_lr)` and `10**(-high_lr)` high_lr : float maximum of log range for learning rate: learning rate is sampled between `10**(-low_lr)` and `10**(-high_lr)` low_reg : float minimum of log range for regularization rate: regularization rate is sampled between `10**(-low_reg)` and `10**(-high_reg)` high_reg : float maximum of log range for regularization rate: regularization rate is sampled between `10**(-low_reg)` and `10**(-high_reg)` Further hyperparameter ranges can be specified according to the respective model types used. Returns ------- models : list List of compiled models """ # Set default hyperparameter ranges defaults = {'low_lr': 1, 'high_lr': 4, 'low_reg': 1, 'high_reg': 4} default_models = {model.model_name: model for model in [CNN, DeepConvLSTM, ResNet, InceptionTime]} _check_arguments_validity(default_models, model_types, number_of_models) _update_hyperparameter_ranges(defaults, hyperparameter_ranges) model_types_selected = _sample_model_types(model_types, number_of_models) return _instantiate_models(default_models, hyperparameter_ranges, metrics, model_types_selected, number_of_output_dimensions, x_shape, task)
def _instantiate_models(default_models, hyperparameter_ranges, metrics, model_types_selected, number_of_output_dimensions, x_shape, task): models = [] for current_model_type in model_types_selected: if current_model_type in default_models: model_type = default_models[current_model_type](x_shape, number_of_output_dimensions, metrics, **hyperparameter_ranges) else: # Assume model class was passed model_type = current_model_type(x_shape, number_of_output_dimensions, metrics, **hyperparameter_ranges) hyperparameters = model_type.generate_hyperparameters() model = model_type.create_model(task=task, **hyperparameters) model_name = model_type.model_name models.append((model, hyperparameters, model_name)) return models def _sample_model_types(model_types, number_of_models): selected = [] for _ in range(int(np.ceil(number_of_models / len(model_types)))): np.random.shuffle(model_types) selected.extend(model_types) return selected[:number_of_models] def _update_hyperparameter_ranges(defaults, hyperparameter_ranges): # Replace default hyperparameter ranges with input for key, value in hyperparameter_ranges.items(): if key in defaults: print("The value of {} is set from {} (default) to {}".format(key, defaults[key], value)) defaults[key] = value # Add missing parameters from default for key, value in defaults.items(): if key not in hyperparameter_ranges: hyperparameter_ranges[key] = value def _check_arguments_validity(default_models, model_types, number_of_models): for model_type in model_types: if isinstance(model_type, str) and model_type not in default_models: raise NameError("Unknown model name, '{}'.".format(model_type)) if number_of_models < len(model_types): warnings.warn("Specified number_of_models is smaller than the given number of model types.")