Trying to leverage relumip package of AnnModel
AnsweredHi,
Basically I trained my neural net model and saved my h5 file and read into my optimization code(https://github.com/processintelligenceresearch/ReLU_ANN_MILP/blob/master/examples/Gurobi%20example%20notebook.ipynb). I am replicating the similar steps for my problem as mentioned in the above link.
In my problem, I am supposed to run the relumip model 10 times something like
m.setObjective(output_vars[p] for p in range(10),GRB.MINIMIZE)

Hi Vignesh,
We actually have released a Python package: gurobimachinelearning which you can use for this.
You can find the GitHub here: Gurobi/gurobimachinelearning
And documentation here: Gurobi Machine Learning (particularly see the installation instructions)Here's the translated code (edit: with 10 output variables instead):
import gurobipy as gp
from gurobi_ml import add_predictor_constr
import tensorflow as tf
tf_model = tf.keras.models.load_model("peaks_3x10.h5")
print("loaded ML model")
with gp.Model() as m:
input_vars = m.addVars(2, lb=3, ub=3, vtype=gp.GRB.CONTINUOUS)
output_vars = m.addVars(
10,
lb=gp.GRB.INFINITY,
ub=gp.GRB.INFINITY,
vtype=gp.GRB.CONTINUOUS,
name="output",
)
m.update()
pred_constr = add_predictor_constr(m, tf_model, input_vars, output_vars)
pred_constr.print_stats()
m.setObjective(output_vars.sum(), gp.GRB.MINIMIZE)
m.optimize()Cheers,
David0 
Hi David,
Thanks for your response. Basically I am looking for AnnModel lib function to leverage for my problem. The code you mentioned top is using the general ml. Kindly can you specify if the AnnModel lib function is still being used separately.? Also can you confirm with the below line, can I loop over to generate 10 diff 10 embed_network_formulations..? It would be great if we can connect on call to resolve.?
with gp.Model() as m:
0 
Just to add to my above comment, looks like the "with gp. model() as m" is performing the optimization separately instead I need to optimize the 10 different models at a time.
Lets say : I have the obj as
max : c1*x1 + c2*x2 + h1*y1 + h2*y2
const1: f(x1) = y1
const2 : f(x2) = y2
x, y belongs to X lets say.
Here f(x1) and f(x2) are my ann models which are supposed to be in one optimization run instead of 2. So basically my f(x1) and f(x2) are not separable
0 
Hi Vignesh,
Unfortunately, I'm not familiar with the library's source code.
It looks like the latest release was a while ago.Please check out the library I linked above, as (I think) does the same thing and is frequently maintained.
Just to add to my above comment, looks like the "with gp. model() as m" is performing the optimization separately instead I need to optimize the 10 different models at a time.
No, this creates a single gurobipy model for all 10 MLmodels (see my updated example); hence they are all optimized simultaneously.
Cheers,
David0 
Hi David,
Thanks for your reply.
In your updated code, it looks like you're optimizing the output_vars.sum() with output_vars being considered as 10 diff MLmodels outputs and finally optimizing the sum of these 10. Rather I am wondering if we can do it individually and access the individually optimized model.
For example: Lets say I have supplydemand constraint problem. Here is how I modeled it
input_vars = m.addVars(2, lb=3, ub=3, vtype=gp.GRB.CONTINUOUS)
output_vars = m.addVars(
10,
lb=gp.GRB.INFINITY,
ub=gp.GRB.INFINITY,
vtype=gp.GRB.CONTINUOUS,
name="output",
)
m.update()
pred_constr = gurobi_ml.keras.add_keras_constr(m, tf_model, input_vars, output_vars)
pred_constr.print_stats()
m.setObjective(
(
gp.quicksum(
demandProb["p"][p] * dcost * distanceCF[c, f] * x[p, c, f] for c, f in cf
)
+ gp.quicksum(tfcost * (1  setup[current, f]) * y[f] for f in facility)
+ output_vars[p]
for p in range(10)
),
GRB.MINIMIZE,
)
# x[p,c,f] <= bpi #supply constraints
# x[p,c,f] >= apj # demand constraints
m.optimize()Comments: As shown above this is what I am expecting to be done. If you see my overall model is getting optimized for every ML models individually with output_vars[p] for every p in range of 10.
The question here is : Since output_vars is being created 10 times by considering 10 ML models. However I am not able to optimize at p level(I mean individual level) in one gurobi model.
Also is there a way to set up my supplydemand constraints to be considered in the ML model.? or the way I have written is enough to be considered at every node in the ML model).?
0 
Hi David,
Any idea about my above query.?
Thanks!
Vignesh
0 
Hi Vignesh,
I guess you can add a model with the supplydemand constraints and variables as well, just normally using standard gurobipy (see Python Examples for simple examples and modeling examples for more complex supply network design).
I don't know that much on this topic so I'm not sure how you can only optimise each level. Perhaps there is a miscommunication between our terms. The package translates the keras model to a mixed integer program (MIP) this is the single \(\texttt{gp.Model}\). The translation depends on how many input variables and output variables you choose (of course the keras model doesn't allow any number of these). The objective of this MIP can be changed but the constraints represent the keras model in the variables you define (not optimised just satisfied as constraints).Cheers,
David0 
I will ask someone that knows more about this.
0 
Hi Vignesh,
I am trying to understand what you want to do but it is not clear to me.
In your first comment, you said that you want to run the "model" 10 times but then you say you want to embed 10 neural networks.
So to understand better:
 How many different neural networks do you have? (i.e. do you have one h5 file or several?)
 How many optimization models do you want to solve in total: 1 or 10?
Mayybe what you are looking for is some sort of multiobjective formulation but it is not clear to me. If you have a full description of the mathematical model you want to solve, it would be easier to help you.
1 
Hi Pierre,
Thanks for taking my question.
To answer your questions:
1. I have got 1 neural network i.e. one h5 file.
2. Basically I will have to run this NN model n times(per say in this case 10 times) and optimize every model in the loop.
Here is my code which is currently running. But I do see my model running into infeasibility.
import gurobipy as gp
from gurobi_ml import add_predictor_constr
import tensorflow as tf
from gurobipy import GRB
opt_model = gp.Model()
tf_model = {}
for p in range(10):
tf_model[p] = tf.keras.models.load_model("model.h5")
print(tf_model[p])
state = 0
pred_constr = {}
facilities = [*range(1, 24)]
def input_features():
input_vars1 = []
f = opt_model.addVars(facilities, lb=50, ub=300, vtype=GRB.CONTINUOUS)
y = opt_model.addVars(facilities, lb=0, ub=1, vtype=GRB.BINARY)
# x = opt_model.addVars(facilities, lb =0, ub = 300,vtype=GRB.CONTINUOUS)
# w = opt_model.addVars(cf, lb =0, ub = 300,vtype=GRB.CONTINUOUS)
input_vars1.extend(f.values())
input_vars1.extend(y.values())
opt_model.update()
return input_vars1
output_vars = opt_model.addVars(
10,
lb=gp.GRB.INFINITY,
ub=gp.GRB.INFINITY,
vtype=gp.GRB.CONTINUOUS,
name="output",
)
opt_model.update()
for p in range(10):
input_vars1 = input_features()
# output_vars = output_response()
pred_constr[p] = add_predictor_constr(
opt_model, tf_model[p], input_vars1, output_vars[p]
)
pred_constr[p].print_stats()
opt_model.setObjective(gp.quicksum(output_vars[p] for p in range(10)), gp.GRB.MINIMIZE)
opt_model.optimize()This above code constructs 10 diff embed networks and solve for every network in a loop. I am kind of wondering why model is running into infeasibility few nodes and taking ever and ever. Ofcourse my h5 file is appropriate and with r2 value ~65%Let me know your thoughts on my understanding and working functionality.Thanks!Vignesh0 
Hi Vignesh,
I don't think that the model above completely matches what you describe.
In the model I see that 10 networks would be added to the optimization problem and then you minimize the sum of the output of these networks.
What are the sizes of the networks that you are adding?
Indeed I don't see why this model would be infeasible. Could you please copy the log of Gurobi that you get?
Thanks,
Pierre
0 
Here is the screenshot of my nn model9, likewise as you rightly pointed I have got 10 such models every model is the same with 46 feature variables and one output variable.
Also Here is the log of the model: This is taking ever and ever, hence I terminated after an hour or so
0 
From the log it looks that the resulting model is very hard to optimize.
Unfortunately formulation with neural networks can be very challenging.
What you could try first is adding only one network and see how it goes.
Then adding 2, probably adding each network will make the optimization exponentially harder.
If you can and want to share the model I could have a look at it to see if there is something that can be done to solve it faster (since we have the python code, we would only need the h5 file).
I won't be able to look at it before the middle of next week though.
Best,
Pierre
0 
Hi Pierre,
Thanks for your response.
I am not sure how to upload the .h5 file here. Kindly can you share your emailid or any link to share the file.
Thanks!
Vignesh
0 
Hi Vignesh
You can upload the file to a filesharing platform of your choosing (e.g. Dropbox or Drive) and share the link with us here.
Cheers,
David0 
Hi David Torres Sanchez, Pierre Bonami,
Here is my H5 model file.
Let me know if you can access this file.
Thanks!
Vignesh
0 
Just to add to my above comments, I was thinking to do warm start my problem by providing a few known solutions to the nn model. But I am thinking what exactly the below line is doing in general.? does it constructs constraints at every node of the neural net.? kindly can you shed some light here.?
pred_constr = add_predictor_constr(m, tf_model, input_vars, output_vars)
0 
Hi Vignesh,
Yes I could download the network file and reproduce the model.
It's indeed very tough to solve.
I could at least get some solutions by changing some parameters of Gurobi, namely with
opt_model.params.PreSOS1BigM = 1e8
opt_model.params.OBBT=3
opt_model.params.MIRCuts = 2The first parameter is to be more aggressive in the formulation of the neural network the two others are to be very aggressive with some techniques that are usually useful for neural networks formulation.
With those it took me some minutes but I got some solutions.
I'll try to see if something else can be done but for some reason the problem is very tough even if I only add one neural network.
To answer your second question, yes we do a full model of the neural network with constraints representing each node of the neural network. You can look at "further reading" in our documentation for papers giving more details on how the networks can be formulated: https://gurobimachinelearning.readthedocs.io/en/stable/mlmfurtherreading.html
Our own formulation is described in the documentation also.
For reference, I use a slight variant of your code using Gurobi's matrix notations to avoid calling several times add_predictor_constr, this is the full code:
import gurobipy as gp
from gurobi_ml import add_predictor_constr
import tensorflow as tf
from gurobipy import GRBtf_model = tf.keras.models.load_model("model_actual.h5")
print(tf_model)# Parameters of the optimization model
facilities = 23
n_pred_constr = 10opt_model = gp.Model()
input_vars = opt_model.addMVar((n_pred_constr, 2*facilities))
output_vars = opt_model.addMVar(
(n_pred_constr,1),
lb=gp.GRB.INFINITY,
ub=gp.GRB.INFINITY,
vtype=gp.GRB.CONTINUOUS,
name="output",
)opt_model.update()
# First group of variables in the input matrix are continuous between 50 and 300
f = input_vars[:, :facilities]
f.LB = 50
f.UB = 300# Second groupd of variables in the input matrix are binary
y = input_vars[:, facilities:]
y.UB = 1.0
y.VType = GRB.BINARYopt_model.update()
# Add the predictor constraint
pred_constr = add_predictor_constr(
opt_model, tf_model, input_vars, output_vars
)
pred_constr.print_stats()# Setup objective
opt_model.setObjective(output_vars.sum(), gp.GRB.MINIMIZE)
opt_model.params.OBBT=3
opt_model.params.PreSOS1BigM = 1e8
opt_model.params.MIRCuts = 2
opt_model.optimize()0 
Thanks, Team @Pierre Bonami and @ David Torres Sanchez these are really helpful. Appreciate your help.
0 
Hi Pierre Bonami, just a quick question: Basically I have trained my model after transforming my feature variables via ztransformation, the same .h5 model read into the optimization. I would like to understand how would gurobi know the model that is read into optimization was trained after feature variable transformation.? Do I need to perform any inversetransformation before I feed the h5 model into the optimization.? Thanks for your valuable responses.
0 
Hi Vignesh,
I am not so familiar with how things are stored in the .h5 format. But if those transformation are not part of the neural network and the Keras model that is created from reading the h5 file, Gurobi wouldn't be able to know about it. So you would have to do the transformations.
Note that for Keras, we don't currently support many types of layers. In particular, we don't support any of the preprocessing layers. There is an issue in Gurobi ML about adding support for it:
https://github.com/Gurobi/gurobimachinelearning/issues/10
If there are some particular layers you would be interested in, you can add them there. And if you have some example, that would motivate us to implement them (not every layer can be implemented though).
(For scikitlearn we implement a number of preprocessing layers, then Gurobi ML can handle directly the transformation).
0
Please sign in to leave a comment.
Comments
21 comments