Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/366.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
Python 2x嵌套Tensorflow自定义层导致零可训练参数_Python_Tensorflow_Machine Learning_Deep Learning_Tensorflow2.0 - Fatal编程技术网

Python 2x嵌套Tensorflow自定义层导致零可训练参数

Python 2x嵌套Tensorflow自定义层导致零可训练参数,python,tensorflow,machine-learning,deep-learning,tensorflow2.0,Python,Tensorflow,Machine Learning,Deep Learning,Tensorflow2.0,我正在创建一系列自定义Tensorflow(版本2.4.1)层,遇到了一个问题,模型摘要显示了零可训练参数。下面是一系列示例,展示了在我添加最后一个自定义层之前,一切都是好的 以下是导入和自定义类: from tensorflow.keras.models import Model from tensorflow.keras.layers import (BatchNormalization, Conv2D, Input, ReLU,

我正在创建一系列自定义Tensorflow(版本
2.4.1
)层,遇到了一个问题,模型摘要显示了零可训练参数。下面是一系列示例,展示了在我添加最后一个自定义层之前,一切都是好的

以下是导入和自定义类:

from tensorflow.keras.models import Model
from tensorflow.keras.layers import (BatchNormalization, Conv2D, Input, ReLU, 
                                     Layer)

class basic_conv_stack(Layer):
    def __init__(self, filters, kernel_size, strides):
        super(basic_conv_stack, self).__init__()
        self.conv1 = Conv2D(filters, kernel_size, strides, padding='same')
        self.bn1 = BatchNormalization()
        self.relu = ReLU()

    def call(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        return x
    
class basic_residual(Layer):
    def __init__(self, filters, kernel_size, strides):
        super(basic_residual, self).__init__()
        self.bcs1 = basic_conv_stack(filters, kernel_size, strides)
        self.bcs2 = basic_conv_stack(filters, kernel_size, strides)

    def call(self, x):
        x = self.bcs1(x)
        x = self.bcs2(x)
        return x
    
class basic_module(Layer):
    def __init__(self, filters, kernel_size, strides):
        super(basic_module, self).__init__()
        self.res = basic_residual
        self.args = (filters, kernel_size, strides)
    
    def call(self, x):
        for _ in range(4):
            x = self.res(*self.args)(x)
        return x
现在,如果我执行以下操作,一切正常,我得到了300可训练参数:

input_layer = Input((128, 128, 3))
conv = basic_conv_stack(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
input_layer = Input((128, 128, 3))
conv = basic_residual(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
input_layer = Input((128, 128, 3))
conv = basic_module(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
类似地,如果我执行以下操作,我将获得1230个可训练参数:

input_layer = Input((128, 128, 3))
conv = basic_conv_stack(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
input_layer = Input((128, 128, 3))
conv = basic_residual(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
input_layer = Input((128, 128, 3))
conv = basic_module(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
但是,如果我尝试基本的_模块类,我得到的可训练参数为零:

input_layer = Input((128, 128, 3))
conv = basic_conv_stack(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
input_layer = Input((128, 128, 3))
conv = basic_residual(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
input_layer = Input((128, 128, 3))
conv = basic_module(10, 3, 1)(input_layer)

model = Model(input_layer, conv)
print (model.summary())
有人知道为什么会这样吗

编辑以添加:

我发现调用中使用的层必须在类的init中初始化才能正常工作。因此,如果我将基本模块更改为:

class basic_module(Layer):
    def __init__(self, filters, kernel_size, strides):
        super(basic_module, self).__init__()
        self.clayers = [basic_residual(filters, kernel_size, strides) for _ in range(4)]

    def call(self, x):
        for idx in range(4):
            x = self.clayers[idx](x)
        return x

一切正常。我不知道为什么会出现这种情况,所以我将保留这个问题,以防有人能够回答这个问题的原因。

您必须使用所需的参数初始化类实例,例如
过滤器
内核大小
跨步
到预定义的
基值
。此外,请注意,这些超参数与可训练权重属性相关

# >>> a = basic_module
# >>> a __main__.basic_module
# >>> a = basic_module(10, 3, 1)
# >>> a 
# >>> <__main__.basic_module at 0x7f6123eed510>

class basic_module(Layer):
    def __init__(self, filters, kernel_size, strides):
        super(basic_module, self).__init__()
        self.res = basic_residual # < ---
        self.args = (filters, kernel_size, strides)
    
    def call(self, x):
        for _ in range(4):
            x = self.res(*self.args)(x)
        return x
#>>>a=基本模块
#>>>一个主要的基本模块
#>>>a=基本模块(10,3,1)
#一个
# >>> 
类基本模块(层):
def uuu init uuuu(自身、过滤器、内核大小、步幅):
super(基本模块,self)。\uuuu init\uuuu()
self.res=基本剩余---
self.args=(过滤器、内核大小、步长)
def呼叫(自我,x):
对于范围(4)内的uu:
x=self.res(*self.args)(x)
返回x