我想将线性激活应用于我的Keras模型的大部分输出层,并将sigmoid激活应用于与张量中的其他数据交织的一组“列”。
根据this post on writing custom activations和this post on sliced assignment中的this other post about sliced assignment和@jdehesa的答案,我写了以下内容:
from keras.layers import Activation
from keras import backend as K
from keras.utils.generic_utils import get_custom_objects
import tensorflow as tf
def selective_activation(x, start=0, end=None, skip_every=6):
with tf.control_dependencies(x[:,start:end:skip_every].assign(K.sigmoid(x[:,start:end:skip_every]))):
x = tf.identity(x)
return x
model = Sequential()
model.add(...bunch of layers...)
model.add(Dense(),name="Final Layer")
get_custom_objects().update({'selective_activation': Activation(selective_activation)})
model.add(Activation(selective_activation))
...
运行此命令时,在带有ValueError: Sliced assignment is only supported for variables
上下文的行上收到错误“ tf.control_dependencies
”。我很困惑:Keras层的输出不是变量吗?
有人可以建议一种方法来实现我要完成的任务吗?
我只想出三种解决方案:
用tf.scatter_nd()或tf.scatter_update()做点什么...?
我可以想到的另一种选择,即重写代码其余部分中的所有其他内容,以将“存在”变量保持在一起,而不是与其他变量交织在一起……这将需要大量工作我不急于着手。
(顺便说一下,这是用于对象检测器的,以前它对所有变量都使用MSE损失,现在我想对“是否存在对象”类别产生交叉熵损失。)
答案 0 :(得分:0)
编辑:documentation for tf.where()包含
行“如果条件为等级1,则x可能具有更高的等级,但其第一个 尺寸必须与条件的大小匹配”
...因此,如果我们仅对x进行转置,则可以使用一维索引数组,而不必担心我们是否知道批处理大小,如下所示:
class SelectiveSigmoid(Layer):
def __init__(self, **kwargs):
self.start = kwargs.get('start', 0)
self.end = kwargs.get('end', None)
self.skip = kwargs.get('skip', 6)
super(SelectiveSigmoid, self).__init__(**kwargs)
def build(self, input_shape):
self.indices = np.zeros(input_shape[-1]) # Note that tf.cast allows a numpy array!
self.indices[self.start:self.end:self.skip] = 1
def call(self, x):
print("In call.... ")
print("x.get_shape().as_list()[0] = ",tf.shape(x)[0])
return tf.transpose(tf.where(tf.cast(self.indices, dtype=tf.bool), K.sigmoid(tf.transpose(x)), tf.transpose(x)))
def compute_output_shape(self, input_shape):
return input_shape
...然后这将毫无错误地运行,我们不需要需要预先知道批次的大小。
这似乎可以完成任务,但是我很乐意为别人可能提出的更好的方案投票!