激活函数和损失函数

神经网络中的激活函数和损失函数

图像卷积操作后,接下来是先激活还是先池化,现在存在两种顺序:

  1. 卷积 -> 激活 -> 池化
  2. 卷积 -> 池化 -> 激活

先给出结论:

  • 如果使用最大池化,两种顺序的结果是一样的。
  • 如果使用平均池化,建议采用第1种顺序,即卷积 -> 激活 -> 池化

1. 激活函数(Activation Functions)

激活函数在神经网络中起着至关重要的作用,它们为网络引入非线性特性,使得神经网络能够学习和模拟复杂的非线性关系。没有激活函数,神经网络无论有多少层,都只能表示线性函数,这大大限制了网络的表达能力。

常见的激活函数:
  1. Sigmoid 函数

    • 公式:[ \sigma(x) = \frac{1}{1 + e^{-x}} ]
    • 特点:输出范围在 (0, 1) 之间,可以将输入映射到 (0, 1) 之间的概率值。
    • 应用场景:常用于二分类问题的输出层,也可以用于隐藏层,但容易出现梯度消失问题。
  2. Tanh 函数

    • 公式:[ \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} ]
    • 特点:输出范围在 (-1, 1) 之间,是 Sigmoid 函数的变体,可以将输入映射到 (-1, 1) 之间的值。
    • 应用场景:常用于隐藏层,比 Sigmoid 函数在训练时更稳定,但同样容易出现梯度消失问题。
  3. ReLU 函数(Rectified Linear Unit)

    • 公式:[ \text{ReLU}(x) = \max(0, x) ]
    • 特点:输出范围在 [0, +∞) 之间,计算简单,能够有效缓解梯度消失问题。
    • 应用场景:常用于隐藏层,是目前最常用的激活函数之一。
  4. Leaky ReLU 函数

    • 公式:[ \text{LeakyReLU}(x) = \max(\alpha x, x) ]
    • 特点:输出范围在 (-∞, +∞) 之间,通过引入一个小的斜率 (\alpha)(通常为 0.01),解决了 ReLU 在 (x < 0) 时梯度为零的问题。
    • 应用场景:常用于隐藏层,特别是在 ReLU 出现梯度消失或梯度爆炸问题时。
  5. Softmax 函数

    • 公式:[ \text{Softmax}(x_i) = \frac{e^{x_i}}{\sum_{j=1}^{n} e^{x_j}} ]
    • 特点:输出范围在 (0, 1) 之间,所有输出值的和为 1,可以将输入映射到概率分布。
    • 应用场景:常用于多分类问题的输出层,将 logits 转换为概率分布。

2. 损失函数(Loss Functions)

损失函数用于衡量模型的预测值与真实值之间的差异,是优化神经网络的关键。通过最小化损失函数,可以调整网络的权重和偏置,使模型的预测值尽可能接近真实值。

常见的损失函数:
  1. 均方误差(Mean Squared Error, MSE)

    • 公式:[ \text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 ]
    • 特点:计算预测值与真实值之间的平方差的均值,对异常值敏感。
    • 应用场景:常用于回归问题,例如房价预测、温度预测等。
  2. 均方根误差(Root Mean Squared Error, RMSE)

    • 公式:[ \text{RMSE} = \sqrt{\frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2} ]
    • 特点:计算预测值与真实值之间的平方差的均值的平方根,与原始数据的单位一致,更易于解释。
    • 应用场景:常用于回归问题,特别是在需要与原始数据单位一致的场景中。
  3. 平均绝对误差(Mean Absolute Error, MAE)

    • 公式:[ \text{MAE} = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i| ]
    • 特点:计算预测值与真实值之间的绝对差的均值,对异常值不敏感。
    • 应用场景:常用于回归问题,特别是在数据中存在大量异常值时。
  4. 交叉熵损失(Cross-Entropy Loss)

    • 公式:[ \text{CrossEntropy} = -\sum_{i=1}^{n} y_i \log(\hat{y}_i) ]
    • 特点:计算预测概率分布与真实概率分布之间的交叉熵,对预测值的对数进行求和,对小概率事件的惩罚更大。
    • 应用场景:常用于分类问题,特别是二分类和多分类问题。
  5. 稀疏分类交叉熵损失(Sparse Categorical Cross-Entropy Loss)

    • 公式:[ \text{SparseCrossEntropy} = -\sum_{i=1}^{n} \log(\hat{y}_{i, y_i}) ]
    • 特点:计算预测概率分布与真实标签(整数形式)之间的交叉熵,避免了 one-hot 编码的步骤。
    • 应用场景:常用于多分类问题,特别是标签为整数形式时。
  6. 二元交叉熵损失(Binary Cross-Entropy Loss)

    • 公式:[ \text{BinaryCrossEntropy} = -\frac{1}{n} \sum_{i=1}^{n} [y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i)] ]
    • 特点:计算预测概率与真实标签(0 或 1)之间的交叉熵,对预测值的对数进行求和。
    • 应用场景:常用于二分类问题,例如垃圾邮件检测、疾病诊断等。

3. 关系

  • 输出层的激活函数:在神经网络的输出层,通常会使用特定的激活函数来将 logits 转换为最终的预测值。例如,在二分类问题中,输出层通常使用 Sigmoid 函数;在多分类问题中,输出层通常使用 Softmax 函数。
  • 损失函数的选择:损失函数的选择与输出层的激活函数密切相关。例如,如果输出层使用 Sigmoid 函数,那么损失函数通常选择二元交叉熵损失;如果输出层使用 Softmax 函数,那么损失函数通常选择交叉熵损失或稀疏分类交叉熵损失。

总结

  • 激活函数:引入非线性特性,使神经网络能够学习复杂的非线性关系。常见的激活函数包括 Sigmoid、Tanh、ReLU、Leaky ReLU 和 Softmax。
  • 损失函数:衡量模型的预测值与真实值之间的差异,通过最小化损失函数调整网络的权重和偏置。常见的损失函数包括 MSE、RMSE、MAE、交叉熵损失、稀疏分类交叉熵损失和二元交叉熵损失。

在实际应用中,选择合适的激活函数和损失函数可以显著提高模型的性能和训练效率。

softmax_cross_entropy_with_logits 详解

softmax_cross_entropy_with_logits 是 TensorFlow 中的一个函数,用于计算 softmax 交叉熵损失。这个函数特别适用于多分类问题,其中模型的输出(logits)是未经过 softmax 归一化的值,而真实标签是 one-hot 编码的。这个函数在内部进行了优化,避免了数值不稳定的问题,并且计算效率更高。

1. 函数定义

softmax_cross_entropy_with_logits 函数计算 softmax 交叉熵损失,适用于未归一化的模型输出(logits)和真实标签(one-hot 编码)。

函数签名:

1
tf.nn.softmax_cross_entropy_with_logits(labels, logits, axis=None, name=None)
  • labels: 真实标签,通常是 one-hot 编码的张量,形状为 [batch_size, num_classes]
  • logits: 模型输出,未经过 softmax 归一化的张量,形状为 [batch_size, num_classes]
  • axis: 计算 softmax 的轴,默认为 -1,即最后一个轴。
  • name: 操作的名称,可选参数。

2. 计算过程

  1. Softmax 归一化:首先,对 logits 进行 softmax 归一化,将 logits 转换为概率分布。
    1
    softmax = exp(logits) / sum(exp(logits), axis=axis)
  2. 交叉熵损失:然后,计算 softmax 输出和真实标签之间的交叉熵损失。
    1
    cross_entropy = -sum(labels * log(softmax), axis=axis)

3. 示例代码

以下是一个使用 softmax_cross_entropy_with_logits 的完整示例,包括模型定义、训练和评估。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical

# 加载 MNIST 数据集
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(-1, 784).astype('float32') / 255.0
x_test = x_test.reshape(-1, 784).astype('float32') / 255.0
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)

# 定义输入和标签的占位符
x = tf.placeholder(tf.float32, [None, 784])
y_ = tf.placeholder(tf.float32, [None, 10])

# 定义模型
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
logits = tf.matmul(x, W) + b

# 计算 softmax 交叉熵损失
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=logits)
loss = tf.reduce_mean(cross_entropy)

# 定义优化器
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss)

# 定义评估指标
correct_prediction = tf.equal(tf.argmax(tf.nn.softmax(logits), 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 初始化变量
init = tf.global_variables_initializer()

# 创建会话
with tf.Session() as sess:
sess.run(init)

# 训练模型
for i in range(1000):
batch_xs, batch_ys = x_train[i*100:(i+1)*100], y_train[i*100:(i+1)*100]
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

# 每100轮输出一次训练准确率
if i % 100 == 0:
train_accuracy = sess.run(accuracy, feed_dict={x: batch_xs, y_: batch_ys})
print("Step %d, training accuracy %g" % (i, train_accuracy))

# 评估模型
test_accuracy = sess.run(accuracy, feed_dict={x: x_test, y_: y_test})
print("Test accuracy %g" % test_accuracy)

4. 为什么使用 softmax_cross_entropy_with_logits

  • 数值稳定性:直接使用 softmax_cross_entropy_with_logits 可以避免数值不稳定的问题。在计算 softmax 时,直接使用 explog 可能会导致数值溢出或下溢,而 softmax_cross_entropy_with_logits 内部进行了优化,避免了这些问题。
  • 性能优化softmax_cross_entropy_with_logits 在内部进行了优化,计算效率更高。
  • 简化代码:使用 softmax_cross_entropy_with_logits 可以简化代码,避免手动计算 softmax 和交叉熵损失。

5. 注意事项

  • logits 和 labels 的形状:确保 logitslabels 的形状相同,通常是 [batch_size, num_classes]
  • axis 参数:默认情况下,axis-1,即最后一个轴。如果需要在其他轴上计算 softmax,可以指定 axis 参数。
  • 版本差异:在 TensorFlow 1.x 和 2.x 中,使用方式略有不同。在 TensorFlow 2.x 中,推荐使用 tf.keras.losses.CategoricalCrossentropytf.keras.losses.SparseCategoricalCrossentropy

总结

softmax_cross_entropy_with_logits 是一个非常有用的函数,适用于多分类问题中的损失计算。它不仅数值稳定,而且性能优化,能够简化代码。在实际应用中,确保 logitslabels 的形状一致,并根据需要调整 axis 参数。


激活函数和损失函数
http://blog.uanet.cn/AI/激活函数和损失函数.html
作者
dnsnat
发布于
2025年2月13日
许可协议