在深度学习中,使用 Softmax 作为激活函数,对 0 到 1 之间的向量中每个值的输出和尺度进行归一化。Softmax 用于分类任务。在网络的最后一层,会生成一个 N 维向量,分类任务中的每个类对应一个向量。Softmax是给每个输出分类的结果都赋予一个概率值,表示属于每个类别的可能性。计算公式:
其中 z(i)为第i个节点的输出值,C为输出节点的个数,即分类的类别个数。通过Softmax函数就可以将多分类的输出值转换为范围在[0, 1]和为1的概率分布。
softmax引入指数,当z(i)较大时,会导致指数计算超出位宽范围,所以这个公式稳定性比较差。在实际计算时,往往会先求向量Z的各元素中最大的值,然后将各元素减去这个最大值,再做指数运算:
softmax特点:
- 由于指数函数的存在,将负数得分变为正数;
- 归一化:将得分/数值转换为概率,且约束到[0,1]区间;
- 防止溢出:由于softmax的数值稳定性,减去最大值,防止指数函数溢出;
- 突出特征:由于指数函数的存在,导致概率大所对应的类别,在指数作用的加成下会更加明显;
TensorFlow提供同时实现Softmax及其交叉熵损失函数的统一接口。使用TensorFlow深度学习框架的时候,一般推荐使用这个统一的接口,避免分开使用Softmax函数与交叉熵损失函数。
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激活函数。
import tensorflow as tf
print(tf.__version__)
z = tf.random.normal([2, 10]) # 构造2个样本的10类别输出的输出值
y = tf.constant([1, 3]) # 两个样本的真是样本标签是1和3
y_true = tf.one_hot(y, depth = 10) # 构造onehot编码
# 输出层未经过Softmax激活函数,因此讲from_logits设置为True
loss1 = tf.keras.losses.categorical_crossentropy(y_true, z, from_logits = True)
loss1 = tf.reduce_mean(loss1)
print(loss1) # tf.Tensor(2.6680193, shape=(), dtype=float32)
y_pred = tf.nn.softmax(z)
# 输出层经过Softmax激活函数,因此讲from_logits设置为True
loss2 = tf.keras.losses.categorical_crossentropy(y_true, y_pred, from_logits = False)
loss2 = tf.reduce_mean(loss2)
print(loss2) # tf.Tensor(2.668019, shape=(), dtype=float32)
参考: