Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

                  Python Python Dependencies GitHub Issues Contributions welcome License

Overview

MiP-EGO (Mixed integer, Parallel - Efficient Global Optimization) is an optimization package that can be used to optimize Mixed integer optimization problems. A mixed-integer problem is one where some of the decision variables are constrained to be integer values or categorical values.
Next to the classical mixed integer problems, Algorithm selection or algorithm parameter optimization can also be seen as a complex mixed-integer problem.

The advantage of MiP-EGO is that it uses a surrogate model (the EGO part) to learn from the evaluations it has made so far. Instead of Gaussian Process Regression like in standard EGO, the MiP-EGO uses Random Forests instead, since Random Forests can handle mixed integer data by default.
The P in MiP-EGO stands for parallel, as this implementation has the additional feature that it can evaluate several solutions in parallel, which is extremely handy when an evaluation takes a long time and several machines are available.

For example, one use case would be to optimize an expensive (in time) simulation. There are four simulation licenses, so four simulations can be run at the same time. With MiP-EGO, all these four licenses can be fully utilized, speeding up the optimization procedure. Using a novel infill-criteria, the Moment Generating Function Based criterium, multiple points can be selected as candidate solutions. See the following paper for more detail about this criterium:
WANG, Hao, et al. A new acquisition function for Bayesian optimization based on the moment-generating function. In: Systems, Man, and Cybernetics (SMC), 2017 IEEE International Conference on. IEEE, 2017. p. 507-512.

Citation

@INPROCEEDINGS{8851720, 
    author={B. v. {Stein} and H. {Wang} and T. {Bäck}}, 
    booktitle={2019 International Joint Conference on Neural Networks (IJCNN)}, 
    title={Automatic Configuration of Deep Neural Networks with Parallel Efficient Global Optimization}, 
    year={2019}, 
    pages={1-7}, 
    keywords={convolutional neural nets;learning (artificial intelligence);neural net architecture;convolutional neural network architectures;deep neural network design;automatic configuration;deep neural networks;artificial neural network;image classification tasks;mixed integer parallel efficient global optimization algorithm;Machine-to-machine communications;Neural networks;Optimization;Deep Learning;Network Architectures;Bayesian Optimization;Optimization}, 
    doi={10.1109/IJCNN.2019.8851720}, 
    ISSN={2161-4393}, 
    month={July}
}

Async Parallel Optimization of Neural Network Architectures

MiP-EGO also supports asynchronous parallel optimization, currently this feature is in Beta and being used to optimize the architecture and parameters of deep neural networks. See Example 2 for more details.

Install

pip install mipego

Usage

To use the optimizer you need to define an objective function, the search space and configure the optimizer. Below are two examples that describe most of the functionality.

Example - Optimizing A Black-Box Function

In this example we optimize a mixed integer black box problem.

import os
import numpy as np

#import our package, the surrogate model and the search space classes
from mipego import mipego
from mipego.surrogate import RandomForest
from mipego.SearchSpace import ContinuousSpace, NominalSpace, OrdinalSpace

# The "black-box" objective function
def obj_func(x):
   x_r, x_i, x_d = np.array([x['C_0'],x['C_1']]), x['I'], x['N']
   if x_d == 'OK':
       tmp = 0
   else:
       tmp = 1
   return np.sum(x_r ** 2.) + abs(x_i - 10) / 123. + tmp * 2.


# First we need to define the Search Space
# the search space consists of two continues variable
# one ordinal (integer) variable
# and one categorical.
C = ContinuousSpace([-5, 5],'C') * 2 
#here we defined two variables at once using the same lower and upper bounds.
#One with label C_0, and the other with label C_1
I = OrdinalSpace([-100, 100],'I') # one integer variable with label I
N = NominalSpace(['OK', 'A', 'B', 'C', 'D', 'E'], 'N')

#the search space is simply the product of the above variables
search_space = C * I * N

#next we define the surrogate model and the optimizer.
model = RandomForest(levels=search_space.levels)
opt = mipego(search_space, obj_func, model, 
                 minimize=True,     #the problem is a minimization problem.
                 max_eval=500,      #we evaluate maximum 500 times
                 max_iter=500,      #we have max 500 iterations
                 infill='EI',       #Expected improvement as criteria
                 n_init_sample=10,  #We start with 10 initial samples
                 n_point=1,         #We evaluate every iteration 1 time
                 n_job=1,           #  with 1 process (job).
                 optimizer='MIES',  #We use the MIES internal optimizer.
                 verbose=False, random_seed=None)


#and we run the optimization.
incumbent, stop_dict = opt.run()

Example 2 - Optimizing A Neural Network

In this example we optimize a neural network architecture on the MNIST dataset. The objective function in this case is this file from the root repository directory.
In the objective file the neural network architecture is defined and evaluated on the MNIST dataset.
The code below shows how to set up the optimizer for this purpose using 4 GPUs asynchronously.

import os
import numpy as np
import subprocess, sys
from subprocess import STDOUT, check_output

#import our package, the surrogate model and the search space classes
from mipego import mipego
from mipego.Surrogate import RandomForest
from mipego.SearchSpace import ContinuousSpace, NominalSpace, OrdinalSpace

#some help packages
import re
import traceback
import time

#first lets define our objective function, 
#this is basically calling the file (all-cnn.py) and processes its output.
class obj_func(object):
    def __init__(self, program):
        self.program = program

    def __call__(self, cfg, gpu_no):
        print("calling program with gpu "+str(gpu_no))
        cmd = ['python3', self.program, '--cfg', str(cfg), str(gpu_no)]
        outs = ""
        outputval = 0
        try:
            #we use a timeout to cancel very long evaluations.
            outs = str(check_output(cmd,stderr=STDOUT, timeout=40000)) 
            outs = outs.split("\\n")

            outputval = 0
            for i in range(len(outs)-1,1,-1):
                if re.match("^\d+?\.\d+?$", outs[-i]) is not None:
                    print(outs[-i])
                    outputval = -1 * float(outs[-i])
            if np.isnan(outputval):
                outputval = 0 #default to 0.
        except subprocess.CalledProcessError as e:
            #exception handling
            traceback.print_exc()
            print (e.output)
        except:
            print ("Unexpected error:")
            traceback.print_exc()
            outputval = 0
        return outputval



objective = obj_func('./all-cnn.py')
activation_fun = ["softmax","sigmoid"] #activation function of the last layer.
activation_fun_conv = ["elu","relu","tanh","sigmoid","selu"]

#Next we define the search space.
filters = OrdinalSpace([10, 600], 'filters') * 7
kernel_size = OrdinalSpace([1, 6], 'k') * 7
strides = OrdinalSpace([1, 5], 's') * 3
stack_sizes = OrdinalSpace([1, 5], 'stack') * 3
activation = NominalSpace(activation_fun_conv, "activation")  
activation_dense = NominalSpace(activation_fun, "activ_dense") 

# to use step decay or not
step = NominalSpace([True, False], "step")  
#to use global pooling in the end or not.
global_pooling = NominalSpace([True, False], "global_pooling")

drop_out = ContinuousSpace([1e-5, .9], 'dropout') * 4 
lr_rate = ContinuousSpace([1e-4, 1.0e-0], 'lr')      #learning rate
l2_regularizer = ContinuousSpace([1e-5, 1e-2], 'l2') # l2_regularizer

search_space =  stack_sizes * strides * filters *  kernel_size * activation * activation_dense * drop_out * lr_rate * l2_regularizer * step * global_pooling 

#We will use the first 4 GPU's of the system.
available_gpus = [0,1,2,3] 

# use random forest as the surrogate model 
model = RandomForest(levels=search_space.levels)

#now define the optimizer.
opt = mipego(search_space, objective, model, 
                 minimize=True, max_eval=None, max_iter=500, 
                 infill='MGFI', n_init_sample=10, 
                 n_point=4, n_job=4, 
                 #4 GPU's, all evaluating 1 point at a time.
                 wait_iter=3, optimizer='MIES', 
                 verbose=False, random_seed=None,
                 available_gpus=available_gpus)


#run
incumbent, stop_dict = opt.run()

Contributing

Please take a look at our contributing guidelines if you're interested in helping!

Beta Features

  • Async GPU execution
  • Intermediate files to support restarts / resumes.

Metadata

Release files for mipego 1.1.0.dev4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mipego 1.1.0.dev4
File Size Uploaded
mipego-1.1.0.dev4.tar.gz 40.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mipego 1.1.0.dev4
File Interpreter ABI Platform
mipego-1.1.0.dev4-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 79.3 kB

Release files / mipego-1.1.0.dev4.tar.gz

Download URL mipego-1.1.0.dev4.tar.gz
Size 40.8 kB
Tags Source
SHA-256 checksum
How to use checksums
c03b8c716fa726271a7058246e5b4cc7664cdbcdd081a25e654efd0411694c50
BLAKE2b-256 checksum
How to use checksums
d486cf4f61875939bf0075c8bd15f98ac14944352551ac8bd3c8c4790171ddc6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.15.0 pkginfo/1.4.2 requests/2.13.0 setuptools/42.0.2 requests-toolbelt/0.8.0 tqdm/4.23.4 CPython/2.7.16

Release files / mipego-1.1.0.dev4-py2.py3-none-any.whl

Download URL mipego-1.1.0.dev4-py2.py3-none-any.whl
Size 38.4 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
ac8e3c1f6887bf5e46ae483c47b0e516ec15a778ba704e8808aaaa9fca3c3811
BLAKE2b-256 checksum
How to use checksums
270c373c83a023b302f52abf6e596dff979b9fc8137ff0b4d5c5ea28440a0fc0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.15.0 pkginfo/1.4.2 requests/2.13.0 setuptools/42.0.2 requests-toolbelt/0.8.0 tqdm/4.23.4 CPython/2.7.16
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page