На самом деле, часть, где вычисляется общий убыток, находится в методе compile
класса Model
, в частности, в этой строке :
# Compute total loss.
# Used to keep track of the total loss value (stateless).
# eg., total_loss = loss_weight_1 * output_1_loss_fn(...) +
# loss_weight_2 * output_2_loss_fn(...) +
# layer losses.
self.total_loss = self._prepare_total_loss(masks)
Метод _prepare_total_loss
добавляет регуляризацию и потери слоя к общим потерям (т. е. все потери суммируются вместе), а затем усредняет их по оси пакета в эти строки :
# Add regularization penalties and other layer-specific losses.
for loss_tensor in self.losses:
total_loss += loss_tensor
return K.mean(total_loss)
На самом деле, self.losses
не является атрибутом класса Model
; скорее это атрибут родительского класса , то есть Network
, который возвращает все потери уровня c в виде списка. Кроме того, чтобы устранить любую путаницу, total_loss
в приведенном выше коде - это единственный тензор, который равен суммированию всех потерь в модели (т. Е. Значений функции потерь и потерь, определяемых уровнем c) ). Обратите внимание, что функции потерь по определению должны возвращать одно значение потерь для каждой входной выборки (а не всей партии). Следовательно, K.mean(total_loss)
будет усреднять все эти значения по оси пакета до одного конечного значения потерь, которое должно быть минимизировано оптимизатором.
Что касается tf.keras
, то оно более или менее совпадает с собственным. keras
; однако структуры и поток вещей немного отличаются, что объясняется ниже.
Во-первых, в compile
методе Model
класса создается контейнер потерь , который содержит и вычисляет значение функций потерь:
self.compiled_loss = compile_utils.LossesContainer(
loss, loss_weights, output_names=self.output_names)
Далее, в train_step
методе класса Model
этот контейнер вызывается для вычисления значения потери партии:
loss = self.compiled_loss(
y, y_pred, sample_weight, regularization_losses=self.losses)
Как вы можете видеть выше, self.losses
передается в этот контейнер. self.losses
, как и в собственной реализации Keras, содержит все значения потерь, определяемые слоем c, с той лишь разницей, что в tf.keras
он реализован в Layer
классе (вместо Network
класс как у родного кераса). Обратите внимание, что Model
является подклассом Network
, который сам является подклассом Layer
. Теперь давайте посмотрим, как будет обрабатываться regularization_losses
в методе __call__
LossesContainer
( эти строки ):
if (loss_obj.reduction == losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE or
loss_obj.reduction == losses_utils.ReductionV2.AUTO):
loss_value = losses_utils.scale_loss_for_distribution(loss_value)
loss_values.append(loss_value)
loss_metric_values.append(loss_metric_value)
if regularization_losses:
regularization_losses = losses_utils.cast_losses_to_common_dtype(
regularization_losses)
reg_loss = math_ops.add_n(regularization_losses)
loss_metric_values.append(reg_loss)
loss_values.append(losses_utils.scale_loss_for_distribution(reg_loss))
if loss_values:
loss_metric_values = losses_utils.cast_losses_to_common_dtype(
loss_metric_values)
total_loss_metric_value = math_ops.add_n(loss_metric_values)
self._loss_metric.update_state(
total_loss_metric_value, sample_weight=batch_dim)
loss_values = losses_utils.cast_losses_to_common_dtype(loss_values)
total_loss = math_ops.add_n(loss_values)
return total_loss
Как вы можете видеть, regularization_losses
будет быть добавлен к total_loss
, который будет содержать сумму специфичных для слоя c потерь и сумму среднего значения всех функций потерь по оси пакета (следовательно, это будет одно значение).