gpt4 book ai didi

python - keras中不同批量大小的损失计算

转载 作者:太空宇宙 更新时间:2023-11-03 13:58:36 25 4
gpt4 key购买 nike

我知道从理论上讲,网络在一批上的损失只是所有个体损失的总和。这反射(reflect)在 Keras code 中。用于计算总损失。相关:

            for i in range(len(self.outputs)):
if i in skip_target_indices:
continue
y_true = self.targets[i]
y_pred = self.outputs[i]
weighted_loss = weighted_losses[i]
sample_weight = sample_weights[i]
mask = masks[i]
loss_weight = loss_weights_list[i]
with K.name_scope(self.output_names[i] + '_loss'):
output_loss = weighted_loss(y_true, y_pred,
sample_weight, mask)
if len(self.outputs) > 1:
self.metrics_tensors.append(output_loss)
self.metrics_names.append(self.output_names[i] + '_loss')
if total_loss is None:
total_loss = loss_weight * output_loss
else:
total_loss += loss_weight * output_loss

但是,我注意到,当我使用 batch_size=32batch_size=64 训练网络时,每个时期的损失值仍然会更多或不太相同,只有 ~0.05% 差异。然而,两个网络的准确度保持完全相同。所以从本质上讲,批量大小对网络没有太大影响。

我的问题是,当我将批处理大小加倍时,假设损失确实被求和,那么损失实际上不应该是之前值(value)的两倍,或者至少更大吗?网络可能在更大的 batch size 下学得更好的借口被准确率保持完全相同的事实所否定。

无论批量大小如何,损失都或多或少保持不变,这一事实让我认为这是平均的。

最佳答案

您发布的代码涉及多输出模型,其中每个输出可能有自己的损失和权重。因此,不同输出层的损失值被加在一起。但是,正如您在 losses.py 中看到的那样,个体损失在批处理 上取平均值。文件。例如,这是与二元交叉熵损失相关的代码:

def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1)

更新:在添加这个答案的第二部分(即损失函数)之后,作为 OP,我对 axis=-1 感到困惑损失函数的定义,我心想它必须是 axis=0 来表示批处理的平均值?!然后我意识到损失函数定义中使用的所有 K.mean() 都是针对由多个单元组成的输出层的情况。那么批量的平均损失在哪里?我检查了代码以找到答案:获取特定损失函数的损失值,a function is called将真实和预测的标签以及样本权重和掩码作为其输入:

weighted_loss = weighted_losses[i]
# ...
output_loss = weighted_loss(y_true, y_pred, sample_weight, mask)

weighted_losses[i] 函数是什么?您可能会发现,it is an element of list of (augmented) loss functions :

weighted_losses = [
weighted_masked_objective(fn) for fn in loss_functions]

fn 实际上是losses.py中定义的损失函数之一文件或者它可以是用户定义的自定义损失函数。现在这个 weighted_masked_objective 函数是什么?已在 training_utils.py 中定义文件:

def weighted_masked_objective(fn):
"""Adds support for masking and sample-weighting to an objective function.
It transforms an objective function `fn(y_true, y_pred)`
into a sample-weighted, cost-masked objective function
`fn(y_true, y_pred, weights, mask)`.
# Arguments
fn: The objective function to wrap,
with signature `fn(y_true, y_pred)`.
# Returns
A function with signature `fn(y_true, y_pred, weights, mask)`.
"""
if fn is None:
return None

def weighted(y_true, y_pred, weights, mask=None):
"""Wrapper function.
# Arguments
y_true: `y_true` argument of `fn`.
y_pred: `y_pred` argument of `fn`.
weights: Weights tensor.
mask: Mask tensor.
# Returns
Scalar tensor.
"""
# score_array has ndim >= 2
score_array = fn(y_true, y_pred)
if mask is not None:
# Cast the mask to floatX to avoid float64 upcasting in Theano
mask = K.cast(mask, K.floatx())
# mask should have the same shape as score_array
score_array *= mask
# the loss per batch should be proportional
# to the number of unmasked samples.
score_array /= K.mean(mask)

# apply sample weighting
if weights is not None:
# reduce score_array to same ndim as weight array
ndim = K.ndim(score_array)
weight_ndim = K.ndim(weights)
score_array = K.mean(score_array,
axis=list(range(weight_ndim, ndim)))
score_array *= weights
score_array /= K.mean(K.cast(K.not_equal(weights, 0), K.floatx()))
return K.mean(score_array)
return weighted

如您所见,首先在 score_array = fn(y_true, y_pred) 行中计算每个样本的损失,然后在最后返回损失的平均值,即 返回 K.mean(score_array)。因此,这证实了报告的损失是每批处理中每个样本损失的平均值。

注意 K.mean(),如果使用 Tensorflow 作为后端,calls tf.reduce_mean() 函数。现在,当在没有 axis 参数的情况下调用 K.mean() 时(axis 参数的默认值为 None),因为它在weighted_masked_objective函数中被调用,对应调用tf.reduce_mean() computes the mean over all the axes and returns one single value .这就是为什么无论输出层的形状和使用的损失函数如何,Keras 只使用和报告一个单一的损失值(它应该是这样的,因为优化算法需要最小化标量值,而不是向量或张量) .

关于python - keras中不同批量大小的损失计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52172859/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com