文章目录
交叉熵损失函数(Cross-Entropy loss function)
交叉熵损失函数常用于二分类和多分类任务,它用于二分类的形式如下:
L
=
−
1
n
∑
i
n
[
y
i
l
n
y
^
i
+
(
1
−
y
i
)
l
n
(
1
−
y
^
i
)
]
L=-\frac{1}{n}\sum_{i}^{n}[y_{i}ln\hat{y}_{i} + (1-y_{i})ln(1-\hat{y}_{i})]
L=−n1i∑n[yilny^i+(1−yi)ln(1−y^i)]其中,
y
y
y表示实际的标签,
y
^
\hat{y}
y^表示预测输出。
它用于多分类的形式如下:
L
=
−
1
n
∑
i
n
y
i
l
n
y
^
i
L=-\frac{1}{n}\sum_{i}^{n}y_{i}ln\hat{y}_{i}
L=−n1i∑nyilny^i交叉熵损失函数在神经网络中做分类问题时,由于交叉熵涉及到计算每个类别的概率,所以交叉熵几乎每次都和sigmoid(或softmax)函数一起出现,用于在神经网络最后一层进行输出每种类别的概率形式。神经网络最后一层得到每个类别的得分scores(也叫logits);该得分经过sigmoid或softmax函数获得概率输出;模型预测的类别概率输出与真实类别的one hot形式进行交叉熵损失函数的计算。在tensorflow中,交叉熵损失函数主要有以下几种形式:
tf.nn.softmax_cross_entropy_with_logits()
形式:
tf.nn.softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, dim=-1, name=None)
作用:计算labels和logits之间的交叉熵。其中,logits表示经过神经网络输出计算得到的未归一化的概率,之后logits会先通过softmax运算再计算交叉熵。它的形式是: t a r g e t s ∗ − l o g ( s o f t m a x ( l o g i t s ) ) + ( 1 − t a r g e t s ) ∗ − l o g ( 1 − s o f t m a x ( l o g i t s ) ) targets*-log(softmax(logits)) + (1-targets)*-log(1-softmax(logits)) targets∗−log(softmax(logits))+(1−targets)∗−log(1−softmax(logits))
tf.nn.sigmoid_cross_entropy_with_logits()
形式:
tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, name=None)
作用:对输入进行sigmoid 函数运算之后,再计算交叉熵。它的形式是: t a r g e t s ∗ − l o g ( s i g m o i d ( l o g i t s ) ) + ( 1 − t a r g e t s ) ∗ − l o g ( 1 − s i g m o i d ( l o g i t s ) ) targets*-log(sigmoid(logits)) + (1-targets)*-log(1-sigmoid(logits)) targets∗−log(sigmoid(logits))+(1−targets)∗−log(1−sigmoid(logits))
tf.nn.weighted_cross_entropy_with_logits()
形式:
weighted_cross_entropy_with_logits(targets, logits, pos_weight, name=None):
作用:是计算具有权重的sigmoid交叉熵函数,其中pos_weight表示加在正样本上的一个系数。对于加了pos_weight的形式是: t a r g e t s ∗ − l o g ( s i g m o i d ( l o g i t s ) ) ∗ p o s w e i g h t + ( 1 − t a r g e t s ) ∗ − l o g ( 1 − s i g m o i d ( l o g i t s ) ) targets*-log(sigmoid(logits))*pos_{weight} + (1-targets)*-log(1-sigmoid(logits)) targets∗−log(sigmoid(logits))∗posweight+(1−targets)∗−log(1−sigmoid(logits))
tf.losses.binary_crossentropy()和tf.losses.BinaryCrossentropy()
形式:
binary_crossentropy(y_true, y_pred, from_logits=False, label_smoothing=0)
它们都是用于计算二分类任务的交叉熵损失。BinaryCrossentropy是一个类,需要先定义再调用,返回的是一个最终loss。而binary_crossentropy是一个函数,计算每个位置的损失值,返回的结果与batch_size大小一样,需要再通过reduce_mean()
计算最终loss。
y_pre = np.array([[0.5, 0.1], [0.3, 0.8]])
y_true = np.array([[1, 0], [0, 1]])
loss = tf.losses.binary_crossentropy(y_true=y_true, y_pred=y_pre)
tf.Tensor([0.39925369 0.28990911], shape=(2,), dtype=float64)
y_pre = np.array([[0.5, 0.1], [0.3, 0.8]])
y_true = np.array([[1, 0], [0, 1]])
loss = tf.losses.BinaryCrossentropy()
print(loss(y_pred=y_pre, y_true=y_true))
tf.Tensor(0.3445814251899719, shape=(), dtype=float64)
其中,binary_crossentropy()默认参数from_logits=False
,也就是说默认y_pre
不是logtis,而是一个已经经过softmax或者sigmoid概率化的输入形式。当指定参数from_logits=True
时,说明y_pre
没有经过softmax或者sigmoid进行概率化,在binary_crossentropy中,会默认调用sigmoid_cross_entropy_with_logits()来对y_pre
通过sigmoid进行概率化,再计算交叉熵。所以下面的两种方法得到的结果是一样的:
y_pre = np.array([[5, 5], [2, 8]], dtype=np.float)
y_true = np.array([[1, 0], [0, 1]], dtype=np.float)
loss = tf.losses.binary_crossentropy(y_true=y_true, y_pred=y_pre, from_logits=True)
print(loss)
y_pre = tf.nn.sigmoid(y_pre)
loss = tf.losses.binary_crossentropy(y_true=y_true, y_pred=y_pre, from_logits=False)
print(loss)
tf.losses.binary_crossentropy()在keras中的形式是:
keras.losses.binary_crossentropy(y_true, y_pred, from_logits=False, label_smoothing=0)
tf.losses.categorical_crossentropy()和tf.losses.CategoricalCrossentropy()
形式:
def categorical_crossentropy(y_true,
y_pred,
from_logits=False,
label_smoothing=0)
它们两者的区别与binary_crossentropy()和BinaryCrossentropy()的区别一样,只不过categorical_crossentropy()和CategoricalCrossentropy()是用计算多分类任务的交叉熵。
y_true = [[0, 1, 0], [0, 0, 1]]
y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]
loss = tf.keras.losses.categorical_crossentropy(y_true, y_pred)
print(loss.numpy())
array([0.0513, 2.303], dtype=float32)