Python Tensorflow,Keras:如何在具有停止梯度的Keras层中设置附加损耗? 问题1
我们知道我们可以使用Python Tensorflow,Keras:如何在具有停止梯度的Keras层中设置附加损耗? 问题1,python,tensorflow,keras,Python,Tensorflow,Keras,我们知道我们可以使用tf.stop\u梯度(B)来防止变量B在反向传播中被训练。但是我不知道如何在一定的损失中阻止B 简单来说,假设我们的损失是: loss = categorical_crossentropy + my_loss B = tf.stop_gradient(B) 其中分类交叉熵和我的损失都取决于B。因此,如果我们为B设置停止梯度,它们都将B作为常数 但是我如何只设置my_lossstop gradient w.r.tB,保持categorical_crossentropy不变?
tf.stop\u梯度(B)
来防止变量B
在反向传播中被训练。但是我不知道如何在一定的损失中阻止B
简单来说,假设我们的损失是:
loss = categorical_crossentropy + my_loss
B = tf.stop_gradient(B)
其中分类交叉熵和我的损失都取决于B
。因此,如果我们为B
设置停止梯度,它们都将B
作为常数
但是我如何只设置my_loss
stop gradient w.r.tB
,保持categorical_crossentropy
不变?类似于B=tf.stop\u梯度(B,myloss)
我的代码是:
这样行吗?或者,如何使其工作
问题2 好的,伙计们,如果Q1可以解决,我最后的任务是如何在自定义层中做到这一点 具体来说,假设我们有一个自定义层,该层仅具有可训练权重
a
和B
和自损耗my_loss
class My_层(keras.layers.Layer):
定义初始(自我,**kwargs):
超级(我的图层,自我)。\uuuuu初始化(**kwargs)
def构建(自我,输入_形状):
self.w=self.add_重量(name='w',trainable=True)
self.B=self.add_weight(name='B',trainable=True)
我的损失=w*B
#tf.停止梯度(w)
添加损失(我的损失)
如何使w
仅可用于模型损耗(MSE、交叉熵等)的培训,以及B
仅可用于my_损耗的培训
如果我添加了tf.stop\u gradient(w)
,那么它是只为my\u损失
而停止,还是为模型的最终损失而停止?问题1
运行y=tf.stop\u gradient(x)
时,创建一个StopGradient
操作,其输入为x
,输出为y
。此操作的行为类似于标识,即x
的值与y
的值相同,只是梯度不会从y
流向x
如果您想让渐变仅从某些损失流向B
,只需执行以下操作:
B_no_grad = tf.stop_gradient(B)
loss1 = get_loss(B) # B will be updated because of loss1
loss2 = get_loss(B_no_grad) # B will not be updated because of loss2
当您考虑正在构建的计算图时,事情应该变得清楚stop_gradient
允许您为任何不允许渐变通过的张量(不仅仅是变量)创建“标识”节点
问题2
我不知道在使用您使用字符串指定的模型丢失时如何执行此操作(例如,model.compile(loss='classifical\u crossentropy',…)
因为你不能控制它的构造。但是,你可以通过使用添加损耗或使用模型输出自己构建模型级损耗来实现。对于前者,只需使用普通变量创建一些损耗,使用*\u no\u grad
版本创建一些损耗,然后使用添加损耗()
,然后用loss=None
编译你的模型,不过这里说你可以传递一个函数到compile
,而不仅仅是一个字符串,比如model.compile(loss=loss.mean\u squared\u error,optimizer='sgd')
而不是model.compile(loss='mean\u squared\u error',optimizer='sgd'))
如果我想让loss1的梯度只影响第1-2层(而不是第3-4层)的权重,让Loss2的梯度只影响第3-4层(而不是第1-2层),该怎么办。这正是您想要的。例如,当您试图向变分自动编码器添加两个不同的自定义正则化项时,一个仅用于编码器,另一个仅用于解码器,而它们必须进行联合训练。@Kristof您有没有想过这一点?如何让loss1仅影响层1-2,而loss2仅影响层1-2第3-4层?
B_no_grad = tf.stop_gradient(B)
loss1 = get_loss(B) # B will be updated because of loss1
loss2 = get_loss(B_no_grad) # B will not be updated because of loss2