神经网络每层的激活函数为什么不同
激活函数(Activation Function)在神经网络中扮演着非常重要的角色。它们的作用是通过对输入进行非线性变换,为神经网络引入非线性因素。每一层的激活函数不同,是为了增强网络的表达能力,提高模型的拟合能力。在本文中,我们将介绍为什么神经网络每层的激活函数不同,并通过代码示例进行说明。
1. 线性激活函数的局限性
首先,让我们来看一下为什么不能在每一层都使用线性激活函数。线性激活函数的输出与输入成正比,没有引入非线性变换,因此无法表达复杂的关系和模式。如果每一层都使用线性激活函数,多层神经网络将退化为线性模型,无法处理非线性的问题。
2. 非线性激活函数的必要性
为了引入非线性变换,我们需要使用非线性激活函数。非线性激活函数能够在每一层中对输入进行非线性变换,使得神经网络能够表示更加复杂的函数关系。常见的非线性激活函数包括Sigmoid函数、ReLU函数、Tanh函数等。
3. 各种非线性激活函数的适用场景
不同的非线性激活函数适用于不同的场景,下面我们将介绍几种常见的非线性激活函数及其适用场景。
3.1 Sigmoid函数
Sigmoid函数的公式为:$f(x) = \frac{1}{1 + e^{-x}}$。它将输入值映射到0到1之间,常用于二分类问题的输出层。然而,Sigmoid函数存在梯度消失的问题,即当输入值过大或过小时,梯度接近于0,导致训练过程中网络参数更新缓慢。
3.2 ReLU函数
ReLU函数的公式为:$f(x) = \max(0, x)$。它将负数映射为0,保持正数不变。ReLU函数是目前最常用的激活函数之一,因为它具有简单的计算方式和较好的表达能力。然而,ReLU函数存在一个问题,即神经元死亡现象,当输入值为负数时,梯度为0,导致相应的神经元无法更新。
3.3 Tanh函数
Tanh函数的公式为:$f(x) = \frac{2}{1 + e^{-2x}} - 1$。它将输入值映射到-1到1之间,是Sigmoid函数的变种。Tanh函数在输入值为0附近的变化更加敏感,因此常用于隐藏层的激活函数。
4. 代码示例
下面我们通过代码示例来说明每一层的激活函数为什么不同。
import torch
import torch.nn as nn
# 定义一个两层神经网络
class TwoLayerNet(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(TwoLayerNet, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.fc2 = nn.Linear(hidden_size, output_size)
self.sigmoid = nn.Sigmoid()
self.relu = nn.ReLU()
self.tanh = nn.Tanh()
def forward(self, x):
x = self.fc1(x)
x = self.sigmoid(x) # 第一层使用Sigmoid激活函数
x = self.fc2(x)
x = self.relu(x) # 第二层使用ReLU激活函数
x = self.fc3(x)
x = self.tanh(x) # 第三层使用Tanh激活函数
return x
# 创建一个网络实例
net = TwoLayerNet(10, 20, 5)
# 输入数据
input_data = torch.randn(10