softmax函数与交叉熵损失详解
softmax函数与交叉熵损失详解
在机器学习和深度学习中,softmax函数和交叉熵损失函数是两个非常重要的概念。本文将详细介绍softmax函数的定义、引入指数形式的优缺点,以及交叉熵损失函数的定义。同时,本文还将探讨softmax函数与交叉熵损失函数的结合使用,并提供具体的Python代码示例。
一、softmax函数
softmax函数主要用于多分类过程中,它将多个神经元的输出映射到(0,1)区间内,可以看作概率来理解,从而实现多分类。
假设我们有一个数组Z,其中Zi表示Z中的第i个元素,那么这个元素的softmax值就是:
更形象的表示如下图:
从图中可以看出,softmax函数将原始输出值(如3,1,-3)映射到(0,1)区间内,且这些值的累和为1,满足概率的性质。因此,我们可以将这些值理解为概率,在最后选取输出结点时,选择概率最大(即值最大的)结点作为预测目标。
1.1 引入指数形式的优点
从y = e^x的函数图像中可以看出,曲线呈现递增趋势,最重要的是斜率逐渐增大。这意味着在x轴上一个很小的变化,可以导致y轴上很大的变化。这种函数曲线能够将输出的数值拉开距离。
假设拥有三个输出节点的输出值为[2, 3, 5]。我们来尝试使用和不使用指数函数的Softmax函数计算会产生什么区别:
import tensorflow as tf
print(tf.__version__) # 2.0.0
a = tf.constant([2, 3, 5], dtype = tf.float32)
b1 = a / tf.reduce_sum(a) # 不使用指数
print(b1) # tf.Tensor([0.2 0.3 0.5], shape=(3,), dtype=float32)
b2 = tf.nn.softmax(a) # 使用指数的Softmax
print(b2) # tf.Tensor([0.04201007 0.11419519 0.8437947 ], shape=(3,), dtype=float32)
结果表明,使用指数形式的Softmax函数能够将差距大的数值距离拉得更大。此外,在深度学习中通常使用反向传播求解梯度进而使用梯度下降进行参数更新的过程,使用指数函数在求导的时候比较方便。
1.2 引入指数形式的缺点
指数函数的曲线斜率逐渐增大虽然能够将输出值拉开距离,但是也带来了缺点,当zi值非常大的话,计算得到的数值也会变的非常大,数值可能会溢出。
import numpy as np
scores = np.array([123, 456, 789])
softmax = np.exp(scores) / np.sum(np.exp(scores))
print(softmax) # [ 0. 0. nan]
针对数值溢出问题,可以将每一个输出值减去输出值中最大的值:
import numpy as np
scores = np.array([123, 456, 789])
scores -= np.max(scores)
p = np.exp(scores) / np.sum(np.exp(scores))
print(p) # [5.75274406e-290 2.39848787e-145 1.00000000e+000]
二、交叉熵损失函数
2.1 交叉熵损失函数
交叉熵函数为在处理分类问题中常用的一种损失函数,用于描述模型预测值与真实值的差距大小,其具体公式为:
其中,p为真实值,q为预测值。
交叉熵损失函数在Python中的具体实现如下:
# tensorflow version
loss = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y), reduction_indices=[1]))
# numpy version
loss = np.mean(-np.sum(y_*np.log(y), axis=1))
# pytorch version
entroy=nn.CrossEntropyLoss()
2.2 softmax与交叉熵损失
当使用Softmax函数作为输出节点的激活函数的时候,一般使用交叉熵作为损失函数。由于Softmax函数的数值计算过程中,很容易因为输出节点的输出值比较大而发生数值溢出的现象,在计算交叉熵的时候也可能会出现数值溢出的问题。为了数值计算的稳定性,TensorFlow提供了一个统一的接口,将Softmax与交叉熵损失函数同时实现,同时也处理了数值不稳定的异常,使用TensorFlow深度学习框架的时候,一般推荐使用这个统一的接口,避免分开使用Softmax函数与交叉熵损失函数。
TensorFlow提供的统一函数式接口为:
import tensorflow as tf
print(tf.__version__) # 2.0.0
tf.keras.losses.categorical_crossentropy(y_true, y_pred, from_logits = False)
其中y_true代表了One-hot编码后的真实标签,y_pred表示网络的实际预测值:
- 当from_logits设置为True时,y_pred表示未经Softmax函数的输出值;
- 当from_logits设置为False时,y_pred表示为经过Softmax函数后的输出值;
为了在计算Softmax函数时候数值的稳定,一般将from_logits设置为True,此时tf.keras.losses.categorical_crossentropy将在内部进行Softmax的计算,所以在不需要在输出节点上添加Softmax激活函数。
参考资料
- Softmax函数详解与推导
- 一文详解Softmax函数