Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在keras层中包装python可调用_Python_Tensorflow_Machine Learning_Keras_Tensorflow2.0 - Fatal编程技术网

在keras层中包装python可调用

在keras层中包装python可调用,python,tensorflow,machine-learning,keras,tensorflow2.0,Python,Tensorflow,Machine Learning,Keras,Tensorflow2.0,在keras/tensorflow中,将层直接描述为将其输入映射到输出的函数通常非常简单,如下所示: def resnet_块(x,内核大小): ch=x.shape[-1] out=Conv2D(ch,内核大小,步幅=(1,1),padding='same',activation='relu')(x) out=Conv2D(ch,内核大小,步幅=(1,1),padding='same',activation='relu')(x) out=Add()([x,out]) 返回 而子类化层来获得

在keras/tensorflow中,将层直接描述为将其输入映射到输出的函数通常非常简单,如下所示:

def resnet_块(x,内核大小):
ch=x.shape[-1]
out=Conv2D(ch,内核大小,步幅=(1,1),padding='same',activation='relu')(x)
out=Conv2D(ch,内核大小,步幅=(1,1),padding='same',activation='relu')(x)
out=Add()([x,out])
返回
而子类化
来获得

r=ResNetBlock(内核大小=(3,3))
y=r(x)
有点麻烦(对于更复杂的示例,甚至麻烦得多)

由于keras似乎非常乐意在第一次调用层时构建其底层权重,我想知道是否可以只包装上面的函数,并在有输入时让keras解决问题,即,我希望它看起来像这样:

r=FunctionWrapperLayer(lambda x:resnet_块(x,kernel_大小=(3,3)))
y=r(x)
我尝试实现
FunctionWrapperLayer
,如下所示:

class FunctionWrapperLayer(层):
定义初始化(self,fn):
super(FunctionWrapperLayer,self)。\uuuu init\uuuuu()
self.fn=fn
def构建(自我,输入_形状):
形状=输入形状[1:]
输入=输入(形状)
输出=self.fn(输入)
self.model=模型(输入=输入,输出=输出)
self.model.compile()
def呼叫(自我,x):
返回自我模型(x)
这看起来可能有用,但是每当我使用激活时,我都会遇到一些奇怪的问题,例如

def坏(x):
out=tf.keras.activations.sigmoid(x)
out=Conv2D(1,(1,1),步长=(1,1),padding='same')(out)
返回
x=tf.constant(tf.reformate(tf.range(48,dtype=tf.float32),[1,4,-1,1])
w=FunctionWrapperLayer(坏)
w(x)
我得到以下错误

FailedPreconditionError:  Error while reading resource variable _AnonymousVar34 from Container: localhost. This could mean that the variable was uninitialized. Not found: Resource localhost/_AnonymousVar34/class tensorflow::Var does not exist.
     [[node conv2d_6/BiasAdd/ReadVariableOp (defined at <ipython-input-33-fc380d9255c5>:12) ]] [Op:__inference_keras_scratch_graph_353]
顺便提一下,
model.submodules

(<tensorflow.python.keras.engine.input_layer.InputLayer at 0x219d80c77c0>,
 <tensorflow.python.keras.engine.base_layer.TensorFlowOpLayer at 0x219d7afc820>,
 <tensorflow.python.keras.layers.convolutional.Conv2D at 0x219d7deafa0>)
(,
,
)
这意味着这样做时,激活会自动变成“TensorFlowPlayer”

另一更新:
查看原始错误消息,似乎激活不是唯一的罪魁祸首。如果我移除卷积并使用包装器,一切都会正常工作,然后再次找到“TensorFlowPlayer”当检查子模块时。

您的解决方案实际上是有效的!您遇到的问题是
tf.keras.activations.sigmoid
不是一个层,而是一个普通的Tensorflow函数。要使其有效,请使用
keras.layers.Activation(“sigmoid”)(x)
相反。对于更一般的情况,如果您想使用一些Tensorflow函数作为层,您可以将其包装在Lambda层中,如下所示:

out = keras.layers.Lambda(lambda x: tf.some_function(x))(out)

查看文档了解更多信息:

您的解决方案确实有效!您遇到的问题是
tf.keras.activations.sigmoid
不是一个层,而是一个普通的Tensorflow函数。要使其有效,请使用
keras.layers.Activation(“sigmoid”)(x)
相反。对于更一般的情况,如果您想使用一些Tensorflow函数作为层,您可以将其包装在Lambda层中,如下所示:

out = keras.layers.Lambda(lambda x: tf.some_function(x))(out)

有关更多信息,请参阅文档:

使用Tensorflow 2.4,它显然现在可以工作了。子模块现在显示了一个“TFOpLambda”层

对任何感兴趣的人来说,这里有一些稍微改进的包装器代码,它也适用于多输入模型:

class FunctionWrapperLayer(Layer):
    def __init__(self, fn):
        super(FunctionWrapperLayer, self).__init__()
        self.fn = fn
        
    def build(self, input_shapes):
        super(FunctionWrapperLayer, self).build(input_shapes)
        if type(input_shapes) is list:
            inputs = [Input(shape[1:]) for shape in input_shapes]
        else:
            inputs = Input(input_shapes[1:])
        outputs = self.fn(inputs)
        self.fn_model = Model(inputs=inputs, outputs=outputs)
        self.fn_model.compile()
        
    def call(self, x):
        return self.fn_model(x)

在Tensorflow 2.4中,它显然现在才起作用。子模块现在显示一个“TFOpLambda”层

对任何感兴趣的人来说,这里有一些稍微改进的包装器代码,它也适用于多输入模型:

class FunctionWrapperLayer(Layer):
    def __init__(self, fn):
        super(FunctionWrapperLayer, self).__init__()
        self.fn = fn
        
    def build(self, input_shapes):
        super(FunctionWrapperLayer, self).build(input_shapes)
        if type(input_shapes) is list:
            inputs = [Input(shape[1:]) for shape in input_shapes]
        else:
            inputs = Input(input_shapes[1:])
        outputs = self.fn(inputs)
        self.fn_model = Model(inputs=inputs, outputs=outputs)
        self.fn_model.compile()
        
    def call(self, x):
        return self.fn_model(x)

你可能是对的,但是当在构建方法之外构建模型时,我从来没有遇到过同样的错误。例如,当我做
I=Input(x.shape[1:])
o=bad(I)
model=model(inputs=I,outputs=o)
model(x)
它似乎可以工作。就API而言,这也是不允许的,我只是因为一些实现细节而侥幸逃脱了?我应该补充一点,我尝试过使用层而不是普通函数,这是我所能说的最有效的方法。我想当你在一个她的图层并将其添加为属性,外层会自动跟踪内部对象的权重(请参见)。因此,我猜它只会在自定义图层内抱怨sigmoid,因为它试图跟踪权重,但无法检查是否有要跟踪的权重(尽管我们知道它没有任何重量)因为乙状结肠不是一个合适的层。看第一条错误消息,似乎激活也不是真的有问题。我在没有后续卷积的情况下尝试了它,确实有效!真奇怪。我原来的帖子已经被修改以反映这些发现。我不知道你是否有任何其他想法。如果我没有如果有任何结论,我可能会回避实际使用我的包装器(尽管我当然想知道为什么我所做的是不允许的)@code我发现了更多的特性。将卷积放在
bad
中激活之前效果很好!似乎这就是失败的原因:在可调用的
层中有状态的
之前,任何时候都可以进行任何非
层的
操作(像
flatte
MaxPooling2D
这样的无状态层似乎还可以)。我不知道该怎么做。考虑到您可以将非层ops包装在
Lambda
层中,或者直接调用
bad
并完全避免包装器,似乎您可以解决它。但我很好奇为什么我们会看到这种行为。您可能是对的,但在构建外部模型时遇到了问题我从来没有遇到过同样的错误。例如,当我做
I=Input(x.shape[1:])