TensorFlow深入了解损失函数Categorical Cross-Entropy Loss、Binary Cross-Entropy Loss等

简介

深度学习中各种各样的损失函数容易让人混淆,根据任务对它们分门别类便于理解。

损失函数又称成本函数或目标函数,它用于寻找真实值与预测值之间的差异,帮助模型最小化它们之间的距离。




安装

pip install tensorflow-gpu==2.3.0
pip install tensorflow-addons




初试

TensorFlow Keras 会在模型编译时使用损失函数,可以传递实例或字符串别名

from tensorflow import keras
from tensorflow.keras import layers

model = keras.Sequential()
model.add(layers.Dense(64, kernel_initializer='uniform', input_shape=(10,)))
model.add(layers.Activation('softmax'))

loss_function = keras.losses.SparseCategoricalCrossentropy(from_logits=True)
model.compile(loss=loss_function, optimizer='adam')  # 传递实例

model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')  # 字符串别名




交叉熵 Cross Entropy

C E = − ∑ i C t i log ⁡ ( s i ) CE=-\sum_i^C{t_i\log \left( s_i \right)} CE=iCtilog(si)

t i t_i ti s i s_i si C C C中每一个类 C l a s s i Class_i Classi的真实值




二分类 Binary Classification

二分类损失函数用于解决只有两个分类的问题。如:

  1. 预测交易中的欺诈行为,要么欺诈,要么不是。
  2. 猫狗分类,要么是猫,要么是狗。

激活函数:sigmoid



二元交叉熵 Binary Cross Entropy

二元交叉熵 BinaryCrossentropy 将计算真实值与预测值之间的交叉熵损失,在二分类中,使用的激活函数是 sigmoid,将输出限制为0到1。

  • sum_over_batch_size:返回批次中每个样本损失的平均值
  • sum:返回批次中每个样本损失的和
  • none:返回每个样本损失的完整数组

预测值取值范围为 [ 0 , 1 ] \left[ 0,1 \right] [0,1]

import tensorflow as tf

y_true = [[0., 1.], [0.2, 0.8], [0.3, 0.7], [0.4, 0.6]]
y_pred = [[0.6, 0.4], [0.4, 0.6], [0.6, 0.4], [0.8, 0.2]]

bce = tf.keras.losses.BinaryCrossentropy(reduction='sum_over_batch_size')
print(bce(y_true, y_pred).numpy())  # 0.839445
bce = tf.keras.losses.BinaryCrossentropy(reduction='sum')
print(bce(y_true, y_pred).numpy())  # 3.35778
bce = tf.keras.losses.BinaryCrossentropy(reduction='none')
print(bce(y_true, y_pred).numpy())  # [0.9162905  0.5919184  0.79465103 1.0549198 ]

若不使用激活函数 sigmoid,预测值为浮点数,预测值取值范围为 [ − ∞ , + ∞ ] \begin{bmatrix}-\infty, +\infty\end{bmatrix} [,+]使用参数 from_logits=True

import tensorflow as tf

# 批次大小为1,样本数为4
y_true = [0, 1, 0, 0]  # 真实值
y_pred = [-18.6, 0.51, 2.94, -12.8]  # 预测值
bce = tf.keras.losses.BinaryCrossentropy(from_logits=True)  # 预测值为浮点数时使用from_logits=True
print(bce(y_true, y_pred).numpy())  # 0.865458

# 批次大小为2,样本数为4
y_true = [[0, 1], [0, 0]]
y_pred = [[-18.6, 0.51], [2.94, -12.8]]
bce = tf.keras.losses.BinaryCrossentropy(from_logits=True, reduction='sum_over_batch_size')
print(bce(y_true, y_pred).numpy())  # 0.865458
print(bce(y_true, y_pred, sample_weight=[0.8, 0.2]).numpy())  # 0.2436386 带样本权重




多分类 Multiclass classification

激活函数:softmax



分类交叉熵 Categorical Crossentropy

分类交叉熵 CategoricalCrossentropy 计算真实值与预测值之间的交叉熵损失,标签以独热编码 one_hot 的形式给出

import tensorflow as tf

y_true = [[0, 1, 0], [0, 0, 1]]
y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]

cce = tf.keras.losses.CategoricalCrossentropy()
print(cce(y_true, y_pred).numpy())  # 1.1769392
print(cce(y_true, y_pred, sample_weight=tf.constant([0.3, 0.7])).numpy())  # 0.8135988 带样本权重

cce = tf.keras.losses.CategoricalCrossentropy(reduction='sum')
print(cce(y_true, y_pred).numpy())  # 2.3538785
cce = tf.keras.losses.CategoricalCrossentropy(reduction='none')
print(cce(y_true, y_pred).numpy())  # [0.05129331 2.3025851 ]



稀疏分类交叉熵 Sparse Categorical Crossentropy

稀疏分类交叉熵 SparseCategoricalCrossentropy 计算真实值与预测值之间的交叉熵损失,标签以整数 int 的形式给出

import tensorflow as tf

y_true = [1, 2]
y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]

scce = tf.keras.losses.SparseCategoricalCrossentropy()
print(scce(y_true, y_pred).numpy())  # 1.1769392
print(scce(y_true, y_pred, sample_weight=tf.constant([0.3, 0.7])).numpy())  # 0.8135988 带样本权重

scce = tf.keras.losses.SparseCategoricalCrossentropy(reduction='sum')
print(scce(y_true, y_pred).numpy())  # 2.3538785
scce = tf.keras.losses.SparseCategoricalCrossentropy(reduction='none')
print(scce(y_true, y_pred).numpy())  # [0.05129331 2.3025851 ]



泊松损失 Poisson

泊松损失 Poisson ,适用于符合泊松分布的数据集,如呼叫中心每小时接到的电话数

import tensorflow as tf

y_true = [[0., 1.], [0., 0.]]
y_pred = [[1., 1.], [0., 0.]]
p = tf.keras.losses.Poisson()
print(p(y_true, y_pred).numpy())  # 0.5
print(p(y_true, y_pred, sample_weight=[0.8, 0.2]).numpy())  # 0.4 带样本权重

p = tf.keras.losses.Poisson(reduction='sum')
print(p(y_true, y_pred).numpy())  # 0.999
p = tf.keras.losses.Poisson(reduction='none')
print(p(y_true, y_pred).numpy())  # [0.99999994 0.        ]



相对熵 Kullback-Leibler Divergence Loss

相对熵 KLDivergence ,也称KL散度,是连续分布的一种距离度量,通常在离散采样连续输出分布空间上直接回归。

loss = y_true * log(y_true / y_pred)

import tensorflow as tf

y_true = [[0, 1], [0, 0]]
y_pred = [[0.6, 0.4], [0.4, 0.6]]
kl = tf.keras.losses.KLDivergence()
print(kl(y_true, y_pred).numpy())  # 0.45814306
print(kl(y_true, y_pred, sample_weight=[0.8, 0.2]).numpy())  # 0.3665154

kl = tf.keras.losses.Poisson(reduction='sum')
print(kl(y_true, y_pred).numpy())  # 1.4581453
kl = tf.keras.losses.Poisson(reduction='none')
print(kl(y_true, y_pred).numpy())  # [0.95814526 0.5       ]




目标检测 Object Detection



焦点损失 Focal Loss

焦点损失 SigmoidFocalCrossEntropy 适用于涉及不平衡数据和目标检测的分类问题,它弱化了分类良好的样本而侧重于难以分类的样本。

与分类良好的样本对应的损失值相比,被分类器误分类的样本的损失值要高得多。

焦点损失的经典用例是背景类和其他类的多分类问题。

FL ( p t ) = − ( 1 − p t ) γ log ⁡ ( p t ) \text{FL}\left( p_t \right) =-\left( 1-p_t \right) ^{\gamma}\log \left( p_t \right) FL(pt)=(1pt)γlog(pt)

import tensorflow_addons as tfa

y_true = [[1.0], [1.0], [0.0]]
y_pred = [[0.97], [0.91], [0.03]]
sfc = tfa.losses.SigmoidFocalCrossEntropy()
print(sfc(y_true, y_pred).numpy())  # [6.8532745e-06 1.9097870e-04 2.0559824e-05]



GIoU Generalized Intersection over Union

GIoULoss 是对 IoU 进行目标检测的一种改进,适用于不重叠边界框的问题

import tensorflow_addons as tfa

boxes1 = [[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]
boxes2 = [[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]]
gl = tfa.losses.GIoULoss()
print(gl(boxes1, boxes2).numpy())  # 1.5041667




回归 Regression

回归多用于预测一个具体的数值,如预测房价、未来的天气等。



均方差 Mean Squared Error

MeanSquaredError 计算真实值和预测值之间的误差的平方平均值,适用于大误差比小误差更受惩罚的情况。

import tensorflow as tf

y_true = [[0., 1.], [0., 0.]]
y_pred = [[1., 1.], [1., 0.]]
mse = tf.keras.losses.MeanSquaredError()
print(mse(y_true, y_pred).numpy())  # 0.5
print(mse(y_true, y_pred, sample_weight=[0.8, 0.2]).numpy())  # 0.25

mse = tf.keras.losses.MeanSquaredError(reduction='sum')
print(mse(y_true, y_pred).numpy())  # 1.0
mse = tf.keras.losses.MeanSquaredError(reduction='none')
print(mse(y_true, y_pred).numpy())  # [0.5 0.5]



平均绝对误差百分比 Mean Absolute Percentage Error

MeanAbsolutePercentageError 常用于销量预测

loss = 100 * abs(y_true - y_pred) / y_true

import tensorflow as tf

y_true = [[2., 1.], [2., 3.]]
y_pred = [[1., 1.], [1., 0.]]
mape = tf.keras.losses.MeanAbsolutePercentageError()
print(mape(y_true, y_pred).numpy())  # 50.0
print(mape(y_true, y_pred, sample_weight=[0.7, 0.3]).numpy())  # 20.0

mape = tf.keras.losses.MeanAbsolutePercentageError(reduction='sum')
print(mape(y_true, y_pred).numpy())  # 100.0
mape = tf.keras.losses.MeanAbsolutePercentageError(reduction='none')
print(mape(y_true, y_pred).numpy())  # [25. 75.]



均方对数误差 Mean Squared Logarithmic Error

MeanSquaredLogarithmicError 对低估的惩罚要大于高估,适用于处理离群值。

loss = square(log(y_true + 1.) - log(y_pred + 1.))

import tensorflow as tf

y_true = [[0., 1.], [0., 0.]]
y_pred = [[1., 1.], [1., 0.]]
msle = tf.keras.losses.MeanSquaredLogarithmicError()
print(msle(y_true, y_pred).numpy())  # 0.24022643
print(msle(y_true, y_pred, sample_weight=[0.7, 0.3]).numpy())  # 0.12011322

msle = tf.keras.losses.MeanSquaredLogarithmicError(reduction='sum')
print(msle(y_true, y_pred).numpy())  # 0.48045287
msle = tf.keras.losses.MeanSquaredLogarithmicError(reduction='none')
print(msle(y_true, y_pred).numpy())  # [0.24022643 0.24022643]



余弦相似度 Cosine Similarity Loss

CosineSimilarity 结果是 -1 到 1 之间的数,越接近 -1 越相似

loss = -sum(l2_norm(y_true) * l2_norm(y_pred))

import tensorflow as tf

y_true = [[0., 1.], [1., 1.]]
y_pred = [[1., 0.], [1., 1.]]
cosine_loss = tf.keras.losses.CosineSimilarity(axis=1)
print(cosine_loss(y_true, y_pred).numpy())  # -0.5
print(cosine_loss(y_true, y_pred, sample_weight=[0.7, 0.3]).numpy())  # -0.0999

cosine_loss = tf.keras.losses.CosineSimilarity(axis=1, reduction='sum')
print(cosine_loss(y_true, y_pred).numpy())  # -0.999
cosine_loss = tf.keras.losses.CosineSimilarity(axis=1, reduction='none')
print(cosine_loss(y_true, y_pred).numpy())  # [-0.         -0.99999994]



LogCosh Loss

LogCosh 类似于均方误差,但不会受到偶尔严重错误预测的强烈影响。

x = y_pred - y_true

logcosh = log((exp(x) + exp(-x))/2)

import tensorflow as tf

y_true = [[0., 1.], [0., 0.]]
y_pred = [[1., 1.], [0., 0.]]
l = tf.keras.losses.LogCosh()
print(l(y_true, y_pred).numpy())  # 0.108
print(l(y_true, y_pred, sample_weight=[0.8, 0.2]).numpy())  # 0.087

l = tf.keras.losses.LogCosh(reduction='sum')
print(l(y_true, y_pred).numpy())  # 0.217
l = tf.keras.losses.LogCosh(reduction='none')
print(l(y_true, y_pred).numpy())  # [0.2168904 0.       ]



Huber loss

Huber 适用于对异常值不太敏感的回归问题

x = y_true - y_pred

loss = 0.5 * x^2                  if |x| <= d
loss = 0.5 * d^2 + d * (|x| - d)  if |x| > d
import tensorflow as tf

y_true = [[0, 1], [0, 0]]
y_pred = [[0.6, 0.4], [0.4, 0.6]]
h = tf.keras.losses.Huber()
print(h(y_true, y_pred).numpy())  # 0.155
print(h(y_true, y_pred, sample_weight=[1, 0]).numpy())  # 0.09

h = tf.keras.losses.LogCosh(reduction='sum')
print(h(y_true, y_pred).numpy())  # 0.29417965
h = tf.keras.losses.LogCosh(reduction='none')
print(h(y_true, y_pred).numpy())  # [0.17013526 0.12404439]




学习嵌入 Learning Embeddings



三元组损失 Triplet Loss

TripletSemiHardLoss 鼓励具有相同标签的嵌入对之间的正距离小于最小负距离

TensorFlow Addons Losses: TripletSemiHardLoss




自定义损失函数

import numpy as np
import tensorflow as tf


def custom_loss_function(y_true, y_pred):
    """自定义损失函数"""
    squared_difference = tf.square(y_true - y_pred)
    return tf.reduce_mean(squared_difference, axis=-1)


y_true = [12, 20, 29., 60.]
y_pred = [14., 18., 27., 55.]
print(custom_loss_function(np.array(y_true), np.array(y_pred)).numpy())  # 9.25




样本权重

阅读 Python计算数据集不同类别的权重class_weight

在调用 Model.compile() 时指定参数 loss_weights

或调用 Model.fit() 时指定参数 class_weight




为什么损失函数的值为nan

当发生损失函数的值为 nan 时,模型将停止学习不会更新权重。

造成 nan 的原因有很多:

  • 训练集 nan 导致损失函数的 nan
  • NumPy 在训练集中的无限大导致 nan
  • 用了没有缩放的训练集
  • 很大的 L2正则化
  • 大于 1 的学习率
  • 错误的优化器
  • 大梯度导致训练期间网络权值的大更新




总结

任务损失函数激活函数
二分类BinaryCrossentropysigmoid
多分类CategoricalCrossentropy
SparseCategoricalCrossentropy
softmax
目标检测SigmoidFocalCrossEntropy
GIoULoss
回归MeanSquaredError




参考文献

  1. Keras Loss Functions: Everything You Need To Know
  2. Understanding Categorical Cross-Entropy Loss, Binary Cross-Entropy Loss, Softmax Loss, Logistic Loss, Focal Loss and all those confusing names
  3. IoU、GIoU、DIoU、CIoU损失函数的那点事儿
### 回答1: 在 tensorflow 中,loss=categorical_crossentropy 表示使用分类交叉熵损失函数。分类交叉熵损失函数是用来评估模型预测结果和真实结果之间的差距的。 在分类问题中,我们希望模型的预测概率和真实概率之间的差距尽可能小。分类交叉熵损失函数可以很好地反映出这一点。 在 tensorflow 中,还有许多其它的损失函数可以使用,比如均方误差损失函数loss=mean_squared_error)和相对误差损失函数loss=mean_absolute_error)等。 ### 回答2: 在TensorFlow中,loss='categorical_crossentropy'是一种损失函数loss function)的表示形式。这个损失函数适用于多分类问题,特别是在输出类别使用独热编码(one-hot encoding)表示的情况下。 损失函数用于衡量模型在训练过程中的预测结果与实际标签之间的差异。而categorical_crossentropy是一种计算预测与真实标签之间差异的数学公式。当模型输出类别为多个,并且采用独热编码表示时,可以使用categorical_crossentropy作为损失函数来优化模型的训练。 除了categorical_crossentropyTensorFlow中还有其他不同类型的损失函数,适用于不同问题和数据。一些常见的损失函数包括: 1. Mean Squared Error(均方误差,即MSE):适用于回归问题,衡量预测值与实际值之间的平均差异。 2. Binary Crossentropy(二分类交叉熵):适用于二分类问题,用于衡量预测结果与实际标签之间的差异,常用于sigmoid激活函数和独热编码。 3. Sparse Categorical Crossentropy(稀疏多分类交叉熵):适用于多分类问题,但是实际标签不使用独热编码的情况。与categorical_crossentropy相比,它处理稀疏标签(即非独热编码)的能力更高效。 总结来说,损失函数TensorFlow中用于衡量模型预测与实际标签之间的差异,loss='categorical_crossentropy'是多分类问题中常用的损失函数之一,同时还有其他类型的损失函数适用于不同问题和数据。 ### 回答3: 在TensorFlow中,loss='categorical_crossentropy'代表使用分类交叉熵作为模型的损失函数损失函数的作用是衡量模型预测结果与实际标签之间的差异,进而用于调整模型的参数,使其能够更准确地预测。 对于多分类任务,使用分类交叉熵可以有效地衡量模型预测结果与真实标签之间的差异。它通过计算每个类别的预测概率与实际标签的交叉熵来得到整体的损失值,然后将这些损失值加权求和,得到模型的最终损失。其中,每个类别的预测概率由softmax函数计算得到。 除了分类交叉熵外,还有一些其他类型的损失函数可以根据不同的任务和模型需求选择。例如,对于二分类问题,可以选择使用二进制交叉熵作为损失函数。对于回归问题,可以选择均方差损失函数或平均绝对误差损失函数。不同的损失函数适用于不同的问题和模型结构,可以根据具体情况进行选择。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XerCis

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值