如何在TensorFlow v1中求神经网络表示的函数的逆,用于优化问题求解
TensorFlow v1实现神经网络表示函数逆的可行方案
TensorFlow v1没有内置针对神经网络映射的通用tf.inverse()接口,因为神经网络属于非线性复合映射,不存在通用解析逆,你可以根据你的使用场景选择以下两种方案实现:
方案1:参数化逆网络(最适配你的优化场景)
直接用独立的神经网络拟合V的逆映射,训练完成后即可直接调用该网络作为V的逆参与你后续的损失计算:
- 训练逻辑:固定已训练好的V*网络参数,训练逆网络
inv_V时同时最小化两个方向的重构误差:- 对任意输入x,
inv_V(V(x)) ≈ x的L2损失 - 对任意输入x,
V(inv_V(V(x))) ≈ V(x)的L2损失
- 对任意输入x,
- 参考代码(TF1静态图实现):
import tensorflow as tf # 配置参数 batch_size = 64 d_in = 10 # V*网络的输入维度 d_out = 10 # V*网络的输出维度,需和输入维度一致才能保证严格可逆 # 你的预训练值函数V*实现 def V_net(x, reuse=False): with tf.variable_scope('V_net', reuse=reuse): x = tf.layers.dense(x, 64, activation=tf.nn.relu) x = tf.layers.dense(x, 32, activation=tf.nn.relu) x = tf.layers.dense(x, d_out, activation=None) return x # 逆网络实现 def inv_V_net(y, reuse=False): with tf.variable_scope('inv_V_net', reuse=reuse): y = tf.layers.dense(y, 64, activation=tf.nn.relu) y = tf.layers.dense(y, 32, activation=tf.nn.relu) y = tf.layers.dense(y, d_in, activation=None) return y # 构建逆网络训练图 x = tf.random_normal(shape=(batch_size, d_in)) v_x = V_net(x) inv_v_x = inv_V_net(v_x) recon_v = V_net(inv_v_x, reuse=True) # 逆网络训练损失 inv_loss = tf.reduce_mean(tf.square(inv_v_x - x)) + tf.reduce_mean(tf.square(recon_v - v_x)) # 只更新逆网络参数 inv_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='inv_V_net') train_inv_op = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(inv_loss, var_list=inv_vars) # 训练完成后,直接调用inv_V_net(y)即可得到V*在y处的逆值,参与你和C*的L2损失计算 c_star = # 你的近似最优函数C*网络输出 loss = tf.reduce_mean(tf.square(c_star - inv_V_net(v_x, reuse=True)))
方案2:数值迭代求逆(适合少量单点逆计算场景)
如果你不需要批量求逆,也可以对每个目标输出y,通过梯度下降迭代求解x使得V(x) ≈ y,收敛后的x即为V*在y处的逆:
- 实现逻辑:对每个目标y,初始化可训练变量x,迭代优化损失
||V(x) - y||²,迭代100~500步基本可以收敛到可用精度。
注意事项
- 只有当V*网络是单射映射(输入输出维度相同、没有多对一的映射关系)时,才存在严格的逆,否则上述方法得到的都是近似伪逆,训练时损失会存在不可降的下界。
- 如果你的V网络还未固定参数,可以和逆网络、C网络做端到端联合训练,不需要单独预训练逆网络。
内容的提问来源于stack exchange,提问作者ForumWhiner
相关产品推荐
相关产品推荐

