如何设置 Tensorflow 变量的边界和约束 (tf.Variable)
How to set bounds and constraints on Tensorflow Variables (tf.Variable)
我正在使用 Tensorflow 来最小化一个函数。该函数需要大约 10 个参数。每个参数都有界限,例如参数允许采用的最小值和最大值。比如参数x1需要在1到10之间
我还有一对参数需要具有以下约束 x2 > x3。换句话说,x2 必须始终大于 x3。 (除此之外,x2和x3也有边界,类似于上面x1的例子。)
我知道 tf.Variable 有一个 "constraint" 参数,但是我真的找不到任何关于如何使用它来实现上述边界和约束的示例或文档。
谢谢!
在我看来(我可能会弄错)约束优化(您可以 google 在 tensorflow 中使用它)并不完全是 tensroflow 的情况设计的。你可能想看看this repo,它可能满足你的需求,但据我了解,它仍然没有解决任意约束优化,只是一些标签和特征的分类问题,兼容[=55= 】 分数。
如果你想对张量流变量使用约束(即在梯度步骤之后应用的一些函数 - 你也可以手动执行 - 通过获取变量值,进行操作,然后重新分配),这意味着你将在 general space 中使用梯度完成每个步骤后切割变量。这是一个问题,你是否会以这种方式成功达到正确的优化目标,或者你的变量会卡在边界处,因为 general
梯度会指向外面的某个地方。
我的做法1
如果你的问题足够简单。您可以尝试将 x2
和 x3
参数化为 x2 = x3 + t
,然后尝试在图中进行切割:
x3 = tf.get_variable('x3',
dtype=tf.float32,
shape=(1,),
initializer=tf.random_uniform_initializer(minval=1., maxval=10.),
constraint=lambda z: tf.clip_by_value(z, 1, 10))
t = tf.get_variable('t',
dtype=tf.float32,
shape=(1,),
initializer=tf.random_uniform_initializer(minval=1., maxval=10.),
constraint=lambda z: tf.clip_by_value(z, 1, 10))
x2 = x3 + t
然后,在单独的调用中另外执行
sess.run(tf.assign(x2, tf.clip_by_value(x2, 1.0, 10.0)))
但我认为它不会很好地工作。
我的做法2
我也会尝试发明一些损失项来将变量保持在约束范围内,这更有可能起作用。例如,x2 在区间 [1,10]
中的约束将是:
loss += alpha*tf.abs(tf.math.tan(((x-5.5)/4.5)*pi/2))
这里把tan
下面的表达式带入-pi/2,pi/2
,然后用tan
函数让它在到达边界的时候增长非常快。在这种情况下,我认为你更有可能找到你的最佳值,但如果 x2
的所需值位于边界附近,那么损失权重 alpha
可能太大并且训练将停留在附近的某个地方。在这种情况下,您可以尝试使用较小的 alpha
.
除了Slowpoke的回答之外,重新参数化是另一种选择。例如。假设你有一个参数 p
,它应该在 [lower_bound,upper_bound] 中,你可以这样写:
p_inner = tf.Variable(...) # unbounded
p = tf.sigmoid(p_inner) * (upper_bound - lower_bound) + lower_bound
但是,这会改变梯度下降的行为。
我正在使用 Tensorflow 来最小化一个函数。该函数需要大约 10 个参数。每个参数都有界限,例如参数允许采用的最小值和最大值。比如参数x1需要在1到10之间
我还有一对参数需要具有以下约束 x2 > x3。换句话说,x2 必须始终大于 x3。 (除此之外,x2和x3也有边界,类似于上面x1的例子。)
我知道 tf.Variable 有一个 "constraint" 参数,但是我真的找不到任何关于如何使用它来实现上述边界和约束的示例或文档。
谢谢!
在我看来(我可能会弄错)约束优化(您可以 google 在 tensorflow 中使用它)并不完全是 tensroflow 的情况设计的。你可能想看看this repo,它可能满足你的需求,但据我了解,它仍然没有解决任意约束优化,只是一些标签和特征的分类问题,兼容[=55= 】 分数。
如果你想对张量流变量使用约束(即在梯度步骤之后应用的一些函数 - 你也可以手动执行 - 通过获取变量值,进行操作,然后重新分配),这意味着你将在 general space 中使用梯度完成每个步骤后切割变量。这是一个问题,你是否会以这种方式成功达到正确的优化目标,或者你的变量会卡在边界处,因为 general
梯度会指向外面的某个地方。
我的做法1
如果你的问题足够简单。您可以尝试将 x2
和 x3
参数化为 x2 = x3 + t
,然后尝试在图中进行切割:
x3 = tf.get_variable('x3',
dtype=tf.float32,
shape=(1,),
initializer=tf.random_uniform_initializer(minval=1., maxval=10.),
constraint=lambda z: tf.clip_by_value(z, 1, 10))
t = tf.get_variable('t',
dtype=tf.float32,
shape=(1,),
initializer=tf.random_uniform_initializer(minval=1., maxval=10.),
constraint=lambda z: tf.clip_by_value(z, 1, 10))
x2 = x3 + t
然后,在单独的调用中另外执行
sess.run(tf.assign(x2, tf.clip_by_value(x2, 1.0, 10.0)))
但我认为它不会很好地工作。
我的做法2
我也会尝试发明一些损失项来将变量保持在约束范围内,这更有可能起作用。例如,x2 在区间 [1,10]
中的约束将是:
loss += alpha*tf.abs(tf.math.tan(((x-5.5)/4.5)*pi/2))
这里把tan
下面的表达式带入-pi/2,pi/2
,然后用tan
函数让它在到达边界的时候增长非常快。在这种情况下,我认为你更有可能找到你的最佳值,但如果 x2
的所需值位于边界附近,那么损失权重 alpha
可能太大并且训练将停留在附近的某个地方。在这种情况下,您可以尝试使用较小的 alpha
.
除了Slowpoke的回答之外,重新参数化是另一种选择。例如。假设你有一个参数 p
,它应该在 [lower_bound,upper_bound] 中,你可以这样写:
p_inner = tf.Variable(...) # unbounded
p = tf.sigmoid(p_inner) * (upper_bound - lower_bound) + lower_bound
但是,这会改变梯度下降的行为。