Keras model.fit() 给出 TypeError: 'NoneType' 对象不可调用

Rut*_*edi 4 python python-3.x deep-learning keras tensorflow

我正在尝试用 Keras 来实现 Siamese Network 来实现一次性人脸识别模型。但我遇到了一个我无法理解的错误,需要一些帮助。

我使用的模型是一个编码器模型,它接收(299,299,3)图像(锚定图像、正图像以及负图像)并输出1000每个图像的维度编码向量。这类似于带有分类头的 InceptionV3 模型。我还使用自定义三元组损失函数来实现同样的目的。我的模型如下:

class SiameseNet(tf.keras.layers.Layer):

  def __init__(self, model):
    self.model = model  # This is the image feature extraction model (similar to InceptionV3)
    super().__init__()

  def call(self, feat):
    feats = self.model(feat[0])
    nfeats = self.model(feat[1])

    return [feats, nfeats]
Run Code Online (Sandbox Code Playgroud)

损失函数如下

def triplet_loss(y_true, y_pred, alpha=1e-2):
  return max(tf.reduce_sum((y_pred[0]-y_true)**2 - (y_pred[0]-y_pred[1])**2) + alpha, 0)
Run Code Online (Sandbox Code Playgroud)

共有三个数组,分别命名为images(锚图像) 和negatives(负图像),形状均为(500,299,299,3)(其中 500 是训练示例的数量) 和positives(正图像特征),形状均为(500,1000)。所有这些都是 numpy 数组。

我的模型代码如下所示

image_input = tf.keras.layers.Input(shape=(299,299,3), name='image_input')
negative_input = tf.keras.layers.Input(shape=(299,299,3), name='negative_input')

siamese = SiameseNet(image_features_extract_model)([image_input, negative_input])

model = tf.keras.Model(inputs=[image_input, negative_input], outputs=siamese)

model.compile(optimizer=tf.keras.optimizers.Adam(), loss=triplet_loss, metrics=['accuracy'])
Run Code Online (Sandbox Code Playgroud)

编译与输出配合良好

Model: "functional_3"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
image_input (InputLayer)        [(None, 299, 299, 3) 0                                            
__________________________________________________________________________________________________
negative_input (InputLayer)     [(None, 299, 299, 3) 0                                            
__________________________________________________________________________________________________
siamese_net (SiameseNet)        [(None, 1000), (None 23851784    image_input[0][0]                
                                                                 negative_input[0][0]             
==================================================================================================
Total params: 23,851,784
Trainable params: 23,817,352
Non-trainable params: 34,432
Run Code Online (Sandbox Code Playgroud)

但在跑步时

model.fit([images, negatives], positives, epochs=10, batch_size=8, verbose=2)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误,需要帮助

Epoch 1/10
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-16-83443f79d005> in <module>()
----> 1 model.fit([images, negatives], positives, epochs=10, batch_size=8, verbose=2)
      2 # model.fit(train, epochs=10, verbose=2)

3 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _method_wrapper(self, *args, **kwargs)
    106   def _method_wrapper(self, *args, **kwargs):
    107     if not self._in_multi_worker_mode():  # pylint: disable=protected-access
--> 108       return method(self, *args, **kwargs)
    109 
    110     # Running inside `run_distribute_coordinator` already.

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)
   1096                 batch_size=batch_size):
   1097               callbacks.on_train_batch_begin(step)
-> 1098               tmp_logs = train_function(iterator)
   1099               if data_handler.should_sync:
   1100                 context.async_wait()

/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/def_function.py in __call__(self, *args, **kwds)
    778       else:
    779         compiler = "nonXla"
--> 780         result = self._call(*args, **kwds)
    781 
    782       new_tracing_count = self._get_tracing_count()

/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/def_function.py in _call(self, *args, **kwds)
    805       # In this case we have created variables on the first call, so we run the
    806       # defunned version which is guaranteed to never create variables.
--> 807       return self._stateless_fn(*args, **kwds)  # pylint: disable=not-callable
    808     elif self._stateful_fn is not None:
    809       # Release the lock early so that multiple threads can perform the call

TypeError: 'NoneType' object is not callable
Run Code Online (Sandbox Code Playgroud)

我正在 CPU 上的 Google Colab 上运行代码。
请帮我解决这个问题。谢谢。

Rut*_*edi 8

我想在这里回答我自己的问题,因为我面临的问题完全不同,并且后来已经解决了。我的具体情况的问题是由于triplet_loss功能引起的。损失函数期望根据张量进行计算,而代码则根据 Numpy 数组进行计算。更改此设置修复了我的错误,并且代码现在运行良好。

函数的实现应该是

def triplet_loss(y_true, y_pred, alpha=0.2):
  return tf.maximum(tf.reduce_sum((y_pred[0]-y_true)**2) - tf.reduce_sum((y_pred[0]-y_pred[1])**2)) + tf.constant(alpha), tf.constant(0.0))

Run Code Online (Sandbox Code Playgroud)

这对我的案例有用。不需要进行其他更改。

PS:这里,alpha需要比我之前选择的值更大,并且学习率需要通过使用1e-2降低到1e-5

optimizer = tf.keras.optimizers.Adam(lr=1e-5)
Run Code Online (Sandbox Code Playgroud)

model.compile()