假设我们有权重
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)
它运行顺利。
答案 0 :(得分:24)
您可以采用拉格朗日方法,只需为您不想要的变量的特征添加惩罚。
e.g。要鼓励 theta
为非负数,您可以将以下内容添加到优化程序的目标函数中。
added_loss = -tf.minimum( tf.reduce_min(theta),0)
如果任何theta
为负数,则add2loss为正数,否则为零。将其缩放到有意义的值是留给读者的练习。缩放太少不会施加足够的压力。太多可能会使事情变得不稳定。
答案 1 :(得分:19)
从TensorFlow 1.4开始,有new argument到tf.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)