问题描述
我正在尝试与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上运行代码。
请帮我解决这个问题。谢谢。
解决方法
我不知道它是否正是您要的东西,但是我可以得到一个形状类似的模型,如下所示。
主要区别在于:
-
return np.stack([feats,nfeats])
。 - 整个模型是
Sequential
模型,因此我不依赖于keras来基于Input
张量构建任何东西(第一层除外)。 -
SiameseNet
的输入是卷积层的输出,因此我将其切成合适的形状。 - 我为
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()
中。