我正在尝试在 Google Colab 上使用 Tensorflow 进行面部识别,但遇到错误。以前工作得很好,但现在却抛出了这个错误。完整的 .ipynb 文件已链接(请注意,您需要一个包含 .jpg 文件的负数、正数和锚文件夹才能运行程序。) 使暹罗模型出错 文件链接: https://www .mediafire.com/file/a5azngcpmdrrxyd/facial_recognition.ipynb/file
我尝试从 4.3 函数中删除嵌入函数,但在训练时它又抛出了另一个错误。 训练错误
我查看了提供的代码和错误消息。看来问题出在
试图将不兼容的张量传递给损失函数
。更具体地说,的
TripletLoss
函数返回一个形状为
(batch_size,)
的张量,而
model.fit()
函数需要一个标量损失值。
以下是导致此错误的分步说明:
-
TripletLoss
函数计算批次中每个三元组的标量损失。 这是正确的。 -
然后,它使用
tf.reduce_mean()
对所有这些标量损失求平均值。 这也是正确的,因为它可以为提供一个批次的平均三元组损失。 -
问题在于
model.fit()
函数期望将一个 标量 值作为损失。 它不知道如何处理形状为(batch_size,)
的张量。
为了解决此错误,需要
在
TripletLoss
函数内聚合三元组损失
。可以通过以下两种方式之一来执行此操作:
选项 1:将损失减少为单个标量
最简单的方法是在
tf.reduce_mean()
之后返回三元组损失的单个标量。这将为提供整个批次的单个平均损失值。
def TripletLoss(margin=0.5):
def _TripletLoss(y_true, y_pred):
anchor, positive, negative = y_pred[:,:128], y_pred[:,128:256], y_pred[:,256:]
positive_dist = tf.reduce_sum(tf.square(anchor - positive), axis=1)
negative_dist = tf.reduce_sum(tf.square(anchor - negative), axis=1)
triplet_loss = tf.maximum(positive_dist - negative_dist + margin, 0.0)
loss = tf.reduce_mean(triplet_loss) # Calculate the mean triplet loss
return loss # Return the scalar loss value
return _TripletLoss
选项 2:使用
tf.keras.losses.Loss
基类
还可以通过子类化
tf.keras.losses.Loss
并实现
call()
方法来创建一个自定义损失函数。这使可以更好地控制损失计算,并且在处理加权损失或需要在损失函数内部执行其他操作时非常有用。
class TripletLoss(tf.keras.losses.Loss):
def __init__(self, margin=0.5):
super(TripletLoss, self).__init__()
self.margin = margin
def call(self, y_true, y_pred):
anchor, positive, negative = y_pred[:,:128], y_pred[:,128:256], y_pred[:,256:]
positive_dist = tf.reduce_sum(tf.square(anchor - positive), axis=1)
negative_dist = tf.reduce_sum(tf.square(anchor - negative), axis=1)
triplet_loss = tf.maximum(positive_dist - negative_dist + self.margin, 0.0)
return triplet_loss # Return the triplet losses for each sample in the batch
在对
TripletLoss
函数进行此更改后,请确保像这样创建损失函数的实例:
triplet_loss = TripletLoss() # For option 1
# OR
triplet_loss = TripletLoss(margin=0.5) # For option 2
并使用它来编译的模型:
model.compile(loss=triplet_loss, optimizer='adam')
通过在
TripletLoss
函数中聚合损失或使用
tf.keras.losses.Loss
基类并返回正确的损失形状,应该可以解决
model.fit()
中的错误。