cog-imperial / OMLT

Represent trained machine learning models as Pyomo optimization formulations
Other
262 stars 57 forks source link

Variable type for NN bounds #34

Closed tsaycal closed 2 years ago

tsaycal commented 2 years ago

I am confused about what format of input bounds should be passed with an onnx model to omlt. Trying a list or a dictionary:

lb = np.maximum(0, image - epsilon_infty)
ub = np.minimum(1, image + epsilon_infty)
input_bounds = [(float(l), float(u)) for l, u in zip(lb[0], ub[0])]

or

input_bounds = {}
for i in range(28*28):
    input_bounds[i] = (float(lb[0][i]), float(ub[0][i])) 

Attempting to create the omlt model with either:

write_onnx_model_with_bounds(f.name, None, input_bounds)
network_definition = load_onnx_neural_network_with_bounds(f.name)
formulation = NeuralNetworkFormulation(network_definition)
m = pyo.ConcreteModel()
m.nn = OmltBlock()
m.nn.build_formulation(formulation) 

Results in: ValueError: Variable 'bounds' keyword must be a tuple or function

fracek commented 2 years ago

If you have the onnx model (converted from Torch) you can use load_onnx_neural_network(onnx_model, input_bounds) without first writing to a file. Your input bounds dictionary looks good if the input of the NN is a 1-dimensional vector.

jalving commented 2 years ago

Can you check your version of Pyomo? You have to upgrade to version 6.2 to support dictionary bounds. Regardless, we should update OMLT requirements in the setup file.

tsaycal commented 2 years ago

Using the load_onnx_neural_network(onnx_model, input_bounds) produces the same error. The input is 1-dimensional:

Running input_layer = list(network_definition.input_layers)[0]; print(input_layer.input_indexes) produces:

[(0,), (1,), (2,), (3,), (4,) ..., (780,), (781,), (782,), (783,)]
tsaycal commented 2 years ago

Upgrading to Pyomo 6.2 fixed this issue. Thanks @jalving @fracek !