Tensorflow2.0之输出层设计

Tensorflow2.0之输出层设计

我们来特别地讨论网络的最后一层的设计,它除了和所有的隐藏层一样,完维度变换、特征提取的功能,还作为输出层使用,需要根据具体的任务场景来定是否使用激活函数,以及使用什么类型的激活函数。

1. 普通实数空间

这一类问题比较普遍,像正弦函数曲线预测、年龄的预测、股票走势的预测等都属于整个或者部分连续的实数空间,输出层可以不加激活函数。误差计算直接基于最后一层的输出𝒐和真实值y 进行计算,如采用均方差误差函数量输出值𝒐与真实值𝒚之间的距离:
ℒ = 𝑔(𝒐, 𝒚)
其中𝑔代表了某个具体的误差计算函数

2.[0,1]区间

输出值属于[0, 1]区间也比较常见,比如图片的生成,二分类问题等。在机学习中,一般会将图片的像素值归一化到[0,1]区间,如果直接使用输出层的值,像素的值范围会分布在整个实数空间。为了让像素的值范围映射到[0,1的有效实数空间,需要在输出层后添加某个合适的激活函数𝜎,其中Sigmoid 函数刚好具有此功能。

同样的,对于二分类问题,如硬币的正反面的预测,输出层可以只需要一节点,表示某个事件A 发生的概率P(𝐴|𝑥)。如果我们把网络的输出o表示正面事件出现的概率,那么反面事件出现的概率即为1 − 𝑜,网络结构如图 所示。

P(正面|𝑥) = 𝑜
P(反面|𝑥) = 1 − 𝑜

在这里插入图片描述
只需要在输出层的净活性值z 后添加Sigmoid 函数即可将输出转译为概率值。
对于二分类问题,除了可以使用单个输出节点表示事件A 发生的概率P(𝐴|𝑥)外,还可以分别预测P(𝐴|𝑥)和P(𝑛𝑜𝑡 𝐴|𝑥),并满足约束

P(𝐴|𝑥) + P(𝑛𝑜𝑡 𝐴|𝑥) = 1
如图 6.14 所示,二分类网络的输出层设置为2 个节点,第一个节点的输出值表示为事件A发生的概率P(𝐴|𝑥),第二个节点的输出值表示非A 即B 事件发生的概率P(𝑛𝑜𝑡 𝐴|𝑥),考虑到Sigmoid 函数只能将单个值压缩到[0,1]区间,并不会考虑2 个节点值之间的关系。我们希望除了满足𝑜𝑖 ∈ [0,1]之外,还希望他们能满足概率之和为1 的约束:

∑ i = 1 o i = 1 \sum\limits_{i=1} o_i =1 i=1oi=1
这种情况就是下面要介绍的问题设定:

3.[0,1]区间,和为1

输出值𝑜𝑖 ∈ [0,1],所有输出值之和为1,这种设定以多分类问题最为常见。输出层的每个输出节点代表了一种类别,图中网络结构用于处理3 分类任务,3 个节点的输出值分布代表了当前样本属于类别A,类别B,类别C 的概率P(A|x), P(B|x), P(C|x),考虑多分类问题中的样本只可能属于所有类别中的某一种,因此满足所有类别概率之和为1 的约束。

如何实现此约束逻辑呢?可以通过在输出层添加Softmax 函数实现Softmax 函数定义为:
在这里插入图片描述
Softmax 函数不仅可以将输出值映射到[0,1]区间,还满足所有的输出值之和为1 的特性。如图中的例子,输出层的输出为[2. ,1. ,0.1],经过Softmax 函数计算后,得到输出为[0.7,0.2,0.1],可以看到每个值代表了当前样本属于每个类别的概率,概率值之和为1。通过Softmax 函数可以将输出层的输出转译为类别概率,在分类问题中使用的非常频繁。

在这里插入图片描述

在这里插入图片描述
在 TensorFlow 中,可以通过tf.nn.softmax 实现Softmax 函数:

In [12]:z = tf.constant([2.,1.,0.1])
tf.nn.softmax(z) # 通过Softmax 函数
Out[12]:
<tf.Tensor: id=19, shape=(3,), dtype=float32, numpy=array([0.6590012,
0.242433 , 0.0985659], dtype=float32)>

与Dense 层类似,Softmax 函数也可以作为网络层类使用,通过类layers.Softmax(axis=-1)可以方便添加Softmax 层,其中axis 参数指定需要进行计算的维度。

在 Softmax 函数的数值计算过程中,容易因输入值偏大发生数值溢出现象;在计算交叉熵时,也会出现数值溢出的问题。为了数值计算的稳定性,TensorFlow 中提供了一个统一的接口,将Softmax 与交叉熵损失函数同时实现,同时也处理了数值不稳定的异常,一般推荐使用,避免单独使用Softmax 函数与交叉熵损失函数。函数式接口为
tf.keras.losses.categorical_crossentropy(y_true, y_pred, from_logits=False)
其中y_true 代表了one-hot 编码后的真实标签,y_pred 表示网络的预测值,当from_logits 设置为True 时,y_pred 表示须为未经过Softmax 函数的变量z;当from_logits 设置为False 时,y_pred 表示为经过Softmax 函数的输出。

In [13]:
z = tf.random.normal([2,10]) # 构造输出层的输出
y_onehot = tf.constant([1,3]) # 构造真实值
y_onehot = tf.one_hot(y_onehot, depth=10) # one-hot 编码
# 输出层未使用Softmax 函数,故from_logits 设置为True
loss = keras.losses.categorical_crossentropy(y_onehot,z,from_logits=True)
loss = tf.reduce_mean(loss) # 计算平均交叉熵损失
loss
Out[13]:
<tf.Tensor: id=210, shape=(), dtype=float32, numpy= 2.4201946>

也可以利用losses.CategoricalCrossentropy(from_logits)类方式同时实现Softmax 与交叉熵损失函数的计算:

In [14]: # 创建Softmax 与交叉熵计算类,输出层的输出z 未使用softmax
criteon = keras.losses.CategoricalCrossentropy(from_logits=True)
loss = criteon(y_onehot,z) # 计算损失
loss
Out[14]:
<tf.Tensor: id=258, shape=(), dtype=float32, numpy= 2.4201946>

4.[-1,1]

如果希望输出值的范围分布在[−1, 1],可以简单地使用tanh 激活函数,实现如下:

In [15]:
x = tf.linspace(-6.,6.,10)
tf.tanh(x) # tanh 激活函数
Out[15]:
<tf.Tensor: id=264, shape=(10,), dtype=float32, numpy=
array([-0.9999877 , -0.99982315, -0.997458 , -0.9640276 , -0.58278286,
0.5827831 , 0.9640276 , 0.997458 , 0.99982315, 0.9999877 ],
dtype=float32)>

输出层的设计具有一定的灵活性,可以根据实际的应用场景自行设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值