fit() 函数的 TensorFlow/Keras 的 class_weight 参数如何工作?
How does TensorFlow/Keras's class_weight parameter of the fit() function work?
我使用 TensorFlow 1.12 和 Keras 进行语义分割。我使用 class_weight
参数向 tf.keras.Model.fit()
提供了一个权重向量(大小等于 classes 的数量)。我想知道这在内部是如何工作的。我使用自定义损失函数(骰子损失和焦点损失等),并且在将权重输入损失函数之前不能将权重与预测或单热基本事实相乘,因为那样不会产生任何影响感觉。我的损失函数输出一个标量值,因此它也不能与函数输出相乘。那么 class 权重在哪里以及如何被考虑在内呢?
我的自定义损失函数是:
def cross_entropy_loss(onehots_true, logits): # Inputs are [BATCH_SIZE, height, width, num_classes]
logits, onehots_true = mask_pixels(onehots_true, logits) # Removes pixels for which no ground truth exists, and returns shape [num_gt_pixels, num_classes]
return tf.losses.softmax_cross_entropy(onehots_true, logits)
所述
class_weight
: Optional dictionary mapping class indices (integers)
to a weight (float) value, used for weighting the loss function
(during training only). This can be useful to tell the model to "pay
more attention" to samples from an under-represented class.
基本上,我们在 class 不平衡e 的地方提供 class 权重。意思是,训练样本并不是均匀分布在所有 classes 中。一些 classes 的样本较少,而一些 classes 的样本较高。
我们需要 classifier 来 关注 数量较少的 classes。一种方法可能是增加 class 具有低样本的损失值。更高的损失意味着更高的优化,从而导致高效的class化。
就 Keras 而言,我们将 dict
映射 class 索引传递给它们的权重(损失值乘以的因子)。举个例子,
class_weights = { 0 : 1.2 , 1 : 0.9 }
在内部,classes 0 和 1 的损失值将乘以它们相应的权重值。
weighed_loss_class0 = loss0 * class_weights[0]
weighed_loss_class1 = loss1 * class_weights[1]
现在,the weighed_loss_class0
和 weighed_loss_class1
将用于反向传播。
您可以参考github中的keras源代码中的以下代码:
class_sample_weight = np.asarray(
[class_weight[cls] for cls in y_classes if cls in class_weight])
if len(class_sample_weight) != len(y_classes):
# subtract the sets to pick all missing classes
existing_classes = set(y_classes)
existing_class_weight = set(class_weight.keys())
raise ValueError(
'`class_weight` must contain all classes in the data.'
' The classes %s exist in the data but not in '
'`class_weight`.' % (existing_classes - existing_class_weight))
if class_sample_weight is not None and sample_weight is not None:
# Multiply weights if both are provided.
return class_sample_weight * sample_weight
所以如你所见,首先 class_weight
被转换为一个 numpy 数组 class_sample_weight
然后它与 sample_weight.
相乘
我使用 TensorFlow 1.12 和 Keras 进行语义分割。我使用 class_weight
参数向 tf.keras.Model.fit()
提供了一个权重向量(大小等于 classes 的数量)。我想知道这在内部是如何工作的。我使用自定义损失函数(骰子损失和焦点损失等),并且在将权重输入损失函数之前不能将权重与预测或单热基本事实相乘,因为那样不会产生任何影响感觉。我的损失函数输出一个标量值,因此它也不能与函数输出相乘。那么 class 权重在哪里以及如何被考虑在内呢?
我的自定义损失函数是:
def cross_entropy_loss(onehots_true, logits): # Inputs are [BATCH_SIZE, height, width, num_classes]
logits, onehots_true = mask_pixels(onehots_true, logits) # Removes pixels for which no ground truth exists, and returns shape [num_gt_pixels, num_classes]
return tf.losses.softmax_cross_entropy(onehots_true, logits)
class_weight
: Optional dictionary mapping class indices (integers) to a weight (float) value, used for weighting the loss function (during training only). This can be useful to tell the model to "pay more attention" to samples from an under-represented class.
基本上,我们在 class 不平衡e 的地方提供 class 权重。意思是,训练样本并不是均匀分布在所有 classes 中。一些 classes 的样本较少,而一些 classes 的样本较高。
我们需要 classifier 来 关注 数量较少的 classes。一种方法可能是增加 class 具有低样本的损失值。更高的损失意味着更高的优化,从而导致高效的class化。
就 Keras 而言,我们将 dict
映射 class 索引传递给它们的权重(损失值乘以的因子)。举个例子,
class_weights = { 0 : 1.2 , 1 : 0.9 }
在内部,classes 0 和 1 的损失值将乘以它们相应的权重值。
weighed_loss_class0 = loss0 * class_weights[0]
weighed_loss_class1 = loss1 * class_weights[1]
现在,the weighed_loss_class0
和 weighed_loss_class1
将用于反向传播。
您可以参考github中的keras源代码中的以下代码:
class_sample_weight = np.asarray(
[class_weight[cls] for cls in y_classes if cls in class_weight])
if len(class_sample_weight) != len(y_classes):
# subtract the sets to pick all missing classes
existing_classes = set(y_classes)
existing_class_weight = set(class_weight.keys())
raise ValueError(
'`class_weight` must contain all classes in the data.'
' The classes %s exist in the data but not in '
'`class_weight`.' % (existing_classes - existing_class_weight))
if class_sample_weight is not None and sample_weight is not None:
# Multiply weights if both are provided.
return class_sample_weight * sample_weight
所以如你所见,首先 class_weight
被转换为一个 numpy 数组 class_sample_weight
然后它与 sample_weight.