在TensorFlow中实施权重约束的最佳方法是什么?

时间:2015-11-13 13:56:20

标签: tensorflow

假设我们有权重

x = tf.Variable(np.random.random((5,10)))
cost = ...

我们使用GD优化器:

upds = tf.train.GradientDescentOptimizer(lr).minimize(cost)
session.run(upds)

我们如何实施例如权重的非负性?

我试着剪掉它们:

upds = tf.train.GradientDescentOptimizer(lr).minimize(cost)
session.run(upds)
session.run(tf.assign(x, tf.clip_by_value(x, 0, np.infty)))

但是这会使我的训练减慢50倍。

有人知道在TensorFlow中对权重实施此类限制的好方法吗?

P.S。:在等效的Theano算法中,我有

T.clip(x, 0, np.infty)

它运行顺利。

5 个答案:

答案 0 :(得分:24)

您可以采用拉格朗日方法,只需为您不想要的变量的特征添加惩罚。

e.g。要鼓励 theta为非负数,您可以将以下内容添加到优化程序的目标函数中。

    added_loss = -tf.minimum( tf.reduce_min(theta),0)

如果任何theta为负数,则add2loss为正数,否则为零。将其缩放到有意义的值是留给读者的练习。缩放太少不会施加足够的压力。太多可能会使事情变得不稳定。

答案 1 :(得分:19)

从TensorFlow 1.4开始,有new argumenttf.get_variable允许传递在更新优化程序后应用的约束函数。这是一个强制执行非负面约束的例子:

with tf.variable_scope("MyScope"):
  v1 = tf.get_variable("v1", …, constraint=lambda x: tf.clip_by_value(x, 0, np.infty))
  

约束:一个可选的投影函数应用于   变量           由Optimizer更新后(例如用于实施规范)           层权重的约束或值约束)。功能必须           将未投影的Tensor作为输入,表示该值           变量并返回Tensor的预计值           (必须具有相同的形状)。约束是不安全的           在进行异步分布式培训时使用。

答案 2 :(得分:15)

运行

sess.run(tf.assign(x, tf.clip_by_value(x, 0, np.infty)))

您一直在向图表添加节点并使其变慢和变慢。

实际上,您可以在构建图表时定义clip_op,并在每次更新权重后运行它:

# build the graph
x = tf.Variable(np.random.random((5,10)))
loss = ...
train_op = tf.train.GradientDescentOptimizer(lr).minimize(loss)
clip_op = tf.assign(x, tf.clip(x, 0, np.infty))

# train
sess.run(train_op)
sess.run(clip_op)

答案 3 :(得分:1)

有一个实用的解决方案:您的成本函数可以由您编写,以便将高成本投入负权重。我在带有python的TensorFlow中的矩阵分解模型中做到了这一点,并且它运行得很好。对?我的意思是显而易见的。但没有其他人提及它,所以你去。编辑:我刚才看到Mark Borderding在我做之前还提供了另一种基于损失和成本的解决方案实施。

如果需要“最好的方式”,OP会问,那么呢? “最佳”可能实际上是特定于应用程序的,在这种情况下,您需要尝试使用 数据集的几种不同方法,并考虑您的应用程序要求。

以下是增加不需要的负解决方案变量成本的工作代码:

cost = tf.reduce_sum(keep_loss) + Lambda * reg # Cost = sum of losses for training set, except missing data.        
if prefer_nonneg: # Optionally increase cost for negative values in rhat, if you want that.
    negs_indices = tf.where(rhat < tf.constant(0.0))
    neg_vals = tf.gather_nd(rhat, negs_indices)
    cost += 2. * tf.reduce_sum(tf.abs(neg_vals))  # 2 is a magic number (empirical parameter)         

您可以自由使用我的代码,但如果您选择使用它,请给我一些信用。请在stackoverflow.com上提供此答案的链接。

这种设计被认为是一种软约束,因为如果你愿意,你仍然可以得到负权重,具体取决于你的成本定义。

似乎约束=在TF v1.4 +中也可用作tf.get_variable()的参数,您可以在其中传递类似tf.clip_by_value的函数。在我看来,这似乎是另一种软约束,而不是硬约束,因为它取决于你的功能是否运作良好。它也可能很慢,因为另一个应答者尝试了相同的功能并报告它收敛缓慢,尽管他们没有使用constraint =参数来做到这一点。我没有看到为什么一个会比另一个更快的原因,因为他们都使用相同的剪辑方法。因此,如果您使用constraint =参数,那么您应该期望在原始海报的应用程序的上下文中收敛缓慢。

如果TF也为API提供了真正的硬约束,那将会更好。让TF弄清楚如何实现它以及在后端使其高效。我的意思是,我已经在线性编程求解器中看到了这个已经很长时间了。应用程序声明了一个约束,后端使它发生。

答案 4 :(得分:1)

我最近也有这个问题。我发现你可以导入具有良好权重约束函数的keras,直接在tensorflow中的kernen约束中使用它们。这是我的代码示例。你可以用kernel regularizer做类似的事情

from keras.constraints import non_neg

conv1 = tf.layers.conv2d(
    inputs=features['x'],
    filters=32,
    kernel_size=[5,5],
    strides = 2,
    padding='valid',
    activation=tf.nn.relu,
    kernel_regularizer=None,
    kernel_constraint=non_neg(),
    use_bias=False)