【问题标题】:Keras model.fit() giving out TypeError: 'NoneType' object is not callableKeras model.fit() 发出 TypeError: 'NoneType' object is not callable
【发布时间】:2021-01-18 08:22:42
【问题描述】:

我正在尝试使用 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]

损失函数如下

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)

共有三个数组,分别名为 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'])

编译与输出效果很好

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

但在运行时

model.fit([images, negatives], positives, epochs=10, batch_size=8, verbose=2)

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

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

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

【问题讨论】:

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


    【解决方案1】:

    我不知道它是否正是你要找的,但我可以得到一个形状相似的模型,如下所示。

    主要区别在于:

    1. return np.stack([feats,nfeats])
    2. 整个模型是 Sequential 模型,所以我不依赖 keras 来构建基于 Input 张量的任何东西(第一层除外)。
    3. SiameseNet 的输入是卷积层的输出,因此我对其进行切片以获得正确的形状。
    4. 我对@9​​87654325@ 使用了一个简单的 MLP,但这只是为了让它更易于使用。
    class SiameseNet(tf.keras.layers.Layer):
    
      def __init__(self, model):
        super().__init__()
        self.model = model  # This is the image feature extraction model (similar to InceptionV3)
    
      def call(self, feat):
        # I'm slicing the input this way because I'm expecting input from some convolutional layer
        feats = self.model(feat[:,:,0])
        nfeats = self.model(feat[:,:,1])
    
        # keras want this output insted of [feats, nfeats]
        return tf.stack([feats, nfeats])
    
    
    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)
    
    
    if __name__ == '__main__':
        # basic MLP for the siamese model
        mlp = tf.keras.models.Sequential()
        mlp.add(tf.keras.Input(shape=(10)))
        mlp.add(tf.keras.layers.Dense(units=10, activation='relu'))
    
        siamese = SiameseNet(mlp)
    
        # the "entire model"
        model = tf.keras.Sequential()
        # convolution is used here purely for convenience, to split an input into two channels
        model.add(tf.keras.layers.Conv1D(2,1))
        model.add(siamese)
    
        # your stuff
        model.compile(optimizer=tf.keras.optimizers.Adam(), loss=triplet_loss, metrics=['accuracy'])
        model.build(input_shape=[1,10,1])
        model.summary()
    

    【讨论】:

      【解决方案2】:

      我想在这里回答我自己的问题,因为我所面临的问题完全不同,后来才弄清楚。特定于我的情况的问题是由于 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))
      
      

      它适用于我的情况。无需进行其他更改。

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

      optimizer = tf.keras.optimizers.Adam(lr=1e-5)
      

      model.compile().

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-06
        • 2020-03-09
        • 2019-06-25
        • 2014-11-16
        • 1970-01-01
        • 2018-03-31
        • 2021-10-22
        • 1970-01-01
        相关资源
        最近更新 更多