为什么在 Keras subclassing API 中,永远不会调用 call 方法,而是通过调用此 class 的对象来传递输入?

Why in Keras subclassing API, the call method is never called and as an alternative the input is passed by calling the object of this class?

在使用 Keras subclassing API 创建模型时,我们编写了一个自定义模型 class 并定义了一个名为 call(self, x) 的函数(主要用于编写前向pass) 需要一个输入。但是,此方法永远不会被调用,它不会将输入传递给 call,而是作为 model(images).

传递给此 class 的对象

当我们还没有实现 Python 特殊方法 __call__ 在 class[=20 中时,我们如何调用这个 model 对象并传递值=]

class MyModel(Model):
  def __init__(self):
    super(MyModel, self).__init__()
    self.conv1 = Conv2D(32, 3, activation='relu')
    self.flatten = Flatten()
    self.d1 = Dense(128, activation='relu')
    self.d2 = Dense(10, activation='softmax')

  def call(self, x):
    x = self.conv1(x)
    x = self.flatten(x)
    x = self.d1(x)
    return self.d2(x)

# Create an instance of the model
model = MyModel()

使用tf.GradientTape训练模型:

@tf.function
def train_step(images, labels):
  with tf.GradientTape() as tape:
    predictions = model(images)
    loss = loss_object(labels, predictions)
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

  train_loss(loss)
  train_accuracy(labels, predictions)

不应该像下面这样传递输入:

model = MyModel()
model.call(images)

奥卡姆剃刀说__call__方法是在Modelclass中实现的,所以你的subclass会继承这个方法,这就是调用有效的原因. Model class 中的 __call__ 只是将参数转发给您的 call 方法并进行一些簿记。

其实__call__方法是在Layerclass中实现的,它被Network继承,class又被[=14=继承] ] class:

class Layer(module.Module):
    def __call__(self, inputs, *args, **kwargs):

class Network(base_layer.Layer):

class Model(network.Network):

所以MyClass会继承这个__call__方法。

附加信息:

所以实际上我们所做的是覆盖继承的 call 方法,然后将从继承的 __call__ 方法调用新的 call 方法。这就是为什么我们不需要做 model.call()。 所以当我们调用我们的模型实例时,它继承的__call__方法会自动执行,即调用我们自己的call方法