如何将Gurobi变量作为TensorFlow模型输入并用于优化约束?
问题分析与解决方案
报错原因
报错本质是类型不兼容问题:TensorFlow的predict方法仅支持接收数值型输入,而你传入的w是gurobipy.Var类型的符号变量,在Gurobi求解完成前它没有确定的实际取值,仅作为优化问题中的占位符号存在,因此TensorFlow无法识别处理这类输入。
可行解决方案
方案1:提取TF模型参数转为Gurobi约束(适用于线性/分段线性TF模型)
如果你的TensorFlow模型是线性结构、或者仅包含ReLU这类可以线性化的激活函数,可以直接提取模型的权重、偏置参数,转换为Gurobi原生支持的约束形式,既可以用到训练好的TF模型参数,又不会有类型兼容问题。如果模型包含ReLU激活,只需要对每个隐藏层的输出用大M法构造分段线性约束即可适配。
以你的测试模型为例,实现代码如下:
import gurobipy as gp import tensorflow as tf # 加载tensorflow模型 model = tf.keras.models.load_model('./models/test_model.h5') # 提取模型权重和偏置 weight = model.get_weights()[0][0][0] bias = model.get_weights()[1][0] mdl = gp.Model() ref = 11 # 期望输出值 w = mdl.addVar(lb=-10, name='input') a = ref b = mdl.addVar(lb=-10,name = "b") x = mdl.addVar(name='error') # 用于线性化abs()的变量 # 目标函数是min abs(ref - 预测值) mdl.setObjective(x, gp.GRB.MINIMIZE) mdl.addConstr(w <= 10) mdl.addConstr(w >= -10) # 用TF模型提取的参数构造约束 mdl.addConstr(b == weight * w + bias) # abs()线性化所需约束 mdl.addConstr(x >= 0) mdl.addConstr(a - b <= x) mdl.addConstr(b - a <= x) # 求解并输出结果 mdl.optimize() for v in mdl.getVars(): print('%s %g' % (v.varName, v.x)) print('2w+1 =', 2*w.X+1)
运行后会和你用手写线性约束的结果完全一致。
方案2:迭代交替求解(适用于任意结构的TF模型)
如果你的TF模型包含无法线性化的非线性结构,就需要采用迭代的方式交替运行Gurobi求解和TF预测:
- 给Gurobi变量
w设置初始猜测值 - 将当前
w的取值传入TF模型预测得到b的取值 - 更新Gurobi模型的约束/目标,求解得到新的
w - 重复步骤2-3,直到
w的迭代变化量小于设定的收敛阈值即可停止。
内容的提问来源于stack exchange,提问作者Technoka
相关产品推荐
相关产品推荐

