Source code for monitizer.optimizers.optimization_config
# This file is part of Monitizer, a tool for optimizing and evaluating neural network monitors:
# https://gitlab.com/live-lab/software/monitizer/
#
# SPDX-FileCopyrightText: 2023 Stefanie Mohr
#
# SPDX-License-Identifier: Apache-2.0
from configparser import ConfigParser
import os
# EXPECTED STRUCTURE OF THE CONFIG
# [Optimization]
# [Optimization.Objective]
# type = single-objective
# function = OptimalForOODClassSubjectToFNR
# file =
# # single-objective currently contains: OptimalForOODClass, OptimalForOODClassSubjectToFNR
# # multi-objective currently contains: OptimalForOODClasses, OptimalForOODClassesSubjectToFNR
#
# [Optimization.Objective.Specification]
# ood_classes = Noise/Gaussian
# tnr_minimum = 70
#
# [Optimization.Optimizer]
# type = random
#
# [Optimization.Optimizer.Random]
# episodes = 1
#
# [Optimization.Optimizer.Grid-search]
# grid_count = 4
#
# [Optimization.Optimizer.Gradient-descent]
# episodes = 1
# learning_rate = 1
#
# [Multi-Objective]
# num_splits = 4
[docs]
class OptimizationConfig:
"""
Configuration that reads a config-file and stores everything in a more readable and useable format.
"""
def __init__(self, config_file: str):
"""
Parse the config-file and store the values in variables.
"""
if not os.path.isfile(config_file):
raise ValueError(f"The optimization config in {config_file} does not exist!")
config = ConfigParser()
config.read(config_file)
if config.has_option("Optimization", "output_plots"):
self.output_plots = True
else:
self.output_plots = False
if config.has_option('Optimization.Objective', 'type'):
self.objective_type = config.get('Optimization.Objective', 'type')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n For single-objective, please add \n'
f'[Optimization.Objective]\n'
f'type = single-objective\n')
if config.has_option('Optimization.Objective', 'function'):
self.objective_function = config.get('Optimization.Objective', 'function')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n Please define the objective function.'
f'For example, if you want to use "OptimalForOODClassSubjectToFNR" as objective, add \n'
f'[Optimization.Objective]\n'
f'function = OptimalForOODClassSubjectToFNR\n')
if config.has_option('Optimization.Objective', 'file'):
self.objective_file = config.get('Optimization.Objective', 'file')
else:
self.objective_file = ""
if config.has_section('Optimization.Objective.Specification'):
self.additional_objective_info = config['Optimization.Objective.Specification']
else:
raise UserWarning("If your objective needs some specification, you should add a section for this in the config.\n"
"This could look like this:\n"
"[Optimization.Objective.Specification]\n"
"ood_classes=Noise/Gaussian,NewWorld/CIFAR10\n")
if config.has_option('Optimization.Optimizer','type'):
self.optimiziation_function = config.get('Optimization.Optimizer', 'type')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n '
f'Please define the optimization function.'
f'For example, if you want to use random optimization, add \n'
f'[Optimization.Optimizer]\n'
f'function = random\n')
if self.optimiziation_function == 'random':
if config.has_option('Optimization.Optimizer.Random', 'episodes'):
self.episodes = config.getint('Optimization.Optimizer.Random', 'episodes')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n '
f'Please define the information for the optimization function.'
f'You specified random optimization, so please add \n'
f'[Optimization.Optimizer.Random]\n'
f'episodes = 10\n')
elif self.optimiziation_function == 'grid-search':
if config.has_option('Optimization.Optimizer.Grid-search', 'grid_count'):
self.grid_count = config.getint('Optimization.Optimizer.Grid-search', 'grid_count')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n '
f'Please define the information for the optimization function.'
f'You specified grid-search, so please add\n'
f'[Optimization.Optimizer.Grid-search]\n'
f'grid_count = 10\n')
elif self.optimiziation_function == 'gradient-descent':
if config.has_section('Optimization.Optimizer.Gradient-descent'):
if config.has_option('Optimization.Optimizer.Gradient-descent', 'episodes'):
self.episodes = config.getint('Optimization.Optimizer.Gradient-descent', 'episodes')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n '
f'Please define the information for the optimization function.'
f'You specified gradient descent, so please add\n'
f'[Optimization.Optimizer.Gradient-descent]\n'
f'episodes = 10\n'
f'learning_rate = 1\n')
if config.has_option('Optimization.Optimizer.Gradient-descent', 'learning_rate'):
self.learning_rate = config.getfloat('Optimization.Optimizer.Gradient-descent', 'learning_rate')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n '
f'Please define the information for the optimization function.'
f'You specified gradient descent, so please add\n'
f'[Optimization.Optimizer.Gradient-descent]\n'
f'episodes = 10\n'
f'learning_rate = 1\n')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n '
f'Please define the information for the optimization function.'
f'You specified gradient descent, so please add\n'
f'[Optimization.Optimizer.Gradient-descent]\n'
f'episodes = 10\n'
f'learning_rate = 1\n')
if self.objective_type == 'multi-objective':
if config.has_option('Multi-Objective', 'num_splits'):
self.num_splits = config.getint('Multi-Objective', 'num_splits')
else:
raise KeyError(
f'The config {config_file} does not have the right structure.\n '
f'Please define the information for the multi objective case. Please add\n'
f'[Multi-Objective]\n'
f'num_splits=4\n')
self._config = config