Как использовать переменную gurobi в качестве входных данных для модели tensorflow?

#python #tensorflow #machine-learning #model #gurobi

#python #тензорный поток #машинное обучение #Модель #gurobi

Вопрос:

В модели gurobi мне нужно использовать переменную (добавленную через addVar) в качестве входных данных для модели тензорного потока (я использовал простую модель, обученную следовать функции: y = 2x 1), которая затем используется в ограничении.

Модель tensorflow уже обучена и загружена, мне просто нужно использовать метод predict .

Проблема оптимизации заключается в следующем: получить наилучшие входные данные для модели tensorflow, чтобы прогноз вывода был наиболее близок к заданной ссылке.

Например, если я хочу, чтобы прогноз был равен 11, входные данные модели должны быть очень близки к 5 (2*5 1 = 11). Способ, которым я это реализовал, заключается в использовании целевой функции абсолютной ошибки между эталонным значением и прогнозируемым, путем линеализации функции abs(), чтобы иметь возможность использовать ее в Gurobi.

Модель gurobi верна, проблема заключается в использовании переменной gurobi в качестве входных данных для модели tf, потому что, пока проблема оптимизации не решена, она не имеет определенного значения (присвоение ей начального значения не сработает).

Это код для моей модели:

 import gurobipy as gp

# Load tensorflow model
model = tf.keras.models.load_model('./models/test_model.h5')

mdl = gp.Model()
ref = 11 # desired output value

w = mdl.addVar(lb=-10, name='input')
a = ref # just for naming purposes
b = mdl.addVar(lb=-10,name = "b")
x = mdl.addVar(name='error') # variable needed to linealize abs() function

mdl.update()

# objective function is abs(ref - model.predict([w])[0][0])
mdl.setObjective(x, gp.GRB.MINIMIZE)

mdl.addConstr(w <= 10)
mdl.addConstr(w >= -10)

# mdl.addConstr(b == 2*w 1) # if I use this line instead of the next one, everything works but I am not using the tensorflow model
mdl.addConstr(b == model.predict([w])[0][0]) # does not work

# 3 constraints needed for the abs() linealization
mdl.addConstr(x >= 0)
mdl.addConstr(a - b <= x)
mdl.addConstr(b - a <= x)
mdl.update()

# Solve and show solution
mdl.optimize()
for v in mdl.getVars():
    print('%s %g' % (v.varName, v.x))
print('2w 1 =', 2*w.X 1)
 

И данная ошибка:

 ---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~AppDataLocalTemp/ipykernel_6484/1577208091.py in <module>
     16 
     17 # mdl.addConstr(b == 2*w 1) # if I use this line instead of the next one, everything works but I am not using the tensorflow model
---> 18 mdl.addConstr(b == model.predict([w])[0][0]) # does not work
     19 
     20 # 3 constraints needed for the abs() linealization

~AppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packageskerasenginetraining.py in predict(self, x, batch_size, verbose, steps, callbacks, max_queue_size, workers, use_multiprocessing)
   1718                         '. Consider setting it to AutoShardPolicy.DATA.')
   1719 
-> 1720       data_handler = data_adapter.get_data_handler(
   1721           x=x,
   1722           batch_size=batch_size,

~AppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packageskerasenginedata_adapter.py in get_data_handler(*args, **kwargs)
   1381   if getattr(kwargs["model"], "_cluster_coordinator", None):
   1382     return _ClusterCoordinatorDataHandler(*args, **kwargs)
-> 1383   return DataHandler(*args, **kwargs)
   1384 
   1385 

~AppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packageskerasenginedata_adapter.py in __init__(self, x, y, sample_weight, batch_size, steps_per_epoch, initial_epoch, epochs, shuffle, class_weight, max_queue_size, workers, use_multiprocessing, model, steps_per_execution, distribute)
   1135       self._steps_per_execution_value = steps_per_execution.numpy().item()
   1136 
-> 1137     adapter_cls = select_data_adapter(x, y)
   1138     self._adapter = adapter_cls(
   1139         x,

~AppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packageskerasenginedata_adapter.py in select_data_adapter(x, y)
    974   if not adapter_cls:
    975     # TODO(scottzhu): This should be a less implementation-specific error.
--> 976     raise ValueError(
    977         "Failed to find data adapter that can handle "
    978         "input: {}, {}".format(

ValueError: Failed to find data adapter that can handle input: (<class 'list'> containing values of types {"<class 'gurobipy.Var'>"}), <class 'NoneType'>
 

Однако, если я использую строку над b == model.predict([w])[0][0] ограничением, все работает нормально, и найденное решение действительно равно 5:

 Gurobi Optimizer version 9.5.0 build v9.5.0rc5 (win64)
Thread count: 2 physical cores, 4 logical processors, using up to 4 threads
Optimize a model with 6 rows, 3 columns and 9 nonzeros
Model fingerprint: 0xc4fcfa7a
Coefficient statistics:
  Matrix range     [1e 00, 2e 00]
  Objective range  [1e 00, 1e 00]
  Bounds range     [1e 01, 1e 01]
  RHS range        [1e 00, 1e 01]
Presolve removed 4 rows and 1 columns
Presolve time: 0.01s
Presolved: 2 rows, 2 columns, 4 nonzeros

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    0.0000000e 00   1.050000e 01   0.000000e 00      0s
       1    0.0000000e 00   0.000000e 00   0.000000e 00      0s

Solved in 1 iterations and 0.04 seconds (0.00 work units)
Optimal objective  0.000000000e 00
input 5
b 11
error 0
2w 1 = 11.0
 

Ответ №1:

Вы просто не можете передать переменную Gurobi в модель TensorFlow. Это совершенно разные программные пакеты, которые не совместимы таким образом. Вы должны изучить, как использовать обратные вызовы Gurobi, чтобы увидеть, как вы можете вызывать разные коды из запущенной оптимизации. Пожалуйста, обратите внимание, что вы не можете изменять проблему по своему усмотрению во время выполнения обратного вызова. Вы также можете просто попробовать итеративный подход: оптимизировать, чтобы получить первую оценку, которую затем можно подключить к Tensorflow, а затем оптимизировать с использованием новой информации.

Я не уверен, какова цель вашего подхода, поэтому мои предложения могут быть неприменимы к вашей идее.

РЕДАКТИРОВАТЬ: возможно, вы сможете использовать этот инструмент для своего приложения: ReLU_ANN_MILP