【问题标题】:How come there are two positional arguments when I put only one?当我只放一个时,为什么会有两个位置参数?
【发布时间】:2019-04-07 16:26:55
【问题描述】:

以下代码用于在带有 tensorflow 后端的 keras 中定义 CNN 架构:

class DownBlock(object):
    def __init__(self, prev_layer, num_chann = 16, depthwise_initializer = 'glorot_uniform', kernel_initializer = 'glorot_uniform', bias_initializer = 'zeros', drop_rate = None, spdrop_rate = None, activation = 'relu', pool = True):

        self.prev_layer = prev_layer

        if pool == True:
            self.prev_layer = MaxPooling2D((2, 2)) (self.prev_layer)
            self.prev_layer = Conv2D(num_chann, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.prev_layer)

        self.convo = Activation(activation) (self.prev_layer)
        self.convo = BatchNormalization() (self.convo)
        if not spdrop_rate == None:             
            self.convo = SpatialDropout2D(spdrop_rate) (self.convo)
        if not drop_rate == None:             
            self.convo = Dropout(drop_rate) (self.convo)

        self.convo = Conv2D(num_chann, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.convo)
        self.convo = DepthwiseConv2D((3, 3), depthwise_initializer = depthwise_initializer, bias_initializer = bias_initializer, padding = 'same') (self.convo)
        self.convo = Conv2D(num_chann, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.convo)

        self.convo = Activation(activation) (self.convo)
        self.convo = BatchNormalization() (self.convo)
        if not spdrop_rate == None:             
            self.convo = SpatialDropout2D(spdrop_rate) (self.convo)
        if not drop_rate == None:             
            self.convo = Dropout(drop_rate) (self.convo)

        self.convo = DepthwiseConv2D((3, 3), depthwise_initializer = depthwise_initializer, bias_initializer = bias_initializer, padding = 'same') (self.convo)
        self.convo = Conv2D(num_chann, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.convo)

        self.convo = Add([self.prev_layer, self.convo])

    def get(self):
        return self.convo

class UpBlock(object):
    def __init__(self, prev_layer, bridge_layer, num_chann = 16, depthwise_initializer = 'glorot_uniform', kernel_initializer = 'glorot_uniform', bias_initializer = 'zeros', drop_rate = None, spdrop_rate = None, activation = 'relu', up = True):

        self.prev_layer = prev_layer
        self.bridge_layer = bridge_layer

        self.convo = Activation(activation) (self.prev_layer)
        self.convo = BatchNormalization() (self.convo)
        if not spdrop_rate == None:             
            self.convo = SpatialDropout2D(spdrop_rate) (self.convo)
        if not drop_rate == None:             
            self.convo = Dropout(drop_rate) (self.convo)

        self.convo = Conv2D(num_chann, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.convo)
        self.convo = DepthwiseConv2D((3, 3), depthwise_initializer = depthwise_initializer, bias_initializer = bias_initializer, padding = 'same') (self.convo)
        self.convo = Conv2D(num_chann, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.convo)

        self.convo = Activation(activation) (self.convo)
        self.convo = BatchNormalization() (self.convo)
        if not spdrop_rate == None:             
            self.convo = SpatialDropout2D(spdrop_rate) (self.convo)
        if not drop_rate == None:             
            self.convo = Dropout(drop_rate) (self.convo)

        self.convo = DepthwiseConv2D((3, 3), depthwise_initializer = depthwise_initializer, bias_initializer = bias_initializer, padding = 'same') (self.convo)
        self.convo = Conv2D(num_chann, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.convo)

        self.convo = Add([self.prev_layer, self.convo])

        if up == True:
            self.convo = Conv2D(num_chann/2, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.convo)
            self.convo = Conv2DTranspose(num_chann/2, (2, 2), strides = (2, 2), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer, padding = 'same') (self.convo)

        self.convo = Add([self.bridge_layer, self.convo])

    def get(self):
        return self.convo



inputs = Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))
s = Lambda(lambda x: x / 255) (inputs)
s = Conv2D(8, (1, 1)) (s)

d1 = DownBlock(s, num_chann = 16, drop_rate = 0.1)

d2 = DownBlock(d1.get(), num_chann = 32, drop_rate = 0.1)

d3 = DownBlock(d2.get(), num_chann = 64, drop_rate = 0.1)

d4 = DownBlock(d3.get(), num_chann = 128, drop_rate = 0.1)

d5 = DownBlock(d4.get(), num_chann = 256, drop_rate = 0.1)

m = DownBlock(d5.get(), num_chann = 512, drop_rate = 0.1)

u5 = UpBlock(m.get(), d4.get(), num_chann = 256, drop_rate = 0.1)

u4 = UpBlock(u5.get(), d3.get(), num_chann = 128, drop_rate = 0.1)

u3 = UpBlock(u4.get(), d2.get(), num_chann = 64, drop_rate = 0.1)

u2 = UpBlock(u3.get(), d1.get(), num_chann = 32, drop_rate = 0.1)

u1 = UpBlock(u2.get(), s, num_chann = 16, drop_rate = 0.1)

final = Conv2D(1, (1, 1)) (u1.get())
# final = SpatialDropout2D(0.1) (final)
final = Dropout(0.1) (final)
final = BatchNormalization() (final)
outputs = Activation("sigmoid") (final)

model = Model(inputs = [inputs], outputs = [outputs])

在 Jupyter 笔记本中执行时,会生成以下堆栈跟踪:

TypeError                                 Traceback (most recent call last)
<ipython-input-31-f23b70d0be6d> in <module>()
    79 s = Conv2D(8, (1, 1)) (s)
    80 
---> 81 d1 = DownBlock(s, num_chann = 16, drop_rate = 0.1)
    82 
    83 d2 = DownBlock(d1.get(), num_chann = 32, drop_rate = 0.1)

<ipython-input-31-f23b70d0be6d> in __init__(self, prev_layer, num_chann, depthwise_initializer, kernel_initializer, bias_initializer, drop_rate, spdrop_rate, activation, pool)
    29         self.convo = Conv2D(num_chann, (1, 1), kernel_initializer = kernel_initializer, bias_initializer = bias_initializer) (self.convo)
    30 
---> 31         self.convo = Add([self.prev_layer, self.convo])
    32 
    33     def get(self):

TypeError: __init__() takes 1 positional argument but 2 were given

跟踪中的最后一行 ...

TypeError: __init__() takes 1 positional argument but 2 were given

...谈到将两个位置参数传递给第一个 UpBlock() 调用,而我显然传递了一个-

d1 = DownBlock(s, num_chann = 16, drop_rate = 0.1)

另一个位置参数在哪里?如果没有,为什么我会收到此错误?

【问题讨论】:

标签: python python-3.x machine-learning keras deep-learning


【解决方案1】:

虽然错误源于您对DownBlock 的构造函数的调用,但Python 也注意到错误回溯是(most recent call last)。此错误是指将两个参数传递给Add 构造函数。 Python 告诉你的是,你对Add() 的调用有太多参数。

这里的窍门,虽然看起来您只向Add() 提供了一个列表参数,但Python 类构造函数都接收一个隐式self 参数作为它们的第一个位置参数。见the Python docs

来自 cmets:

在 Keras 中使用函数式 API 时,必须首先创建层对象,如 a = Add(),然后必须通过调用结果对象将层添加到计算图中,如下所示:

out = a([input1, input2, ...])

或者在你原来的例子中:

self.convo = Add()([self.prev_layer, self.convo])

【讨论】:

  • 这个答案基本上是正确的,但可以扩展如下:在 Keras 中使用函数式 API 时,必须首先创建层对象,如 a = Add(),然后必须将层添加到通过调用out = a([input1, input2, ...]) 中的结果对象来计算图。
  • 我会更新以纳入更详尽的解释
  • 所以@quiet_laika 这意味着 Add() 不接受除了隐含的“自我”之外的任何位置争论,如果我做对了吗?
  • @Asef 大部分是正确的。我在这里做了一点挖掘:github.com/keras-team/keras/blob/master/keras/layers/merge.py 并且要 100% 准确,看起来 Add() 继承了 __init__() 的方法 _Merge,它需要一些可选的关键字参数。这意味着_Merge 的某些实例可能有参数,但似乎Add 没有具体参数。
猜你喜欢
  • 2019-09-18
  • 1970-01-01
  • 2020-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多