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

问题描述

我正在尝试与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,3)(其中500个训练示例数)和{{1}形状为positives的}(正图像特征)。所有这些都是numpy数组。

我的模型代码如下所示

(500,1000)

编译与输出正常工作

image_input = tf.keras.layers.Input(shape=(299,3),name='image_input')
negative_input = tf.keras.layers.Input(shape=(299,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,3) 0                                            
__________________________________________________________________________________________________
negative_input (InputLayer)     [(None,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)

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

解决方法

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

主要区别在于:

  1. return np.stack([feats,nfeats])
  2. 整个模型是Sequential模型,因此我不依赖于keras来基于Input张量构建任何东西(第一层除外)。
  3. SiameseNet的输入是卷积层的输出,因此我将其切成合适的形状。
  4. 我为SiameseNet使用了一个简单的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()
,

我想在这里回答我自己的问题,因为我面临的问题是完全不同的,后来已经解决了。我的具体情况是由于triplet_loss函数引起的。损失函数期望以张量为单位进行计算,而代码则以Numpy数组为单位进行计算。更改此错误对于我来说已解决此错误,并且代码现在可以正常工作了。

函数实现应该已经

def triplet_loss(y_true,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()中。